Skip to content

Commit 0a568ed

Browse files
committed
Make XCTMain() return its exit code instead of calling exit().
Right now, `XCTMain()` returns `Never` and calls `exit()` to report its status. This makes it difficult (if not outright impossible) to do any post-test cleanup work like writing an event log or other cleanup. This PR adds a new overload of `XCTMain()` that instead returns the intended exit code of the process (as `CInt`, since process exit codes passed to `exit()` are always of type `int` in C.) The new overload is, for now, disfavoured until we can teach SwiftPM about it. Once we can (in a subsequent PR), we'll mark the _old_ one disfavored and deprecated.
1 parent 191097e commit 0a568ed

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

Sources/XCTest/Public/XCTestMain.swift

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,13 @@
5959
///
6060
/// - Parameter testCases: An array of test cases run, each produced by a call to the `testCase` function
6161
/// - seealso: `testCase`
62-
public func XCTMain(_ testCases: [XCTestCaseEntry]) -> Never {
63-
XCTMain(testCases, arguments: CommandLine.arguments)
64-
}
65-
66-
public func XCTMain(_ testCases: [XCTestCaseEntry], arguments: [String]) -> Never {
67-
XCTMain(testCases, arguments: arguments, observers: [PrintObserver()])
68-
}
69-
62+
@_disfavoredOverload
7063
public func XCTMain(
7164
_ testCases: [XCTestCaseEntry],
72-
arguments: [String],
73-
observers: [XCTestObservation]
74-
) -> Never {
65+
arguments: [String] = CommandLine.arguments,
66+
observers: [XCTestObservation]? = nil
67+
) -> CInt {
68+
let observers = observers ?? [PrintObserver()]
7569
let testBundle = Bundle.main
7670

7771
let executionMode = ArgumentParser(arguments: arguments).executionMode
@@ -99,10 +93,10 @@ public func XCTMain(
9993
switch executionMode {
10094
case .list(type: .humanReadable):
10195
TestListing(testSuite: rootTestSuite).printTestList()
102-
exit(EXIT_SUCCESS)
96+
return EXIT_SUCCESS
10397
case .list(type: .json):
10498
TestListing(testSuite: rootTestSuite).printTestJSON()
105-
exit(EXIT_SUCCESS)
99+
return EXIT_SUCCESS
106100
case let .help(invalidOption):
107101
if let invalid = invalidOption {
108102
let errMsg = "Error: Invalid option \"\(invalid)\"\n"
@@ -133,7 +127,7 @@ public func XCTMain(
133127
134128
> \(exeName) \(sampleTests)
135129
""")
136-
exit(invalidOption == nil ? EXIT_SUCCESS : EXIT_FAILURE)
130+
return invalidOption == nil ? EXIT_SUCCESS : EXIT_FAILURE
137131
case .run(selectedTestNames: _):
138132
// Add a test observer that prints test progress to stdout.
139133
let observationCenter = XCTestObservationCenter.shared
@@ -145,6 +139,15 @@ public func XCTMain(
145139
rootTestSuite.run()
146140
observationCenter.testBundleDidFinish(testBundle)
147141

148-
exit(rootTestSuite.testRun!.totalFailureCount == 0 ? EXIT_SUCCESS : EXIT_FAILURE)
142+
return rootTestSuite.testRun!.totalFailureCount == 0 ? EXIT_SUCCESS : EXIT_FAILURE
149143
}
150144
}
145+
146+
// @available(*, deprecated, message: "Call the overload of XCTMain() that returns an exit code instead.")
147+
public func XCTMain(
148+
_ testCases: [XCTestCaseEntry],
149+
arguments: [String] = CommandLine.arguments,
150+
observers: [XCTestObservation]? = nil
151+
) -> Never {
152+
exit(XCTMain(testCases, arguments: arguments, observers: observers) as CInt)
153+
}

0 commit comments

Comments
 (0)