Skip to content

Instantly share code, notes, and snippets.

@CodaFi
Last active January 26, 2017 08:26
Show Gist options
  • Save CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38 to your computer and use it in GitHub Desktop.
Save CodaFi/6bd83e5315c7d30aeaf4154ed3b03a38 to your computer and use it in GitHub Desktop.

Test-Only Package Dependencies and Targets

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

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.

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 */
     ]
 )

Impact on Existing Code

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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment