Skip to content

Commit c449f42

Browse files
committed
avoid deprecation warnings from test discovery (#3992)
motivation: do not prduce warning when tests are marked as deprecated, since they are designed to test deprecated functionality changes: * mark generated test-discovery wrappers as psuedo-deprecated so they dont produce deprecation warnings * use @main for the test discovery entry point instead of main.swift which helps avoid deprecation warnings at the entry point * cleanup test discovery generate names to be easier to reason about * add and adjust tests for throwing variants * add test for deprecation use case
1 parent 68adc9d commit c449f42

File tree

11 files changed

+75
-17
lines changed

11 files changed

+75
-17
lines changed

Fixtures/Miscellaneous/TestDiscovery/Async/Tests/AsyncTests/SwiftTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class AsyncTests: XCTestCase {
77
func testAsync() async {
88
}
99

10+
func testAsyncThrows() async throws {
11+
}
12+
1013
@MainActor func testMainActor() async {
1114
XCTAssertTrue(Thread.isMainThread)
1215
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// swift-tools-version:4.2
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "Simple",
6+
targets: [
7+
.target(name: "Simple"),
8+
.testTarget(name: "SimpleTests", dependencies: ["Simple"]),
9+
]
10+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
struct Simple {
2+
func hello() {}
3+
4+
@available(*, deprecated, message: "use hello instead")
5+
func deprecatedHello() {}
6+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import XCTest
2+
@testable import Simple
3+
4+
class SimpleTests: XCTestCase {
5+
func testHello() {
6+
Simple().hello()
7+
}
8+
9+
@available(*, deprecated, message: "testing deprecated API")
10+
func testDeprecatedHello() {
11+
Simple().deprecatedHello()
12+
}
13+
}

Fixtures/Miscellaneous/TestDiscovery/Simple/Tests/SimpleTests/SwiftTests.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ class SimpleTests: XCTestCase {
99
func test_Example2() {
1010
}
1111

12-
func testExample3(arg: String) {
12+
func testThrowing() throws {
13+
}
14+
15+
func testWithArgs(arg: String) {
1316
}
1417

1518
func nontest() {

Sources/Build/BuildOperationBuildSystemDelegateHandler.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ final class TestDiscoveryCommand: CustomLLBuildCommand {
7373
let testMethods = iterator.value.flatMap{ $0.testMethods }
7474
stream <<< "\n"
7575
stream <<< "fileprivate extension " <<< className <<< " {" <<< "\n"
76-
stream <<< indent(4) <<< "static let __allTests__\(className) = [" <<< "\n"
76+
stream <<< indent(4) <<< "@available(*, deprecated, message: \"Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings\")" <<< "\n"
77+
stream <<< indent(4) <<< "static let __allTests = [" <<< "\n"
7778
for method in testMethods {
7879
stream <<< indent(8) <<< method.allTestsEntry <<< ",\n"
7980
}
@@ -82,13 +83,14 @@ final class TestDiscoveryCommand: CustomLLBuildCommand {
8283
}
8384

8485
stream <<< """
85-
func __allTests_\(module)() -> [XCTestCaseEntry] {
86+
@available(*, deprecated, message: "Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings")
87+
func __\(module)__allTests() -> [XCTestCaseEntry] {
8688
return [\n
8789
"""
8890

8991
for iterator in testsByClassNames {
9092
let className = iterator.key
91-
stream <<< indent(8) <<< "testCase(\(className).__allTests__\(className)),\n"
93+
stream <<< indent(8) <<< "testCase(\(className).__allTests),\n"
9294
}
9395

9496
stream <<< """
@@ -113,7 +115,7 @@ final class TestDiscoveryCommand: CustomLLBuildCommand {
113115
let testsByModule = Dictionary(grouping: tests, by: { $0.module.spm_mangledToC99ExtendedIdentifier() })
114116

115117
func isMainFile(_ path: AbsolutePath) -> Bool {
116-
return path.basename == "main.swift"
118+
return path.basename == LLBuildManifest.TestDiscoveryTool.mainFileName
117119
}
118120

119121
var maybeMainFile: AbsolutePath?
@@ -140,19 +142,26 @@ final class TestDiscoveryCommand: CustomLLBuildCommand {
140142
}
141143

142144
guard let mainFile = maybeMainFile else {
143-
throw InternalError("unknown main file")
145+
throw InternalError("main output (\(LLBuildManifest.TestDiscoveryTool.mainFileName)) not found")
144146
}
145147

146148
// Write the main file.
147149
let stream = try LocalFileOutputByteStream(mainFile)
148150

149151
stream <<< "import XCTest" <<< "\n\n"
150-
stream <<< "var tests = [XCTestCaseEntry]()" <<< "\n"
152+
153+
stream <<< "@main" <<< "\n"
154+
stream <<< "@available(*, deprecated, message: \"Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings\")" <<< "\n"
155+
stream <<< "struct Runner" <<< " {" <<< "\n"
156+
stream <<< indent(4) <<< "static func main()" <<< " {" <<< "\n"
157+
stream <<< indent(8) <<< "var tests = [XCTestCaseEntry]()" <<< "\n"
151158
for module in testsByModule.keys {
152-
stream <<< "tests += __allTests_\(module)()" <<< "\n"
159+
stream <<< indent(8) <<< "tests += __\(module)__allTests()" <<< "\n"
153160
}
154-
stream <<< "\n"
155-
stream <<< "XCTMain(tests)" <<< "\n"
161+
stream <<< indent(8) <<< "\n"
162+
stream <<< indent(8) <<< "XCTMain(tests)" <<< "\n"
163+
stream <<< indent(4) <<< "}" <<< "\n"
164+
stream <<< "}" <<< "\n"
156165

157166
stream.flush()
158167
}

Sources/Build/BuildPlan.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,7 @@ public class BuildPlan {
14781478
} else {
14791479
// We'll generate sources containing the test names as part of the build process.
14801480
let derivedTestListDir = buildParameters.buildPath.appending(components: "\(testProduct.name).derived")
1481-
let mainFile = derivedTestListDir.appending(component: "main.swift")
1481+
let mainFile = derivedTestListDir.appending(component: "runner.swift")
14821482

14831483
var paths: [AbsolutePath] = []
14841484
paths.append(mainFile)

Sources/Build/LLBuildManifestBuilder.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,8 +832,8 @@ extension LLBuildManifestBuilder {
832832
let objectFiles = testTargets.flatMap{ $0.objects }.sorted().map(Node.file)
833833
let outputs = testDiscoveryTarget.target.sources.paths
834834

835-
guard let mainOutput = (outputs.first{ $0.basename == "main.swift" }) else {
836-
throw InternalError("output main.swift not found")
835+
guard let mainOutput = (outputs.first{ $0.basename == TestDiscoveryTool.mainFileName }) else {
836+
throw InternalError("main output (\(TestDiscoveryTool.mainFileName)) not found")
837837
}
838838
let cmdName = mainOutput.pathString
839839
manifest.addTestDiscoveryCmd(

Sources/LLBuildManifest/Tools.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public struct PhonyTool: ToolProtocol {
4444

4545
public struct TestDiscoveryTool: ToolProtocol {
4646
public static let name: String = "test-discovery-tool"
47+
public static let mainFileName: String = "runner.swift"
4748

4849
public var inputs: [Node]
4950
public var outputs: [Node]

Tests/FunctionalTests/MiscellaneousTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ class MiscellaneousTestCase: XCTestCase {
550550
static let __allTests__SimpleTests = [
551551
("test_Example2", test_Example2),
552552
("testExample1", testExample1),
553+
("testThrowing", testThrowing),
553554
]
554555
}
555556

Tests/FunctionalTests/TestDiscoveryTests.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ class TestDiscoveryTests: XCTestCase {
3030
let (stdout, stderr) = try executeSwiftTest(path)
3131
#if os(macOS)
3232
XCTAssertMatch(stdout, .contains("module Simple"))
33-
XCTAssertMatch(stderr, .contains("Executed 2 tests"))
33+
XCTAssertMatch(stderr, .contains("Executed 3 tests"))
3434
#else
3535
XCTAssertMatch(stdout, .contains("module Simple"))
36-
XCTAssertMatch(stdout, .contains("Executed 2 tests"))
36+
XCTAssertMatch(stdout, .contains("Executed 3 tests"))
3737
#endif
3838
}
3939
}
@@ -56,10 +56,10 @@ class TestDiscoveryTests: XCTestCase {
5656
let (stdout, stderr) = try executeSwiftTest(path)
5757
#if os(macOS)
5858
XCTAssertMatch(stdout, .contains("module Async"))
59-
XCTAssertMatch(stderr, .contains("Executed 3 tests"))
59+
XCTAssertMatch(stderr, .contains("Executed 4 tests"))
6060
#else
6161
XCTAssertMatch(stdout, .contains("module Async"))
62-
XCTAssertMatch(stdout, .contains("Executed 3 tests"))
62+
XCTAssertMatch(stdout, .contains("Executed 4 tests"))
6363
#endif
6464
}
6565
}
@@ -115,4 +115,16 @@ class TestDiscoveryTests: XCTestCase {
115115
}
116116
#endif
117117
}
118+
119+
func testDeprecatedTests() throws {
120+
#if os(macOS)
121+
try XCTSkipIf(true)
122+
#else
123+
fixture(name: "Miscellaneous/TestDiscovery/Deprecation") { path in
124+
let (stdout, _) = try executeSwiftTest(path, extraArgs: ["--enable-test-discovery"])
125+
XCTAssertMatch(stdout, .contains("Executed 2 tests"))
126+
XCTAssertNoMatch(stdout, .contains("is deprecated"))
127+
}
128+
#endif
129+
}
118130
}

0 commit comments

Comments
 (0)