Hello Swift Community,

Harlan Haskins and I have been working on libraries 
<https://github.com/trill-lang> 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 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38>.

Cheers,

~Robert Widmann

Test-Only Package Dependencies and Targets

Proposal: SE-NNNN <https://gist.github.com/CodaFi/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Robert Widmann 
<https://github.com/codafi>
Review Manager: TBD
Status: Awaiting review
 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38#introduction>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 
<https://lists.swift.org/pipermail/swift-evolution/>
 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38#motivation>Motivation

Soon after SE-0019 
<https://github.com/apple/swift-evolution/blob/master/proposals/0019-package-manager-testing.md#test-only-dependencies>
 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] 
<https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/.travis.yml#L85>, 
[2] <https://github.com/ReactiveX/RxSwift/blob/master/Package.swift#L3>, [3] 
<https://github.com/Quick/Quick/blob/master/.Package.test.swift>) 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.

 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38#proposed-solution>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.

 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38#detailed-design>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)),
    ]
)
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
 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38#impact-on-existing-code>Impact
 on Existing Code

As this change is purely additive there will be no impact on existing code and 
no impact on existing packages.

 
<https://gist.github.com/CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38#alternatives-considered>Alternatives
 considered

Other names for the parameters to be added to the package manifest are possible.

The new support for executing specific tests could be exposed behind a flag.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to