Skip to content

Commit e5c0cb3

Browse files
committed
Allow test methods to throw an error as an unexpected failure
Change the type of the function portion of XCTestCaseProvider.allTests to a closure that throws, so that test methods are allowed to throw an error. The only change this requires on clients' part is to adjust their declarations of allTests. When a test method does throw an error, treat that as an unexpected failure. Addresses rdar://problem/23778435.
1 parent f98cf49 commit e5c0cb3

File tree

6 files changed

+50
-25
lines changed

6 files changed

+50
-25
lines changed

Sources/XCTest/XCTestCase.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This source file is part of the Swift.org open source project
22
//
3-
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
3+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
44
// Licensed under Apache License v2.0 with Runtime Library Exception
55
//
66
// See http://swift.org/LICENSE.txt for license information
@@ -50,7 +50,14 @@ extension XCTestCase {
5050

5151
setUp()
5252

53-
let duration = measureTimeExecutingBlock(test)
53+
let duration = measureTimeExecutingBlock {
54+
do {
55+
try test()
56+
} catch {
57+
let unexpectedFailure = XCTFailure(message: "", failureDescription: "threw error \"\(error)\"", expected: false, file: "<EXPR>", line: 0)
58+
XCTFailureHandler!(unexpectedFailure)
59+
}
60+
}
5461

5562
tearDown()
5663

Sources/XCTest/XCTestCaseProvider.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This source file is part of the Swift.org open source project
22
//
3-
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
3+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
44
// Licensed under Apache License v2.0 with Runtime Library Exception
55
//
66
// See http://swift.org/LICENSE.txt for license information
@@ -13,6 +13,6 @@
1313

1414
public protocol XCTestCaseProvider {
1515
// In the Objective-C version of XCTest, it is possible to discover all tests when the test is executed by asking the runtime for all methods and looking for the string "test". In Swift, we ask test providers to tell us the list of tests by implementing this property.
16-
var allTests : [(String, () -> Void)] { get }
16+
var allTests : [(String, () throws -> Void)] { get }
1717
}
1818

Tests/Functional/ErrorHandling/main.swift

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
// RUN: %{swiftc} %s -o %{built_tests_dir}/ErrorHandling
22
// RUN: %{built_tests_dir}/ErrorHandling > %t || true
33
// RUN: %{xctest_checker} %t %s
4-
// CHECK: Test Case 'ErrorHandling.test_shouldButDoesNotThrowError' started.
5-
// CHECK: .*/Tests/Functional/ErrorHandling/main.swift:\d+: error: ErrorHandling.test_shouldButDoesNotThrowError : XCTAssertThrowsError failed: did not throw error -
6-
// CHECK: Test Case 'ErrorHandling.test_shouldButDoesNotThrowError' failed \(\d+\.\d+ seconds\).
7-
// CHECK: Test Case 'ErrorHandling.test_shouldThrowError' started.
8-
// CHECK: Test Case 'ErrorHandling.test_shouldThrowError' passed \(\d+\.\d+ seconds\).
9-
// CHECK: Test Case 'ErrorHandling.test_throwsButFailsWhenCheckingError' started.
10-
// CHECK: .*/Tests/Functional/ErrorHandling/main.swift:\d+: error: ErrorHandling.test_throwsButFailsWhenCheckingError : XCTAssertEqual failed: \("Optional\("an error message"\)"\) is not equal to \("Optional\(""\)"\) -
11-
// CHECK: Test Case 'ErrorHandling.test_throwsButFailsWhenCheckingError' failed \(\d+\.\d+ seconds\).
12-
// CHECK: Executed 3 tests, with 2 failures \(0 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
13-
// CHECK: Total executed 3 tests, with 2 failures \(0 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
4+
// CHECK: Test Case 'ErrorHandling.test_shouldButDoesNotThrowErrorInAssertion' started.
5+
// CHECK: .*/Tests/Functional/ErrorHandling/main.swift:\d+: error: ErrorHandling.test_shouldButDoesNotThrowErrorInAssertion : XCTAssertThrowsError failed: did not throw error -
6+
// CHECK: Test Case 'ErrorHandling.test_shouldButDoesNotThrowErrorInAssertion' failed \(\d+\.\d+ seconds\).
7+
// CHECK: Test Case 'ErrorHandling.test_shouldThrowErrorInAssertion' started.
8+
// CHECK: Test Case 'ErrorHandling.test_shouldThrowErrorInAssertion' passed \(\d+\.\d+ seconds\).
9+
// CHECK: Test Case 'ErrorHandling.test_throwsErrorInAssertionButFailsWhenCheckingError' started.
10+
// CHECK: .*/Tests/Functional/ErrorHandling/main.swift:\d+: error: ErrorHandling.test_throwsErrorInAssertionButFailsWhenCheckingError : XCTAssertEqual failed: \("Optional\("an error message"\)"\) is not equal to \("Optional\(""\)"\) -
11+
// CHECK: Test Case 'ErrorHandling.test_throwsErrorInAssertionButFailsWhenCheckingError' failed \(\d+\.\d+ seconds\).
12+
// CHECK: Test Case 'ErrorHandling.test_canAndDoesThrowErrorFromTestMethod' started.
13+
// CHECK: \<EXPR\>:0: unexpected error: ErrorHandling.test_canAndDoesThrowErrorFromTestMethod : threw error "AnError\("an error message"\)" -
14+
// CHECK: Test Case 'ErrorHandling.test_canAndDoesThrowErrorFromTestMethod' failed \(\d+\.\d+ seconds\).
15+
// CHECK: Test Case 'ErrorHandling.test_canButDoesNotThrowErrorFromTestMethod' started.
16+
// CHECK: Test Case 'ErrorHandling.test_canButDoesNotThrowErrorFromTestMethod' passed \(\d+\.\d+ seconds\).
17+
// CHECK: Executed 5 tests, with 3 failures \(1 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
18+
// CHECK: Total executed 5 tests, with 3 failures \(1 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
1419

1520
#if os(Linux) || os(FreeBSD)
1621
import XCTest
@@ -19,11 +24,16 @@
1924
#endif
2025

2126
class ErrorHandling: XCTestCase {
22-
var allTests: [(String, () -> ())] {
27+
var allTests: [(String, () throws -> ())] {
2328
return [
24-
("test_shouldButDoesNotThrowError", test_shouldButDoesNotThrowError),
25-
("test_shouldThrowError", test_shouldThrowError),
26-
("test_throwsButFailsWhenCheckingError", test_throwsButFailsWhenCheckingError)
29+
// Tests for XCTAssertThrowsError
30+
("test_shouldButDoesNotThrowErrorInAssertion", test_shouldButDoesNotThrowErrorInAssertion),
31+
("test_shouldThrowErrorInAssertion", test_shouldThrowErrorInAssertion),
32+
("test_throwsErrorInAssertionButFailsWhenCheckingError", test_throwsErrorInAssertionButFailsWhenCheckingError),
33+
34+
// Tests for "testFoo() throws"
35+
("test_canAndDoesThrowErrorFromTestMethod", test_canAndDoesThrowErrorFromTestMethod),
36+
("test_canButDoesNotThrowErrorFromTestMethod", test_canButDoesNotThrowErrorFromTestMethod),
2737
]
2838
}
2939

@@ -38,11 +48,11 @@ class ErrorHandling: XCTestCase {
3848
throw SomeError.AnError("an error message")
3949
}
4050

41-
func test_shouldButDoesNotThrowError() {
51+
func test_shouldButDoesNotThrowErrorInAssertion() {
4252
XCTAssertThrowsError(try functionThatDoesNotThrowError())
4353
}
4454

45-
func test_shouldThrowError() {
55+
func test_shouldThrowErrorInAssertion() {
4656
XCTAssertThrowsError(try functionThatDoesThrowError()) { error in
4757
guard let thrownError = error as? SomeError else {
4858
XCTFail("Threw the wrong type of error")
@@ -56,7 +66,7 @@ class ErrorHandling: XCTestCase {
5666
}
5767
}
5868

59-
func test_throwsButFailsWhenCheckingError() {
69+
func test_throwsErrorInAssertionButFailsWhenCheckingError() {
6070
XCTAssertThrowsError(try functionThatDoesThrowError()) { error in
6171
guard let thrownError = error as? SomeError else {
6272
XCTFail("Threw the wrong type of error")
@@ -69,6 +79,14 @@ class ErrorHandling: XCTestCase {
6979
}
7080
}
7181
}
82+
83+
func test_canAndDoesThrowErrorFromTestMethod() throws {
84+
try functionThatDoesThrowError()
85+
}
86+
87+
func test_canButDoesNotThrowErrorFromTestMethod() throws {
88+
try functionThatDoesNotThrowError()
89+
}
7290
}
7391

7492
XCTMain([ErrorHandling()])

Tests/Functional/FailingTestSuite/main.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#endif
2323

2424
class PassingTestCase: XCTestCase {
25-
var allTests: [(String, () -> ())] {
25+
var allTests: [(String, () throws -> ())] {
2626
return [
2727
("test_passes", test_passes),
2828
]
@@ -34,7 +34,7 @@ class PassingTestCase: XCTestCase {
3434
}
3535

3636
class FailingTestCase: XCTestCase {
37-
var allTests: [(String, () -> ())] {
37+
var allTests: [(String, () throws -> ())] {
3838
return [
3939
("test_passes", test_passes),
4040
("test_fails", test_fails),

Tests/Functional/NegativeAccuracyTestCase/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
// Regression test for https://github.com/apple/swift-corelibs-xctest/pull/7
2424
class NegativeAccuracyTestCase: XCTestCase {
25-
var allTests: [(String, () -> ())] {
25+
var allTests: [(String, () throws -> ())] {
2626
return [
2727
("test_equalWithAccuracy_passes", test_equalWithAccuracy_passes),
2828
("test_equalWithAccuracy_fails", test_equalWithAccuracy_fails),

Tests/Functional/SingleFailingTestCase/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#endif
1515

1616
class SingleFailingTestCase: XCTestCase {
17-
var allTests: [(String, () -> ())] {
17+
var allTests: [(String, () throws -> ())] {
1818
return [
1919
("test_fails", test_fails),
2020
]

0 commit comments

Comments
 (0)