Skip to content

Commit cc2ae5d

Browse files
committed
Don't use assert to emit failure when not continuing after failure
* Refactor to rely less on global state for failure reporting * Handle failures with a closure capturing the current test method name so that the failure can be printed before erroring out
1 parent 75d601c commit cc2ae5d

File tree

3 files changed

+19
-21
lines changed

3 files changed

+19
-21
lines changed

XCTest/XCTAssert.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ The primitive assertion function for XCTest. All other XCTAssert* functions are
1919
*/
2020
public func XCTAssert(@autoclosure expression: () -> BooleanType, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
2121
if !expression().boolValue {
22-
if let test = XCTCurrentTestCase {
23-
test.testFailure(message, expected: true, file: file, line: line)
22+
if let handler = XCTFailureHandler {
23+
handler(XCTFailure(message: message, expected: true, file: file, line: line))
2424
}
2525
}
2626
}

XCTest/XCTestCase.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,18 @@ extension XCTestCase {
3232
var totalFailures = 0
3333
var unexpectedFailures = 0
3434
for (name, test) in tests {
35-
XCTCurrentTestCase = self
3635
let method = "\(self.dynamicType).\(name)"
36+
37+
var failures = [XCTFailure]()
38+
XCTFailureHandler = { failure in
39+
if !self.continueAfterFailure {
40+
failure.emit(method)
41+
fatalError("Terminating execution due to test failure")
42+
} else {
43+
failures.append(failure)
44+
}
45+
}
46+
3747
var duration: Double = 0.0
3848
print("Test Case '\(method)' started.")
3949

@@ -47,21 +57,20 @@ extension XCTestCase {
4757

4858
duration = end - start
4959
totalDuration += duration
50-
for failure in XCTCurrentFailures {
60+
for failure in failures {
5161
failure.emit(method)
5262
totalFailures += 1
5363
if !failure.expected {
5464
unexpectedFailures += 1
5565
}
5666
}
5767
var result = "passed"
58-
if XCTCurrentFailures.count > 0 {
68+
if failures.count > 0 {
5969
result = "failed"
6070
}
6171
print("Test Case '\(method)' \(result) (\(printableStringForTimeInterval(duration)) seconds).")
62-
XCTAllRuns.append(XCTRun(duration: duration, method: method, passed: XCTCurrentFailures.count == 0, failures: XCTCurrentFailures))
63-
XCTCurrentFailures.removeAll()
64-
XCTCurrentTestCase = nil
72+
XCTAllRuns.append(XCTRun(duration: duration, method: method, passed: failures.count == 0, failures: failures))
73+
XCTFailureHandler = nil
6574
}
6675
var testCountSuffix = "s"
6776
if tests.count == 1 {
@@ -75,16 +84,7 @@ extension XCTestCase {
7584

7685
print("Executed \(tests.count) test\(testCountSuffix), with \(totalFailures) failure\(failureSuffix) (\(unexpectedFailures) unexpected) in \(printableStringForTimeInterval(averageDuration)) (\(printableStringForTimeInterval(totalDuration))) seconds")
7786
}
78-
79-
// This function is for the use of XCTestCase only, but we must make it public or clients will get a link failure when using XCTest (23476006)
80-
public func testFailure(message: String, expected: Bool, file: StaticString , line: UInt) {
81-
if !continueAfterFailure {
82-
assert(false, message, file: file, line: line)
83-
} else {
84-
XCTCurrentFailures.append(XCTFailure(message: message, expected: expected, file: file, line: line))
85-
}
86-
}
87-
87+
8888
public func setUp() {
8989

9090
}

XCTest/XCTestMain.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,5 @@ internal struct XCTRun {
6262
exit(totalFailures > 0 ? 1 : 0)
6363
}
6464

65-
internal var XCTCurrentTestCase: XCTestCase?
66-
internal var XCTCurrentFailures = [XCTFailure]()
65+
internal var XCTFailureHandler: (XCTFailure -> Void)?
6766
internal var XCTAllRuns = [XCTRun]()
68-

0 commit comments

Comments
 (0)