<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I’ve been working on getting Siesta up and running with SwiftPM, and have hit snags running the tests. At Ankit Aggarwal’s encouragement, I’m opening a discussion thread here.<div class=""><br class=""></div><div class="">By “test-only dependencies,” I mean external packages required by a package’s tests, but not by the package's exported targets. For example, Siesta’s tests depend on Quick, Nimble, and Nocilla, but apps that use Siesta should not have to build those dependencies and would very much not want them baked into the resulting binary.</div><div class=""><br class=""></div><div class="">Proper support for test-only dependencies would have three essential features:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">They are not downloaded or built by “swift build,” but <i class="">are</i> downloaded and built by “swift test.”</li><li class="">Any modules they define do not end up in the compiled binary, and are not available for the package’s non-test targets to import.</li><li class="">A package ignores the test-only dependencies of its dependencies.</li></ul><div class=""><br class=""></div></div><div class="">Those are the essentials. Also nice to have:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">The ability to limit test-only dependencies to specific test modules (e.g. an integration test module might pull in some heavyweight context that isn’t necessary or desirable for basic regression tests).</li><li class="">The ability to import / run tests defined in an external module. (Probably a separate discussion.)</li></ul></div><div class=""><br class=""></div><div class="">To open the discussion, I see three general approaches:</div><div class=""><br class=""></div><div class=""><b class="">Approach 1: Special testDependencies attribute</b></div><div class=""><b class=""><br class=""></b></div><div class="">It looks like SwiftPM flirted with this, then abandoned it?</div><div class=""><br class=""></div><div class="">Pros: Clear.</div><div class=""><br class=""></div><div class="">Cons: Creates (another) special exception for tests. Doesn’t obviously generalize to handle the “specific test modules” nice-to-have above.</div><div class=""><br class=""></div><div class=""><b class="">Approach 2: Per-target external dependencies</b></div><div class=""><br class=""></div><div class="">SwiftPM could allow individual targets to specify external dependencies, something like this:</div><div class=""><br class=""></div><div class=""><div class=""> targets: [</div><div class=""> Target(</div><div class=""> name: "SiestaTests",</div><div class=""> dependencies: [</div><div class=""> .Package(url: "<a href="https://github.com/Quick/Quick" class="">https://github.com/Quick/Quick</a>", majorVersion: 0)</div><div class=""> ])</div><div class=""> ],</div><div class=""><br class=""></div></div><div class="">Pros: Covers the “essential features” above in a way that generalizes nicely to other interesting use cases beside testing.</div><div class=""><br class=""></div><div class="">Cons: Requires redundant dependency declarations across test targets.</div><div class=""><br class=""></div><div class=""><b class="">Approach 3: Target groups</b></div><div class=""><br class=""></div><div class=""><div class="">Bundler provides arbitrary logical gem groupings, which Rails uses to isolate dependencies to development, test, and/or production environments. For example:</div></div><div class=""><br class=""></div><div class=""><div class=""><div class=""> group :<b class="">development</b>, :<b class="">test </b>do</div><div class=""> gem 'byebug'</div><div class=""> gem 'spring'</div><div class=""> end</div><div class=""><br class=""></div><div class=""> group :<b class="">test </b>do</div><div class=""> gem 'minitest-spec-rails'</div><div class=""> gem 'factory_girl_rails'</div><div class=""> end</div><div class=""><br class=""></div><div class=""> group :<b class="">development</b></div><div class=""> gem 'letter_opener'</div><div class=""> end</div><div class=""><br class=""></div><div class=""> group :<b class="">production</b></div><div class=""> gem 'puma'</div><div class=""> end</div></div></div><div class=""><br class=""></div><div class="">Apps can then decide which groups to include depending on their runtime environment.</div><div class=""><br class=""></div><div class="">Pros: Gives the clarity & conciseness of #1 with the generality benefits of #2.</div><div class=""><br class=""></div><div class="">Cons: Lots of additional structure here, both explicit and implicit. Not clear how useful this would be in SwiftPM: because Ruby is so dynamic, <i class="">all</i> dependencies are runtime dependencies, so code can decide whether it’s “in test mode” or “in production” before looking for modules. In SwiftPM, all dependencies are <i class="">compile-time</i> dependencies, so arbitrary logical groups lose the benefits that come with runtime resolution.</div><div class=""><br class=""></div><div class="">________</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">I’m throwing all of this out there in a state of general ignorance about SwiftPM’s direction and status. Hopefully it spurs some useful discussion.</div><div class=""><br class=""></div><div class="">Cheers,</div><div class=""><br class=""></div><div class="">Paul</div><div class=""><br class=""></div></body></html>