Skip to content

Tests: Do not use mix of XCTest and Swift Testing #8942

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
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
100 changes: 95 additions & 5 deletions Sources/_InternalTestSupport/misc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import SPMBuildCore
import struct SPMBuildCore.BuildParameters
import TSCTestSupport
import Workspace
import Testing
import func XCTest.XCTFail
import struct XCTest.XCTSkip

Expand Down Expand Up @@ -112,7 +113,8 @@ public func testWithTemporaryDirectory<Result>(
/// The temporary copy is deleted after the block returns. The fixture name may
/// contain `/` characters, which are treated as path separators, exactly as if
/// the name were a relative path.
@discardableResult public func fixture<T>(
@available(*, deprecated, message: "Migrate test to Swift Testing and use 'fixture' instead")
@discardableResult public func fixtureXCTest<T>(
name: String,
createGitRepo: Bool = true,
file: StaticString = #file,
Expand All @@ -133,7 +135,44 @@ public func testWithTemporaryDirectory<Result>(
try? localFileSystem.removeFileTree(tmpDirPath)
}

let fixtureDir = try verifyFixtureExists(at: fixtureSubpath, file: file, line: line)
let fixtureDir = try verifyFixtureExistsXCTest(at: fixtureSubpath, file: file, line: line)
let preparedFixture = try setup(
fixtureDir: fixtureDir,
in: tmpDirPath,
copyName: copyName,
createGitRepo:createGitRepo
)
return try body(preparedFixture)
}
} catch SwiftPMError.executionFailure(let error, let output, let stderr) {
print("**** FAILURE EXECUTING SUBPROCESS ****")
print("output:", output)
print("stderr:", stderr)
throw error
}
}

