Skip to content

Commit e2fb647

Browse files
authored
Merge pull request #468 from apple/jgrynspan/XCTMain-signature
Make `XCTMain()` return its exit code instead of calling `exit()`.
2 parents 191097e + efdd66f commit e2fb647

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

Sources/XCTest/Public/XCTestMain.swift

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
/// Starts a test run for the specified test cases.
3434
///
35-
/// This function will not return. If the test cases pass, then it will call `exit(EXIT_SUCCESS)`. If there is a failure, then it will call `exit(EXIT_FAILURE)`.
3635
/// Example usage:
3736
///
3837
/// class TestFoo: XCTestCase {
@@ -50,28 +49,33 @@
5049
/// // etc...
5150
/// }
5251
///
53-
/// XCTMain([ testCase(TestFoo.allTests) ])
52+
/// let exitCode = XCTMain([ testCase(TestFoo.allTests) ])
5453
///
55-
/// Command line arguments can be used to select a particular test case or class to execute. For example:
54+
/// Command line arguments can be used to select a particular test case or class
55+
/// to execute. For example:
5656
///
5757
/// ./FooTests FooTestCase/testFoo # Run a single test case
5858
/// ./FooTests FooTestCase # Run all the tests in FooTestCase
5959
///
60-
/// - Parameter testCases: An array of test cases run, each produced by a call to the `testCase` function
61-
/// - 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-
60+
/// - Parameters:
61+
/// - testCases: An array of test cases run, each produced by a call to the
62+
/// `testCase` function.
63+
/// - arguments: Command-line arguments to pass to XCTest. By default, the
64+
/// arguments passed to the process are used.
65+
/// - observers: Zero or more observers that should observe events that
66+
/// occur while testing. If `nil` (the default), events are written to
67+
/// the console.
68+
///
69+
/// - Returns: The exit code to use when the process terminates. `EXIT_SUCCESS`
70+
/// indicates success, while any other value (including `EXIT_FAILURE`)
71+
/// indicates failure.
72+
@_disfavoredOverload
7073
public func XCTMain(
7174
_ testCases: [XCTestCaseEntry],
72-
arguments: [String],
73-
observers: [XCTestObservation]
74-
) -> Never {
75+
arguments: [String] = CommandLine.arguments,
76+
observers: [XCTestObservation]? = nil
77+
) -> CInt {
78+
let observers = observers ?? [PrintObserver()]
7579
let testBundle = Bundle.main
7680

7781
let executionMode = ArgumentParser(arguments: arguments).executionMode
@@ -99,10 +103,10 @@ public func XCTMain(
99103
switch executionMode {
100104
case .list(type: .humanReadable):
101105
TestListing(testSuite: rootTestSuite).printTestList()
102-
exit(EXIT_SUCCESS)
106+
return EXIT_SUCCESS
103107
case .list(type: .json):
104108
TestListing(testSuite: rootTestSuite).printTestJSON()
105-
exit(EXIT_SUCCESS)
109+
return EXIT_SUCCESS
106110
case let .help(invalidOption):
107111
if let invalid = invalidOption {
108112
let errMsg = "Error: Invalid option \"\(invalid)\"\n"
@@ -133,7 +137,7 @@ public func XCTMain(
133137
134138
> \(exeName) \(sampleTests)
135139
""")
136-
exit(invalidOption == nil ? EXIT_SUCCESS : EXIT_FAILURE)
140+
return invalidOption == nil ? EXIT_SUCCESS : EXIT_FAILURE
137141
case .run(selectedTestNames: _):
138142
// Add a test observer that prints test progress to stdout.
139143
let observationCenter = XCTestObservationCenter.shared
@@ -145,6 +149,25 @@ public func XCTMain(
145149
rootTestSuite.run()
146150
observationCenter.testBundleDidFinish(testBundle)
147151

148-
exit(rootTestSuite.testRun!.totalFailureCount == 0 ? EXIT_SUCCESS : EXIT_FAILURE)
152+
return rootTestSuite.testRun!.totalFailureCount == 0 ? EXIT_SUCCESS : EXIT_FAILURE
149153
}
150154
}
155+
156+
// @available(*, deprecated, message: "Call the overload of XCTMain() that returns an exit code instead.")
157+
public func XCTMain(_ testCases: [XCTestCaseEntry]) -> Never {
158+
exit(XCTMain(testCases, arguments: CommandLine.arguments, observers: nil) as CInt)
159+
}
160+
161+
// @available(*, deprecated, message: "Call the overload of XCTMain() that returns an exit code instead.")
162+
public func XCTMain(_ testCases: [XCTestCaseEntry], arguments: [String]) -> Never {
163+
exit(XCTMain(testCases, arguments: arguments, observers: nil) as CInt)
164+
}
165+
166+
// @available(*, deprecated, message: "Call the overload of XCTMain() that returns an exit code instead.")
167+
public func XCTMain(
168+
_ testCases: [XCTestCaseEntry],
169+
arguments: [String],
170+
observers: [XCTestObservation]
171+
) -> Never {
172+
exit(XCTMain(testCases, arguments: arguments, observers: observers) as CInt)
173+
}

0 commit comments

Comments
 (0)