Skip to content

[6.0] Update package templates to use Swift Testing in the toolchain rather than as a package dependency. #7910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions Fixtures/Miscellaneous/TestDiscovery/SwiftTesting/Package.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
// swift-tools-version: 5.10
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
name: "SwiftTesting",
platforms: [
.macOS(.v13), .iOS(.v16), .watchOS(.v9), .tvOS(.v16), .visionOS(.v1)
],
dependencies: [
.package(url: "https://github.com/apple/swift-testing.git", branch: "main"),
],
targets: [
.testTarget(
name: "SwiftTestingTests",
dependencies: [.product(name: "Testing", package: "swift-testing"),]
),
.testTarget(name: "SwiftTestingTests"),
]
)
12 changes: 7 additions & 5 deletions Sources/Commands/PackageCommands/Init.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ extension SwiftPackageCommand {

let packageName = self.packageName ?? cwd.basename

// Which testing libraries should be used? XCTest is on by default,
// but Swift Testing must remain off by default until it is present
// in the Swift toolchain.
// Testing is on by default, with XCTest only enabled explicitly.
// For macros this is reversed, since we don't support testing
// macros with Swift Testing yet.
var supportedTestingLibraries = Set<BuildParameters.Testing.Library>()
if testLibraryOptions.isEnabled(.xctest) {
if testLibraryOptions.isExplicitlyEnabled(.xctest) ||
(initMode == .macro && testLibraryOptions.isEnabled(.xctest)) {
supportedTestingLibraries.insert(.xctest)
}
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting) {
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting) ||
(initMode != .macro && testLibraryOptions.isEnabled(.swiftTesting)) {
supportedTestingLibraries.insert(.swiftTesting)
}

Expand Down
51 changes: 1 addition & 50 deletions Sources/PackageModelSyntax/AddTarget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@ public struct AddTarget {
// SwiftSyntax.
target.dependencies.append(contentsOf: macroTargetDependencies)

case .test where configuration.testHarness == .swiftTesting:
// Testing targets using swift-testing need to depend on
// SwiftTesting from the swift-testing package.
target.dependencies.append(contentsOf: swiftTestingTestTargetDependencies)

default:
break;
}
Expand Down Expand Up @@ -163,17 +158,6 @@ public struct AddTarget {
}
}

case .test where configuration.testHarness == .swiftTesting:
if !manifest.description.contains("swift-testing") {
newPackageCall = try AddPackageDependency
.addPackageDependencyLocal(
.swiftTesting(
configuration: installedSwiftPMConfiguration
),
to: newPackageCall
)
}

default: break;
}

Expand Down Expand Up @@ -212,8 +196,7 @@ public struct AddTarget {
importModuleNames.append("XCTest")

case .swiftTesting:
// Import is handled by the added dependency.
break
importModuleNames.append("Testing")
}
}

Expand Down Expand Up @@ -380,35 +363,3 @@ fileprivate extension PackageDependency {
)
}
}

/// The set of dependencies we need to introduce to a newly-created macro
/// target.
fileprivate let swiftTestingTestTargetDependencies: [TargetDescription.Dependency] = [
.product(name: "Testing", package: "swift-testing"),
]