@discardableResult public func fixture<T>(
name: String,
createGitRepo: Bool = true,
sourceLocation: SourceLocation = #_sourceLocation,
body: (AbsolutePath) throws -> T
) throws -> T {
do {
// Make a suitable test directory name from the fixture subpath.
let fixtureSubpath = try RelativePath(validating: name)
let copyName = fixtureSubpath.components.joined(separator: "_")

// Create a temporary directory for the duration of the block.
return try withTemporaryDirectory(prefix: copyName) { tmpDirPath in

defer {
// Unblock and remove the tmp dir on deinit.
try? localFileSystem.chmod(.userWritable, path: tmpDirPath, options: [.recursive])
try? localFileSystem.removeFileTree(tmpDirPath)
}

let fixtureDir = try verifyFixtureExists(at: fixtureSubpath, sourceLocation: sourceLocation)
let preparedFixture = try setup(
fixtureDir: fixtureDir,
in: tmpDirPath,
Expand All @@ -154,7 +193,8 @@ public enum TestError: Error {
case platformNotSupported
}

@discardableResult public func fixture<T>(
@available(*, deprecated, message: "Migrate test to Swift Testing and use 'fixture' instead")
@discardableResult public func fixtureXCTest<T>(
name: String,
createGitRepo: Bool = true,
file: StaticString = #file,
Expand All @@ -175,7 +215,7 @@ public enum TestError: Error {
try? localFileSystem.removeFileTree(tmpDirPath)
}

let fixtureDir = try verifyFixtureExists(at: fixtureSubpath, file: file, line: line)
let fixtureDir = try verifyFixtureExistsXCTest(at: fixtureSubpath, file: file, line: line)
let preparedFixture = try setup(
fixtureDir: fixtureDir,
in: tmpDirPath,
Expand All @@ -192,7 +232,44 @@ public enum TestError: Error {
}
}

fileprivate func verifyFixtureExists(at fixtureSubpath: RelativePath, file: StaticString = #file, line: UInt = #line) throws -> AbsolutePath {
@discardableResult public func fixture<T>(
name: String,
createGitRepo: Bool = true,
sourceLocation: SourceLocation = #_sourceLocation,
body: (AbsolutePath) async throws -> T
) async throws -> T {
do {
// Make a suitable test directory name from the fixture subpath.
let fixtureSubpath = try RelativePath(validating: name)
let copyName = fixtureSubpath.components.joined(separator: "_")

// Create a temporary directory for the duration of the block.
return try await withTemporaryDirectory(prefix: copyName) { tmpDirPath in

defer {
// Unblock and remove the tmp dir on deinit.
try? localFileSystem.chmod(.userWritable, path: tmpDirPath, options: [.recursive])
try? localFileSystem.removeFileTree(tmpDirPath)
}

let fixtureDir = try verifyFixtureExists(at: fixtureSubpath, sourceLocation: sourceLocation)
let preparedFixture = try setup(
fixtureDir: fixtureDir,
in: tmpDirPath,
copyName: copyName,
createGitRepo:createGitRepo
)
return try await body(preparedFixture)
}
} catch SwiftPMError.executionFailure(let error, let output, let stderr) {
print("**** FAILURE EXECUTING SUBPROCESS ****")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: we should also consider dumping out the command line arguments.

print("output:", output)
print("stderr:", stderr)
throw error
}
}

fileprivate func verifyFixtureExistsXCTest(at fixtureSubpath: RelativePath, file: StaticString = #file, line: UInt = #line) throws -> AbsolutePath {
let fixtureDir = AbsolutePath("../../../Fixtures", relativeTo: #file)
.appending(fixtureSubpath)

Expand All @@ -205,6 +282,19 @@ fileprivate func verifyFixtureExists(at fixtureSubpath: RelativePath, file: Stat
return fixtureDir
}

fileprivate func verifyFixtureExists(at fixtureSubpath: RelativePath, sourceLocation: SourceLocation = #_sourceLocation) throws -> AbsolutePath {
let fixtureDir = AbsolutePath("../../../Fixtures", relativeTo: #file)
.appending(fixtureSubpath)

// Check that the fixture is really there.
guard localFileSystem.isDirectory(fixtureDir) else {
Issue.record("No such fixture: \(fixtureDir)", sourceLocation: sourceLocation)
throw SwiftPMError.packagePathNotFound
}

return fixtureDir
}

fileprivate func setup(
fixtureDir: AbsolutePath,
in tmpDirPath: AbsolutePath,
Expand Down
6 changes: 3 additions & 3 deletions Tests/BuildTests/BuildPlanTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
toolchain: UserToolchain.default,
fileSystem: localFileSystem
)
try await fixture(name: "Miscellaneous/PackageNameFlag") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in
let (stdout, stderr) = try await executeSwiftBuild(
fixturePath.appending("appPkg"),
extraArgs: ["--vv"],
Expand Down Expand Up @@ -666,7 +666,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
toolchain: UserToolchain.default,
fileSystem: localFileSystem
)
try await fixture(name: "Miscellaneous/PackageNameFlag") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in
let (stdout, _) = try await executeSwiftBuild(
fixturePath.appending("appPkg"),
extraArgs: ["--vv"],
Expand Down Expand Up @@ -697,7 +697,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
toolchain: UserToolchain.default,
fileSystem: localFileSystem
)
try await fixture(name: "Miscellaneous/TargetPackageAccess") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/TargetPackageAccess") { fixturePath in
let (stdout, _) = try await executeSwiftBuild(
fixturePath.appending("libPkg"),
extraArgs: ["-v"],
Expand Down
4 changes: 2 additions & 2 deletions Tests/BuildTests/BuildSystemDelegateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import var TSCBasic.localFileSystem
final class BuildSystemDelegateTests: XCTestCase {
func testDoNotFilterLinkerDiagnostics() async throws {
try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")
try await fixture(name: "Miscellaneous/DoNotFilterLinkerDiagnostics") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/DoNotFilterLinkerDiagnostics") { fixturePath in
#if !os(macOS)
// These linker diagnostics are only produced on macOS.
try XCTSkipIf(true, "test is only supported on macOS")
Expand All @@ -39,7 +39,7 @@ final class BuildSystemDelegateTests: XCTestCase {
#else
let executableExt = ""
#endif
try await fixture(name: "Miscellaneous/TestableExe") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/TestableExe") { fixturePath in
_ = try await executeSwiftBuild(fixturePath)
let execPath = fixturePath.appending(components: ".build", "debug", "TestableExe1\(executableExt)")
XCTAssertTrue(localFileSystem.exists(execPath), "executable not found at '\(execPath)'")
Expand Down
8 changes: 4 additions & 4 deletions Tests/BuildTests/IncrementalBuildTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class IncrementalBuildTests: XCTestCase {

func testIncrementalSingleModuleCLibraryInSources() async throws {
try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")
try await fixture(name: "CFamilyTargets/CLibrarySources") { fixturePath in
try await fixtureXCTest(name: "CFamilyTargets/CLibrarySources") { fixturePath in
// Build it once and capture the log (this will be a full build).
let (fullLog, _) = try await executeSwiftBuild(fixturePath)

Expand Down Expand Up @@ -98,7 +98,7 @@ final class IncrementalBuildTests: XCTestCase {

func testBuildManifestCaching() async throws {
try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")
try await fixture(name: "ValidLayouts/SingleModule/Library") { fixturePath in
try await fixtureXCTest(name: "ValidLayouts/SingleModule/Library") { fixturePath in
@discardableResult
func build() async throws -> String {
return try await executeSwiftBuild(fixturePath).stdout
Expand Down Expand Up @@ -132,7 +132,7 @@ final class IncrementalBuildTests: XCTestCase {

func testDisableBuildManifestCaching() async throws {
try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")
try await fixture(name: "ValidLayouts/SingleModule/Library") { fixturePath in
try await fixtureXCTest(name: "ValidLayouts/SingleModule/Library") { fixturePath in
@discardableResult
func build() async throws -> String {
return try await executeSwiftBuild(fixturePath, extraArgs: ["--disable-build-manifest-caching"]).stdout
Expand All @@ -152,7 +152,7 @@ final class IncrementalBuildTests: XCTestCase {
#if os(macOS)
try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")

try await fixture(name: "ValidLayouts/SingleModule/Library") { fixturePath in
try await fixtureXCTest(name: "ValidLayouts/SingleModule/Library") { fixturePath in
let dummySwiftcPath = SwiftPM.xctestBinaryPath(for: "dummy-swiftc")
let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath
let environment: Environment = [
Expand Down
6 changes: 3 additions & 3 deletions Tests/BuildTests/PluginsBuildPlanTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class PluginsBuildPlanTests: XCTestCase {
func testBuildToolsDatabasePath() async throws {
try XCTSkipOnWindows(because: "Fails to build the project to due to incorrect Path handling. Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511")

try await fixture(name: "Miscellaneous/Plugins/MySourceGenPlugin") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/Plugins/MySourceGenPlugin") { fixturePath in
let (stdout, _) = try await executeSwiftBuild(fixturePath)
XCTAssertMatch(stdout, .contains("Build complete!"))
// FIXME: This is temporary until build of plugin tools is extracted into its own command.
Expand Down Expand Up @@ -48,7 +48,7 @@ final class PluginsBuildPlanTests: XCTestCase {
let targetTriple = hostToolchain.targetTriple.arch == .aarch64 ? x86Triple : armTriple

// By default, plugin dependencies are built for the host platform
try await fixture(name: "Miscellaneous/Plugins/CommandPluginTestStub") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/Plugins/CommandPluginTestStub") { fixturePath in
let (stdout, stderr) = try await executeSwiftPackage(fixturePath, extraArgs: ["-v", "build-plugin-dependency"])
XCTAssertMatch(stdout, .contains("Hello from dependencies-stub"))
XCTAssertMatch(stderr, .contains("Build of product 'plugintool' complete!"))
Expand All @@ -65,7 +65,7 @@ final class PluginsBuildPlanTests: XCTestCase {
}

// When cross compiling the final product, plugin dependencies should still be built for the host
try await fixture(name: "Miscellaneous/Plugins/CommandPluginTestStub") { fixturePath in
try await fixtureXCTest(name: "Miscellaneous/Plugins/CommandPluginTestStub") { fixturePath in
let (stdout, stderr) = try await executeSwiftPackage(fixturePath, extraArgs: ["--triple", targetTriple, "-v", "build-plugin-dependency"])
XCTAssertMatch(stdout, .contains("Hello from dependencies-stub"))
XCTAssertMatch(stderr, .contains("Build of product 'plugintool' complete!"))
Expand Down
Loading