[swift-evolution] [Draft] Test-Only Package Dependencies and Targets

Robert Widmann devteam.codafi at gmail.com
Mon Jan 30 12:27:29 CST 2017



~Robert Widmann

2017/01/26 4:11、Ankit Agarwal <ankit at ankit.im> のメッセージ:

> 
> 
>> On Thu, Jan 26, 2017 at 1:55 PM, Robert Widmann via swift-evolution <swift-evolution at swift.org> wrote:
>> Three parts for three points:
>> 
>> 1) Thanks!
>> 
>> 2) I'm not sure generalizing this is particularly useful post-products.  The larger point is not to have non-exported/local target dependencies but to make clear the divide between a package and its test suite in the manifest as well as on disk.  Local dependencies seem like a separate proposal entirely.
> 
> We do have a clear divide between normal modules and test modules. 
> I am not sure adding a special case test dependencies makes sense right now. We might end up having conditional dependencies later w.r.t platform and other parameters.
> 

Not in practice (with respect to package manifests). In fact, it seems that, given there are separate commands (swift build and swift test), separate directories (Sources and Tests), and separate products, that there's a hole to be filled here by separate handling for test suites in package manifests.

This is all not to discount the features you've brought up as well, but I'm having trouble seeing why a distinction here is such a problem.

