Skip to content

Suppress Swift Testing invocation when XCTMain.swift or LinuxMain.swift is present. #7787

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

Closed
Closed
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
3 changes: 2 additions & 1 deletion Sources/Build/LLBuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ public struct BuildDescription: Codable {
try BuiltTestProduct(
productName: desc.product.name,
binaryPath: desc.binaryPath,
packagePath: desc.package.path
packagePath: desc.package.path,
testEntryPointPath: desc.product.underlying.testEntryPointPath
)
}
self.pluginDescriptions = pluginDescriptions
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/PackageCommands/Init.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ extension SwiftPackageCommand {
if testLibraryOptions.isEnabled(.xctest) {
supportedTestingLibraries.insert(.xctest)
}
if testLibraryOptions.explicitlyEnableSwiftTestingLibrarySupport == true || testLibraryOptions.explicitlyEnableExperimentalSwiftTestingLibrarySupport == true {
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting) == true {
supportedTestingLibraries.insert(.swiftTesting)
}

Expand Down
70 changes: 44 additions & 26 deletions Sources/Commands/SwiftTestCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,24 @@ public struct SwiftTestCommand: AsyncSwiftCommand {

// Run Swift Testing (parallel or not, it has a single entry point.)
if options.testLibraryOptions.isEnabled(.swiftTesting) {
results.append(
try await runTestProducts(
testProducts,
additionalArguments: [],
productsBuildParameters: buildParameters,
swiftCommandState: swiftCommandState,
library: .swiftTesting
if let explicitlyEnabled = options.testLibraryOptions.isExplicitlyEnabled(.swiftTesting),
explicitlyEnabled,
let testEntryPointPath = testProducts.lazy.compactMap(\.testEntryPointPath).first {
// Cannot run Swift Testing because an entry point file was used.
swiftCommandState.observabilityScope.emit(
debug: "Skipping automatic Swift Testing invocation because a test entry point path is present: \(testEntryPointPath)"
)
)
} else {
results.append(
try await runTestProducts(
testProducts,
additionalArguments: [],
productsBuildParameters: buildParameters,
swiftCommandState: swiftCommandState,
library: .swiftTesting
)
)
}
}

switch results.reduce() {
Expand Down Expand Up @@ -725,25 +734,34 @@ extension SwiftTestCommand {
}

if testLibraryOptions.isEnabled(.swiftTesting) {
let additionalArguments = ["--list-tests"] + CommandLine.arguments.dropFirst()
let runner = TestRunner(
bundlePaths: testProducts.map(\.binaryPath),
additionalArguments: additionalArguments,
cancellator: swiftCommandState.cancellator,
toolchain: toolchain,
testEnv: testEnv,
observabilityScope: swiftCommandState.observabilityScope,
library: .swiftTesting
)
if let explicitlyEnabled = testLibraryOptions.isExplicitlyEnabled(.swiftTesting),
explicitlyEnabled,
let testEntryPointPath = testProducts.lazy.compactMap(\.testEntryPointPath).first {
// Cannot run Swift Testing because an entry point file was used.
swiftCommandState.observabilityScope.emit(
debug: "Skipping automatic Swift Testing invocation (list) because a test entry point path is present: \(testEntryPointPath)"
)
} else {
let additionalArguments = ["--list-tests"] + CommandLine.arguments.dropFirst()
let runner = TestRunner(
bundlePaths: testProducts.map(\.binaryPath),
additionalArguments: additionalArguments,
cancellator: swiftCommandState.cancellator,
toolchain: toolchain,
testEnv: testEnv,
observabilityScope: swiftCommandState.observabilityScope,
library: .swiftTesting
)

// Finally, run the tests.
let result = runner.test(outputHandler: {
// command's result output goes on stdout
// ie "swift test" should output to stdout
print($0, terminator: "")
})
if result == .failure {
swiftCommandState.executionStatus = .failure
// Finally, run the tests.
let result = runner.test(outputHandler: {
// command's result output goes on stdout
// ie "swift test" should output to stdout
print($0, terminator: "")
})
if result == .failure {
swiftCommandState.executionStatus = .failure
}
}
}
}
Expand Down
16 changes: 12 additions & 4 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -597,16 +597,24 @@ public struct TestLibraryOptions: ParsableArguments {
help: .private)
public var explicitlyEnableExperimentalSwiftTestingLibrarySupport: Bool?

/// Test whether or not a given library is enabled.
public func isEnabled(_ library: BuildParameters.Testing.Library) -> Bool {
/// Test whether or not a given library was explicitly enabled by the developer.
///
/// If the developer did not specify either way, the result is `nil`.
public func isExplicitlyEnabled(_ library: BuildParameters.Testing.Library) -> Bool? {
switch library {
case .xctest:
explicitlyEnableXCTestSupport ?? true
explicitlyEnableXCTestSupport
case .swiftTesting:
explicitlyEnableSwiftTestingLibrarySupport ?? explicitlyEnableExperimentalSwiftTestingLibrarySupport ?? true
explicitlyEnableSwiftTestingLibrarySupport ?? explicitlyEnableExperimentalSwiftTestingLibrarySupport
}
}

/// Test whether or not a given library is enabled.
public func isEnabled(_ library: BuildParameters.Testing.Library) -> Bool {
// Both libraries are enabled by default.
isExplicitlyEnabled(library) ?? true
}

/// The list of enabled testing libraries.
public var enabledTestingLibraries: [BuildParameters.Testing.Library] {
[.xctest, .swiftTesting].filter(isEnabled)
Expand Down
8 changes: 7 additions & 1 deletion Sources/SPMBuildCore/BuiltTestProduct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,20 @@ public struct BuiltTestProduct: Codable {
return bundlePath
}

/// The path to the entry point source file (XCTMain.swift, LinuxMain.swift,
/// etc.) used, if any.
public let testEntryPointPath: AbsolutePath?

/// Creates a new instance.
/// - Parameters:
/// - productName: The test product name.
/// - binaryPath: The path of the test binary.
/// - packagePath: The path to the package this product was declared in.
public init(productName: String, binaryPath: AbsolutePath, packagePath: AbsolutePath) {
/// - mainSourceFilePath: The path to the main source file used, if any.
public init(productName: String, binaryPath: AbsolutePath, packagePath: AbsolutePath, testEntryPointPath: AbsolutePath?) {
self.productName = productName
self.binaryPath = binaryPath
self.packagePath = packagePath
self.testEntryPointPath = testEntryPointPath
}
}
3 changes: 2 additions & 1 deletion Sources/XCBuildSupport/XcodeBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
BuiltTestProduct(
productName: product.name,
binaryPath: binaryPath,
packagePath: package.path
packagePath: package.path,
testEntryPointPath: product.underlying.testEntryPointPath
)
)
}
Expand Down