/// The package dependency for swift-testing, for use in test files.
fileprivate extension PackageDependency {
/// Source control URL for the swift-syntax package.
static var swiftTestingURL: SourceControlURL {
"https://github.com/apple/swift-testing.git"
}

/// Package dependency on the swift-testing package.
static func swiftTesting(
configuration: InstalledSwiftPMConfiguration
) -> PackageDependency {
let swiftTestingVersionDefault =
configuration.swiftTestingVersionForTestTemplate
let swiftTestingVersion = Version(swiftTestingVersionDefault.description)!

return .sourceControl(
identity: PackageIdentity(url: swiftTestingURL),
nameForTargetDependencyResolutionOnly: nil,
location: .remote(swiftTestingURL),
requirement: .range(.upToNextMajor(from: swiftTestingVersion)),
productFilter: .everything
)
}
}
2 changes: 1 addition & 1 deletion Sources/SPMTestSupport/misc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ extension InitPackage {
public convenience init(
name: String,
packageType: PackageType,
supportedTestingLibraries: Set<BuildParameters.Testing.Library> = [.xctest],
supportedTestingLibraries: Set<BuildParameters.Testing.Library> = [.swiftTesting],
destinationPath: AbsolutePath,
fileSystem: FileSystem
) throws {
Expand Down
51 changes: 21 additions & 30 deletions Sources/Workspace/InitPackage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public final class InitPackage {

public init(
packageType: PackageType,
supportedTestingLibraries: Set<BuildParameters.Testing.Library> = [.xctest],
supportedTestingLibraries: Set<BuildParameters.Testing.Library>,
platforms: [SupportedPlatform] = []
) {
self.packageType = packageType
Expand Down Expand Up @@ -186,8 +186,8 @@ public final class InitPackage {

var platforms = options.platforms

// Macros and swift-testing require macOS 10.15, iOS 13, etc.
if packageType == .macro || options.supportedTestingLibraries.contains(.swiftTesting) {
// Macros require macOS 10.15, iOS 13, etc.
if packageType == .macro {
func addIfMissing(_ newPlatform: SupportedPlatform) {
if platforms.contains(where: { platform in
platform.platform == newPlatform.platform
Expand Down Expand Up @@ -275,9 +275,6 @@ public final class InitPackage {
} else if packageType == .macro {
dependencies.append(#".package(url: "https://github.com/swiftlang/swift-syntax.git", from: "\#(self.installedSwiftPMConfiguration.swiftSyntaxVersionForMacroTemplate.description)")"#)
}
if options.supportedTestingLibraries.contains(.swiftTesting) {
dependencies.append(#".package(url: "https://github.com/apple/swift-testing.git", from: "0.11.0")"#)
}
if !dependencies.isEmpty {
let dependencies = dependencies.map { dependency in
" \(dependency),"
Expand Down Expand Up @@ -384,17 +381,7 @@ public final class InitPackage {
"""
} else {
let testTarget: String
if options.supportedTestingLibraries.contains(.swiftTesting) {
testTarget = """
.testTarget(
name: "\(pkgname)Tests",
dependencies: [
"\(pkgname)",
.product(name: "Testing", package: "swift-testing"),
]
),
"""
} else if options.supportedTestingLibraries.contains(.xctest) {
if !options.supportedTestingLibraries.isEmpty {
testTarget = """
.testTarget(
name: "\(pkgname)Tests",
Expand Down Expand Up @@ -687,6 +674,10 @@ public final class InitPackage {
private func writeLibraryTestsFile(_ path: AbsolutePath) throws {
var content = ""

// XCTest is only added if it was explicitly asked for, so add tests
// for it *and* Testing if it is enabled (or just XCTest if Testing
// is explicitly disabled).

if options.supportedTestingLibraries.contains(.swiftTesting) {
content += "import Testing\n"
}
Expand All @@ -695,20 +686,18 @@ public final class InitPackage {
}
content += "@testable import \(moduleName)\n"

// Prefer swift-testing if specified, otherwise XCTest. If both are
// specified, the developer is free to write tests using both
// libraries, but we still only want to present a single library's
// example tests.

if options.supportedTestingLibraries.contains(.swiftTesting) {
content += """

@Test func example() throws {
// swift-testing Documentation
// https://swiftpackageindex.com/apple/swift-testing/main/documentation/testing
@Test func example() async throws {
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
}

"""
} else if options.supportedTestingLibraries.contains(.xctest) {
}

if options.supportedTestingLibraries.contains(.xctest) {
content += """

final class \(moduleName)Tests: XCTestCase {
Expand Down Expand Up @@ -761,13 +750,15 @@ public final class InitPackage {

"""##

// Prefer swift-testing if specified, otherwise XCTest. If both are
// specified, the developer is free to write tests using both
// libraries, but we still only want to present a single library's
// example tests.

// XCTest is only added if it was explicitly asked for, so add tests
// for it *and* Testing if it is enabled.

if options.supportedTestingLibraries.contains(.swiftTesting) {
// FIXME: https://github.com/swiftlang/swift-syntax/issues/2400
} else if options.supportedTestingLibraries.contains(.xctest) {
}

if options.supportedTestingLibraries.contains(.xctest) {
content += ##"""
final class \##(moduleName)Tests: XCTestCase {
func testMacro() throws {
Expand Down
18 changes: 18 additions & 0 deletions Tests/CommandsTests/TestCommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,28 @@ final class TestCommandTests: CommandsTestCase {
}

func testBasicSwiftTestingIntegration() async throws {
#if !canImport(Testing)
try XCTSkipUnless(
nil != Environment.current["SWIFT_PM_SWIFT_TESTING_TESTS_ENABLED"],
"Skipping \(#function) because swift-testing tests are not explicitly enabled"
)
#endif

try await fixture(name: "Miscellaneous/TestDiscovery/SwiftTesting") { fixturePath in
do {
let (stdout, _) = try await SwiftPM.Test.execute(["--enable-swift-testing", "--disable-xctest"], packagePath: fixturePath)
XCTAssertMatch(stdout, .contains(#"Test "SOME TEST FUNCTION" started"#))
}
}
}

func testBasicSwiftTestingIntegration_ExperimentalFlag() async throws {
#if !canImport(Testing)
try XCTSkipUnless(
nil != Environment.current["SWIFT_PM_SWIFT_TESTING_TESTS_ENABLED"],
"Skipping \(#function) because swift-testing tests are not explicitly enabled"
)
#endif

try await fixture(name: "Miscellaneous/TestDiscovery/SwiftTesting") { fixturePath in
do {
Expand Down
16 changes: 5 additions & 11 deletions Tests/PackageModelSyntaxTests/ManifestEditTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -575,14 +575,8 @@ class ManifestEditTests: XCTestCase {
// swift-tools-version: 5.5
let package = Package(
name: "packages",
dependencies: [
.package(url: "https://github.com/apple/swift-testing.git", from: "0.8.0"),
],
targets: [
.testTarget(
name: "MyTest",
dependencies: [ .product(name: "Testing", package: "swift-testing") ]
),
.testTarget(name: "MyTest"),
]
)
""",
Expand Down Expand Up @@ -618,7 +612,7 @@ class ManifestEditTests: XCTestCase {
let package = Package(
name: "packages",
dependencies: [
.package(url: "https://github.com/apple/swift-testing.git", from: "0.8.0"),
.package(url: "https://github.com/swiftlang/swift-example.git", from: "1.2.3"),
],
targets: [
.testTarget(
Expand All @@ -632,20 +626,20 @@ class ManifestEditTests: XCTestCase {
let package = Package(
name: "packages",
dependencies: [
.package(url: "https://github.com/apple/swift-testing.git", from: "0.8.0"),
.package(url: "https://github.com/swiftlang/swift-example.git", from: "1.2.3"),
],
targets: [
.testTarget(
name: "MyTest",
dependencies: [
.product(name: "Testing", package: "swift-testing"),
.product(name: "SomethingOrOther", package: "swift-example"),
]
),
]
)
""") { manifest in
try AddTargetDependency.addTargetDependency(
.product(name: "Testing", package: "swift-testing"),
.product(name: "SomethingOrOther", package: "swift-example"),
targetName: "MyTest",
to: manifest
)
Expand Down
Loading