diff --git a/Package.swift b/Package.swift index 754c662..2f3f80b 100644 --- a/Package.swift +++ b/Package.swift @@ -17,11 +17,14 @@ let products: [PackageDescription.Product] = [ ) ] +let flags: [PackageDescription.SwiftSetting] = [.enableExperimentalFeature("StrictConcurrency")] + let targets: [PackageDescription.Target] = [ .executableTarget( name: "xcode-selective-test", dependencies: ["SelectiveTestingCore", - .product(name: "ArgumentParser", package: "swift-argument-parser")] + .product(name: "ArgumentParser", package: "swift-argument-parser")], + swiftSettings: flags ), .target(name: "SelectiveTestingCore", dependencies: ["DependencyCalculator", @@ -29,25 +32,44 @@ let targets: [PackageDescription.Target] = [ "Git", "PathKit", "Yams", - .product(name: "ArgumentParser", package: "swift-argument-parser")]), + .product(name: "ArgumentParser", package: "swift-argument-parser")], + swiftSettings: flags, + ), .target(name: "DependencyCalculator", - dependencies: ["Workspace", "PathKit", "Git", .product(name: "Logging", package: "swift-log")]), + dependencies: ["Workspace", "PathKit", "Git", .product(name: "Logging", package: "swift-log")], + swiftSettings: flags, + ), .target(name: "TestConfigurator", - dependencies: ["Workspace", "PathKit", .product(name: "Logging", package: "swift-log")]), + dependencies: [ + "Workspace", + "PathKit", + .product(name: "Logging", package: "swift-log"), + .product(name: "ArgumentParser", package: "swift-argument-parser") + ], + swiftSettings: flags, + ), .target(name: "Workspace", - dependencies: ["XcodeProj", .product(name: "Logging", package: "swift-log")]), + dependencies: ["XcodeProj", .product(name: "Logging", package: "swift-log")], + swiftSettings: flags, + ), .target(name: "Git", - dependencies: ["SelectiveTestShell", "PathKit", .product(name: "Logging", package: "swift-log")]), - .target(name: "SelectiveTestShell"), + dependencies: ["SelectiveTestShell", "PathKit", .product(name: "Logging", package: "swift-log")], + swiftSettings: flags, + ), + .target(name: "SelectiveTestShell", + swiftSettings: flags, + ), .testTarget( name: "SelectiveTestingTests", dependencies: ["xcode-selective-test", "PathKit"], - resources: [.copy("ExampleProject")] + resources: [.copy("ExampleProject")], + swiftSettings: flags ), .testTarget( name: "DependencyCalculatorTests", dependencies: ["DependencyCalculator", "Workspace", "PathKit", "SelectiveTestingCore"], - resources: [.copy("ExamplePackages")] + resources: [.copy("ExamplePackages")], + swiftSettings: flags ), .plugin( name: "SelectiveTestingPlugin", diff --git a/Plugins/SelectiveTestingPlugin/SelectiveTestingPlugin.swift b/Plugins/SelectiveTestingPlugin/SelectiveTestingPlugin.swift index 7f0dc29..2a73c2d 100644 --- a/Plugins/SelectiveTestingPlugin/SelectiveTestingPlugin.swift +++ b/Plugins/SelectiveTestingPlugin/SelectiveTestingPlugin.swift @@ -48,19 +48,23 @@ struct SelectiveTestingPlugin: CommandPlugin { } if !toolArguments.contains(where: { $0 == "--test-plan" }) { - let testPlans = context.xcodeProject.filePaths.filter { - $0.extension == "xctestplan" + let allFiles = context.xcodeProject.targets.reduce([]) { partialResult, target in + partialResult + target.inputFiles + } + + let testPlans = allFiles.filter { + $0.url.pathExtension == "xctestplan" } if !testPlans.isEmpty { if testPlans.count == 1 { - print("Using \(testPlans[0].string) test plan") + print("Using \(testPlans[0].url.path()) test plan") } else { print("Using \(testPlans.count) test plans") } for testPlan in testPlans { - toolArguments.append(contentsOf: ["--test-plan", testPlan.string]) + toolArguments.append(contentsOf: ["--test-plan", testPlan.url.path()]) } } } diff --git a/Sources/SelectiveTestingCore/SelectiveTestingTool.swift b/Sources/SelectiveTestingCore/SelectiveTestingTool.swift index 1589279..2910077 100644 --- a/Sources/SelectiveTestingCore/SelectiveTestingTool.swift +++ b/Sources/SelectiveTestingCore/SelectiveTestingTool.swift @@ -37,9 +37,8 @@ public final class SelectiveTestingTool { dryRun: Bool = false, verbose: Bool = false) throws { - let suppliedBasePath = basePath.map { Path($0) } var configCandidates: [Path] = [] - if let suppliedBasePath { + if let suppliedBasePath = basePath.map({ Path($0) }) { let baseDirectory: Path if let ext = suppliedBasePath.extension, ext == "xcworkspace" || ext == "xcodeproj" { diff --git a/Sources/Workspace/Target.swift b/Sources/Workspace/Target.swift index 0c59a4f..e3cca85 100644 --- a/Sources/Workspace/Target.swift +++ b/Sources/Workspace/Target.swift @@ -3,7 +3,7 @@ // import Foundation -import PathKit +@preconcurrency import PathKit import XcodeProj extension PBXNativeTarget { @@ -17,8 +17,8 @@ extension PBXNativeTarget { } } -public struct TargetIdentity: Hashable { - public enum TargetType { +public struct TargetIdentity: Hashable, Sendable { + public enum TargetType: Sendable { case project case package } diff --git a/Tests/DependencyCalculatorTests/DependencyCalculatorTests.swift b/Tests/DependencyCalculatorTests/DependencyCalculatorTests.swift index 0aa7733..f3a9109 100644 --- a/Tests/DependencyCalculatorTests/DependencyCalculatorTests.swift +++ b/Tests/DependencyCalculatorTests/DependencyCalculatorTests.swift @@ -38,6 +38,7 @@ struct DependencyCalculatorTests { @Test func graphIntegrity_submodule() async throws { + // given let (depsGraph, mainApp, module, submodule, mainAppTests, moduleTests, submoduleTests) = depStructure() let files = Set([Path("/folder/submodule/file.swift")]) @@ -47,13 +48,16 @@ struct DependencyCalculatorTests { dependencyStructure: depsGraph, candidateTestPlan: nil) + // when let affected = graph.affectedTargets(changedFiles: files) + // then #expect(affected == Set([mainApp, mainAppTests, module, moduleTests, submodule, submoduleTests])) } @Test func graphIntegrity_mainApp() async throws { + // given let (depsGraph, mainApp, _, _, mainAppTests, _, _) = depStructure() let files = Set([Path("/folder/submodule/file.swift")]) @@ -63,13 +67,16 @@ struct DependencyCalculatorTests { dependencyStructure: depsGraph, candidateTestPlan: nil) + // when let affected = graph.affectedTargets(changedFiles: files) + // then #expect(affected == Set([mainApp, mainAppTests])) } @Test func graphIntegrity_module() async throws { + // given let (depsGraph, mainApp, module, _, mainAppTests, moduleTests, _) = depStructure() let files = Set([Path("/folder/submodule/file.swift")]) @@ -79,8 +86,10 @@ struct DependencyCalculatorTests { dependencyStructure: depsGraph, candidateTestPlan: nil) + // when let affected = graph.affectedTargets(changedFiles: files) + // then #expect(affected == Set([module, moduleTests, mainApp, mainAppTests])) } } diff --git a/Tests/DependencyCalculatorTests/PackageMetadataTests.swift b/Tests/DependencyCalculatorTests/PackageMetadataTests.swift index f4eac3b..9e39e3a 100644 --- a/Tests/DependencyCalculatorTests/PackageMetadataTests.swift +++ b/Tests/DependencyCalculatorTests/PackageMetadataTests.swift @@ -12,13 +12,16 @@ import Testing struct PackageMetadataTests { @Test func packageMetadataParsing_Simple() throws { + // given guard let exampleInBundle = Bundle.module.path(forResource: "ExamplePackages", ofType: "") else { fatalError("Missing ExamplePackages in TestBundle") } + // when let basePath = Path(exampleInBundle) + "Simple" let metadata = try PackageTargetMetadata.parse(at: basePath) + // then #expect(metadata.count == 2) let first = metadata[0] #expect(first.name == "ExampleSubpackage") @@ -51,13 +54,16 @@ struct PackageMetadataTests { @Test func packageMetadataParsing_ExamplePackage() throws { + // given guard let exampleInBundle = Bundle.module.path(forResource: "ExamplePackages", ofType: "") else { fatalError("Missing ExamplePackages in TestBundle") } + // when let basePath = Path(exampleInBundle) + "CrossDependency" let metadata = try PackageTargetMetadata.parse(at: basePath) + // then #expect(metadata.count == 10) let first = metadata[0] #expect(first.name == "SelectiveTesting") @@ -82,13 +88,16 @@ struct PackageMetadataTests { @Test func packageAndWorkspace() throws { + // given guard let exampleInBundle = Bundle.module.path(forResource: "ExamplePackages", ofType: "") else { fatalError("Missing ExamplePackages in TestBundle") } + // when let basePath = Path(exampleInBundle) + "PackageAndWorkspace" let metadata = try PackageTargetMetadata.parse(at: basePath) + // then #expect(metadata.count == 2) let first = metadata[0] #expect(first.name == "APackage") diff --git a/Tests/SelectiveTestingTests/SelectiveTestingConfigTests.swift b/Tests/SelectiveTestingTests/SelectiveTestingConfigTests.swift index 79f70b4..610906b 100644 --- a/Tests/SelectiveTestingTests/SelectiveTestingConfigTests.swift +++ b/Tests/SelectiveTestingTests/SelectiveTestingConfigTests.swift @@ -12,6 +12,7 @@ import Workspace struct SelectiveTestingConfigTests { @Test func configWorkspacePath() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -21,8 +22,10 @@ struct SelectiveTestingConfigTests { exclude: nil, extra: nil)) + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -33,6 +36,7 @@ struct SelectiveTestingConfigTests { @Test func configTestplanPath() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -42,8 +46,10 @@ struct SelectiveTestingConfigTests { exclude: nil, extra: nil)) + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -58,6 +64,7 @@ struct SelectiveTestingConfigTests { @Test func configTestplanPath_packageChanged() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -68,8 +75,10 @@ struct SelectiveTestingConfigTests { exclude: nil, extra: nil)) + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Package.swift") + // then _ = try await tool.run() try testTool.validateTestPlan(testPlanPath: testTool.projectPath + "ExampleProject.xctestplan", expected: Set([testTool.mainProjectTests(), @@ -80,6 +89,7 @@ struct SelectiveTestingConfigTests { @Test func configTestplanPath_packageResolvedChanged() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -89,8 +99,10 @@ struct SelectiveTestingConfigTests { exclude: nil, extra: nil)) + // when try testTool.addFile(at: testTool.projectPath + "ExamplePackage/Package.resolved") + // then _ = try await tool.run() try testTool.validateTestPlan(testPlanPath: testTool.projectPath + "ExampleProject.xctestplan", expected: Set([testTool.mainProjectTests(), @@ -101,6 +113,7 @@ struct SelectiveTestingConfigTests { @Test func additionalDependency() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -113,8 +126,10 @@ struct SelectiveTestingConfigTests { extra: additionalConfig) let tool = try testTool.createSUT(config: fullConfig) + // when try testTool.changeFile(at: testTool.projectPath + "ExampleSubpackage/Package.swift") + // then let result = try await tool.run() #expect(result.contains(testTool.mainProjectLibrary())) #expect(result.contains(testTool.mainProjectLibraryTests())) @@ -122,6 +137,7 @@ struct SelectiveTestingConfigTests { @Test func additionalFiles() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -134,8 +150,10 @@ struct SelectiveTestingConfigTests { extra: additionalConfig) let tool = try testTool.createSUT(config: fullConfig) + // when try testTool.addFile(at: testTool.projectPath + "ExmapleTargetLibrary/SomeFile.swift") + // then let result = try await tool.run() #expect(result.contains(testTool.mainProjectLibrary())) #expect(result.contains(testTool.mainProjectLibraryTests())) @@ -143,6 +161,7 @@ struct SelectiveTestingConfigTests { @Test func exclude() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -152,8 +171,10 @@ struct SelectiveTestingConfigTests { exclude: ["ExamplePackage"], extra: nil)) + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Package.swift") + // then _ = try await tool.run() try testTool.validateTestPlan(testPlanPath: testTool.projectPath + "ExampleProject.xctestplan", expected: Set([])) @@ -161,13 +182,16 @@ struct SelectiveTestingConfigTests { @Test func packageChangeInDifferentNamedPackage() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Tests/Subtests/Test.swift") + // then _ = try await tool.run() try testTool.validateTestPlan(testPlanPath: testTool.projectPath + "ExampleProject.xctestplan", expected: Set([testTool.subtests()])) @@ -175,6 +199,7 @@ struct SelectiveTestingConfigTests { @Test func dryRun() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -186,14 +211,17 @@ struct SelectiveTestingConfigTests { dryRun: true, verbose: true) + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Tests/Subtests/Test.swift") + // then _ = try await tool.run() try testTool.checkTestPlanUnmodified(at: testTool.projectPath + "ExampleProject.xctestplan") } @Test func multipleTestPlansViaCLI() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -203,8 +231,10 @@ struct SelectiveTestingConfigTests { changedFiles: [], verbose: true) + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -224,6 +254,7 @@ struct SelectiveTestingConfigTests { @Test func multipleTestPlansViaConfig() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -233,8 +264,10 @@ struct SelectiveTestingConfigTests { exclude: nil, extra: nil)) + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -254,6 +287,7 @@ struct SelectiveTestingConfigTests { @Test func multipleTestPlansMixedCliAndConfig() async throws { + // given - config has one test plan, CLI adds another let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -265,8 +299,10 @@ struct SelectiveTestingConfigTests { extra: nil), testPlan: "ExampleProject2.xctestplan") + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), diff --git a/Tests/SelectiveTestingTests/SelectiveTestingPackagesTests.swift b/Tests/SelectiveTestingTests/SelectiveTestingPackagesTests.swift index cd439c6..9df4bce 100644 --- a/Tests/SelectiveTestingTests/SelectiveTestingPackagesTests.swift +++ b/Tests/SelectiveTestingTests/SelectiveTestingPackagesTests.swift @@ -12,12 +12,16 @@ import Workspace struct SelectiveTestingPackagesTests { @Test func projectLoading_changePackage() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Sources/ExamplePackage/ExamplePackage.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -29,12 +33,16 @@ struct SelectiveTestingPackagesTests { @Test func projectLoading_changePackageDefinition() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Package.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -47,12 +55,16 @@ struct SelectiveTestingPackagesTests { @Test func projectLoading_packageAddFile() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + + // when try testTool.addFile(at: testTool.projectPath + "ExamplePackage/Sources/ExamplePackage/ExamplePackageFile.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -64,12 +76,16 @@ struct SelectiveTestingPackagesTests { @Test func projectLoading_packageRemoveFile() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + + // when try testTool.removeFile(at: testTool.projectPath + "ExamplePackage/Sources/ExamplePackage/ExamplePackage.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -81,12 +97,16 @@ struct SelectiveTestingPackagesTests { @Test func binaryTargetChange() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + + // when try testTool.changeFile(at: testTool.projectPath + "ExamplePackage/Binary.xcframework/Info.plist") + // then let result = try await tool.run() #expect(result == Set([testTool.binary()])) } diff --git a/Tests/SelectiveTestingTests/SelectiveTestingPerformanceTests.swift b/Tests/SelectiveTestingTests/SelectiveTestingPerformanceTests.swift index fc2663d..8b58282 100644 --- a/Tests/SelectiveTestingTests/SelectiveTestingPerformanceTests.swift +++ b/Tests/SelectiveTestingTests/SelectiveTestingPerformanceTests.swift @@ -11,12 +11,16 @@ import Testing struct SelectiveTestingPerformanceTests { @Test func performance() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT() + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject.xcodeproj/project.pbxproj") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), diff --git a/Tests/SelectiveTestingTests/SelectiveTestingProjectTests.swift b/Tests/SelectiveTestingTests/SelectiveTestingProjectTests.swift index a51b995..9794d18 100644 --- a/Tests/SelectiveTestingTests/SelectiveTestingProjectTests.swift +++ b/Tests/SelectiveTestingTests/SelectiveTestingProjectTests.swift @@ -12,13 +12,17 @@ import Workspace struct SelectiveTestingProjectTests { @Test func projectAlone() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT(config: nil, basePath: "ExampleProject.xcodeproj") + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject.xcodeproj/project.pbxproj") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), @@ -31,14 +35,18 @@ struct SelectiveTestingProjectTests { @Test func projectDeepGroupPathChange_turbo() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT(config: nil, basePath: "ExampleProject.xcodeproj", turbo: true) + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject/DeepGroup/Path/GroupContentView.swift") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget() @@ -47,13 +55,17 @@ struct SelectiveTestingProjectTests { @Test func projectDeepGroupPathChange() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT(config: nil, basePath: "ExampleProject.xcodeproj") + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject/DeepGroup/Path/GroupContentView.swift") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), @@ -64,14 +76,18 @@ struct SelectiveTestingProjectTests { @Test func projectDeepFolderPathChange_turbo() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT(config: nil, basePath: "ExampleProject.xcodeproj", turbo: true) + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject/DeepFolder/Path/FolderContentView.swift") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget() @@ -80,13 +96,17 @@ struct SelectiveTestingProjectTests { @Test func projectDeepFolderPathChange() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT(config: nil, basePath: "ExampleProject.xcodeproj") + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject/DeepFolder/Path/FolderContentView.swift") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), @@ -97,13 +117,17 @@ struct SelectiveTestingProjectTests { @Test func projectLocalizedPathChange() async throws { + // given let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } let tool = try testTool.createSUT(config: nil, basePath: "ExampleProject.xcodeproj") + + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject/Base.lproj/Example.xib") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), @@ -114,6 +138,7 @@ struct SelectiveTestingProjectTests { @Test func passingChangedFiles() async throws { + // given & when let testTool = try IntegrationTestTool() defer { try? testTool.tearDown() } @@ -122,6 +147,7 @@ struct SelectiveTestingProjectTests { basePath: "ExampleProject.xcodeproj", changedFiles: [changedPath.string]) + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), diff --git a/Tests/SelectiveTestingTests/SelectiveTestingWorkspaceTests.swift b/Tests/SelectiveTestingTests/SelectiveTestingWorkspaceTests.swift index 43c51b8..c0e3cdd 100644 --- a/Tests/SelectiveTestingTests/SelectiveTestingWorkspaceTests.swift +++ b/Tests/SelectiveTestingTests/SelectiveTestingWorkspaceTests.swift @@ -13,8 +13,13 @@ struct SelectiveTestingWorkspaceTests { @Test func projectLoading_empty() async throws { try await IntegrationTestTool.withTestTool { testTool in + // given let tool = try testTool.createSUT() + + // when let result = try await tool.run() + + // then #expect(result == Set()) } } @@ -22,9 +27,12 @@ struct SelectiveTestingWorkspaceTests { @Test func projectLoading_changeLibrary() async throws { try await IntegrationTestTool.withTestTool { testTool in + // given let tool = try testTool.createSUT() + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -37,9 +45,12 @@ struct SelectiveTestingWorkspaceTests { @Test func projectLoading_changeAsset() async throws { try await IntegrationTestTool.withTestTool { testTool in + // given let tool = try testTool.createSUT() + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject/Assets.xcassets/Contents.json") + // then let result = try await tool.run() #expect(result == Set([testTool.mainProjectMainTarget(), testTool.mainProjectTests(), @@ -50,9 +61,12 @@ struct SelectiveTestingWorkspaceTests { @Test func projectLoading_testPlanChange() async throws { try await IntegrationTestTool.withTestTool { testTool in + // given let tool = try testTool.createSUT() + // when try testTool.changeFile(at: testTool.projectPath + "ExampleProject.xctestplan") + // then let result = try await tool.run() #expect(result == Set()) } @@ -61,9 +75,12 @@ struct SelectiveTestingWorkspaceTests { @Test func projectLoading_testWorkspaceFileChange() async throws { try await IntegrationTestTool.withTestTool { testTool in + // given let tool = try testTool.createSUT() + // when try testTool.changeFile(at: testTool.projectPath + "ExampleWorkspace.xcworkspace/contents.xcworkspacedata") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), @@ -81,8 +98,11 @@ struct SelectiveTestingWorkspaceTests { @Test func projectLoading_testProjectFileChange() async throws { try await IntegrationTestTool.withTestTool { testTool in - try testTool.changeFile(at: testTool.projectPath + "ExampleProject.xcodeproj/project.pbxproj") + // given let tool = try testTool.createSUT() + // when + try testTool.changeFile(at: testTool.projectPath + "ExampleProject.xcodeproj/project.pbxproj") + // then let result = try await tool.run() #expect(result == Set([ testTool.mainProjectMainTarget(), @@ -97,10 +117,13 @@ struct SelectiveTestingWorkspaceTests { @Test func inferTestPlan() async throws { try await IntegrationTestTool.withTestTool { testTool in + // given let tool = try testTool.createSUT(config: nil, testPlan: nil) + // when try testTool.changeFile(at: testTool.projectPath + "ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then _ = try await tool.run() try testTool.validateTestPlan(testPlanPath: testTool.projectPath + "ExampleProject.xctestplan", expected: Set([testTool.mainProjectTests(), @@ -112,13 +135,16 @@ struct SelectiveTestingWorkspaceTests { @Test func inferTestPlanInSubfolder() async throws { try await IntegrationTestTool.withTestTool(subfolder: true) { testTool in + // given let tool = try testTool.createSUT( config: nil, basePath: testTool.projectPath + "Subfolder", testPlan: nil) + // when try testTool.changeFile(at: testTool.projectPath + "Subfolder/ExampleLibrary/ExampleLibrary/ExampleLibrary.swift") + // then _ = try await tool.run() try testTool.validateTestPlan(testPlanPath: testTool.projectPath + "Subfolder/ExampleProject.xctestplan", expected: Set([testTool.mainProjectTests(),