> Daniel, do you want to pitch in? 
> 
>> 3) Wow, I honestly should have noticed this: I took the time to peruse the source for the help text and still managed to miss it.  It has been struck from the gist of this proposal.
>> 
>> ~Robert Widmann
>> 
>> 2017/01/25 3:07、Ankit Aggarwal <ankit_aggarwal at apple.com> のメッセージ:
>> 
>>> 
>>>> On 25-Jan-2017, at 4:02 AM, Robert Widmann via swift-evolution <swift-evolution at swift.org> wrote:
>>>> 
>>>> Hello Swift Community,
>>>> 
>>>> Harlan Haskins and I have been working on libraries to make interacting with LLVM and Clang’s APIs more elegant with native Swift interfaces.  While writing up the packages we realized the package manager wouldn’t allow us to specify testing targets and test-only dependencies.  To rectify that, I have attached a draft proposal for adding test-only targets and dependency fields to the Swift Package manager.  This proposal can also be read in gist form.
>>>> 
>>>> Cheers,
>>>> 
>>>> ~Robert Widmann
>>>> 
>>> 
>>> Thanks for driving this! It is a very desirable feature which needs proposal work. Comments inline.
>>> 
>>> 
>>> 
>>>> Test-Only Package Dependencies and Targets
>>>> Proposal: SE-NNNN
>>>> Authors: Harlan Haskins, Robert Widmann
>>>> Review Manager: TBD
>>>> Status: Awaiting review
>>>> Introduction
>>>> 
>>>> This proposal reinstates Swift package manager’s ability to fetch dependencies and build targets scoped exclusively to the testing module(s) of a given package.
>>>> 
>>>> Swift-evolution thread: Discussion thread topic for that proposal
>>>> 
>>>> Motivation
>>>> 
>>>> Soon after SE-0019 identified the need for richer test-only dependencies and targets, a decision was made to remove the package manager’s fledgling ability to treat certain dependencies as test-only. This has led to a myriad of clever-but-needlessly-complex workarounds ([1], [2], [3]) on the part of 3rd parties to recover the feature themselves. In addition, the Swift community has come up with a number of their own frameworks to augment functionality in XCTest but depending on these external testing frameworks is brittle and difficult to get right.
>>>> 
>>>> Proposed solution
>>>> 
>>>> We propose the re-introduction of the testDependencies parameter in Package Manifests to support external test-only dependencies. To support local test-only targets we also propose the introduction of the testTargets parameter and an extension of the existing swift test command to support individual invocation of these targets.
>>>> 
>>>> Detailed design
>>>> 
>>>> The behavior of the new testDependencies parameter mirrors that of the existing dependencies parameter with one important difference: fetched dependencies are only built to support package-defined test targets as part of an invocation of swift test.
>>>> 
>>>> import PackageDescription
>>>> 
>>>> let package = Package(
>>>>     name: "Foo",
>>>>     targets: [
>>>>         Target(name: "Foo")
>>>>     ],
>>>>     dependencies: [
>>>>         .Package(url: "https://github.com/org/ana.git", versions: Version(1,0,0)...Version(1,9,9)),
>>>>     ],
>>>>     testDependencies: [
>>>>         .Package(url: "https://github.com/org/anism.git", versions: Version(1,0,0)...Version(1,9,9)),
>>>>     ]
>>>> )
>>> 
>>> I think this feature should be called local dependencies (or maybe dev dependencies) because it can be used for tests as well as regular targets. 
>>> As an example say you have a networking library package and you want to create an example CLI target which uses a JSON mapper package. You wouldn't want to vend the CLI tool when you act as a dependency to other packages, or include the JSON mapper in your dependencies. Test dependency doesn't sound right in that context.
>>> 
>>> After the product proposal is implemented, you will be able to control what you vend to your clients, and we thought about adding ability to define dependencies in-line with target dependencies but left it out of the proposal to keep it simpler. Maybe this proposal can add that instead of a separate `testDependencies` property. Consider this manifest:
>>> 
>>> let package = Package(
>>>     name: "FooNetworking",
>>>     targets: [
>>>         Target(
>>>             name: "FooNetworking"),
>>>         Target(
>>>             name: "FooNetworkingExample",
>>>             dependencies: [
>>>                 "FooNetworking", 
>>>                 .package(url: "/path/to/BarJSON.git", version: "1.0.0", product: "BarJSON"), // Note: This doesn't actually exists right now.
>>>             ]),
>>>         Target(
>>>             name: "FooNetworkingTests",
>>>             dependencies: [
>>>                 "FooNetworking", 
>>>                 .package(url: "/path/to/Quick.git", version: "1.0.0", product: "Quick"), // Note: This doesn't actually exists right now.
>>>             ]),
>>>    ],
>>>    products: [
>>>        .Library(name: "FooNetworking", targets: ["FooNetworking"]),
>>>    ]
>>> )
>>> 
>>> This manifest defines three targets and one product.
>>> 
>>> FooNetworking: The base target and the actual library.
>>> FooNetworkingExample: The example cli tool. It depends on FooNetworking target and BarJSON product from an external package.
>>> FooNetworkingTests: The test target depends on an external package Quick.
>>> 
>>> Both BarJSON and Quick are local dependencies to this package. If FooNetworkingExample was also vended as a product, BarJSON would automatically become a regular external dependency.
>>> 
>>>> Similarly, the behavior of the testTargets field mirrors that of the existing targets field but defines a set of targets that are only built during an invocation of swift test. Importantly, a target defined in testTargets may reference a target defined in targets but not vice-versa. Should that behavior be needed, the test target should be promoted to a “full” target.
>>>> 
>>>> import PackageDescription
>>>> 
>>>> let package = Package(
>>>>     name: "SwiftPM",
>>>>     targets: [
>>>>         Target(
>>>>             name: "PackageDescription",
>>>>             dependencies: []),
>>>> 
>>>>         // MARK: Support libraries
>>>> 
>>>>         Target(
>>>>             /** Cross-platform access to bare `libc` functionality. */
>>>>             name: "libc",
>>>>             dependencies: []),
>>>>         Target(
>>>>             /** “Swifty” POSIX functions from libc */
>>>>             name: "POSIX",
>>>>             dependencies: ["libc"]),
>>>>         Target(
>>>>             /** Basic support library */
>>>>             name: "Basic",
>>>>             dependencies: ["libc", "POSIX"]),
>>>> 
>>>>         /* Omitted for Brevity */
>>>>      ],
>>>>      testTargets: [
>>>>         Target(
>>>>             name: "BasicPerformanceTests",
>>>>             dependencies: ["Basic"]),
>>>>        /* Omitted for Brevity */
>>>>      ]
>>>>  )
>>>> Finally, with well-defined test targets in hand, we propose swift test be amended to support individual test execution.
>>>> 
>>>> 
>>>> We propose the following syntax to execute all tests of all known test targets.
>>>> 
>>>> $ swift test
>>>> To run a set of specific test cases, reference the module-defining test target and the specific name of a subclass of XCTestCase:
>>>> 
>>>> $ swift test TestModule.TestCase
>>>> To run an individual test case, reference the module-defining test target, the name of the test case subclass, and the name of the test:
>>>> 
>>>> $ swift test TestModule.TestCase.exampleTest
>>> 
>>> We already have all these features. A target is a test target if it has a suffix Tests and is placed under Tests/ directory ― we might loosen these restrictions with custom target conventions feature. This proposal could clarify further.
>>> 
>>> Here is a summary of what `swift test` currently supports:
>>> * Test targets are only built (and run) when you run `swift test`.
>>> * `swift test --skip-build` skips building of test targets and runs whatever was last built.
>>> * `swift test -s <test-module>.<test-case>` will run a test case class.
>>> * `swift test -s <test-module>.<test-case>/<test>` will run an individual test.
>>> * `swift test --list-tests` will list all tests in above format.
>>> * `swift test --parallel` will run tests in parallel.
>>> 
>>> You can view these options and their help text using `swift test --help`.
>>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
> 
> 
> -- 
> Ankit
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170130/6ed97904/attachment.html>


More information about the swift-evolution mailing list