Skip to content

Commit bf3fddf

Browse files
committed
Print additional details when emitting assertion failure messages
This brings the output in line with what Darwin's XCTest outputs * Includes the name of the failing assertion function * Includes details about the asserted expressions when appropriate
1 parent 75d601c commit bf3fddf

File tree

3 files changed

+124
-31
lines changed

3 files changed

+124
-31
lines changed

XCTest/XCTAssert.swift

Lines changed: 120 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,101 +10,193 @@
1010
// XCTAssert.swift
1111
//
1212

13+
private enum _XCTAssertion {
14+
case Equal(Any, Any)
15+
case EqualWithAccuracy(Any, Any, accuracy: Any)
16+
case GreaterThan(Any, Any)
17+
case GreaterThanOrEqual(Any, Any)
18+
case LessThan(Any, Any)
19+
case LessThanOrEqual(Any, Any)
20+
case NotEqual(Any, Any)
21+
case NotEqualWithAccuracy(Any, Any, accuracy: Any)
22+
case Nil
23+
case NotNil
24+
case True
25+
case False
26+
case Fail
27+
28+
var name: String? {
29+
switch(self) {
30+
case .Equal: return "XCTAssertEqual"
31+
case .EqualWithAccuracy: return "XCTAssertEqualWithAccuracy"
32+
case .GreaterThan: return "XCTAssertGreaterThan"
33+
case .GreaterThanOrEqual: return "XCTAssertGreaterThanOrEqual"
34+
case .LessThan: return "XCTAssertLessThan"
35+
case .LessThanOrEqual: return "XCTAssertLessThanOrEqual"
36+
case .NotEqual: return "XCTAssertNotEqual"
37+
case .NotEqualWithAccuracy: return "XCTAssertNotEqualWithAccuracy"
38+
case .Nil: return "XCTAssertNil"
39+
case .NotNil: return "XCTAssertNotNil"
40+
case .True: return "XCTAssertTrue"
41+
case .False: return "XCTAssertFalse"
42+
case .Fail: return nil
43+
}
44+
}
45+
46+
var failureDetails: String? {
47+
switch(self) {
48+
case .Equal(let value1, let value2):
49+
return "(\"\(value1)\") is not equal to (\"\(value2)\")"
50+
case .EqualWithAccuracy(let value1, let value2, let accuracy):
51+
return "(\"\(value1)\") is not equal to (\"\(value2)\") +/- (\"\(accuracy)\")"
52+
case .GreaterThan(let value1, let value2):
53+
return "(\"\(value1)\") is not greater than (\"\(value2)\")"
54+
case .GreaterThanOrEqual(let value1, let value2):
55+
return "(\"\(value1)\") is less than (\"\(value2)\")"
56+
case .LessThan(let value1, let value2):
57+
return "(\"\(value1)\") is not less than (\"\(value2)\")"
58+
case .LessThanOrEqual(let value1, let value2):
59+
return "(\"\(value1)\") is greater than (\"\(value2)\")"
60+
case .NotEqual(let value1, let value2):
61+
return "(\"\(value1)\") is equal to (\"\(value2)\")"
62+
case .NotEqualWithAccuracy(let value1, let value2, let accuracy):
63+
return "(\"\(value1)\") is equal to (\"\(value2)\") +/- (\"\(accuracy)\")"
64+
case .Nil:
65+
return "\"notnil\""
66+
case .NotNil: return nil
67+
case .True: return nil
68+
case .False: return nil
69+
case .Fail: return nil
70+
}
71+
}
72+
73+
var failureDescription: String {
74+
switch (name, failureDetails) {
75+
case let (name?, description?):
76+
return "\(name) failed: \(description)"
77+
case let (name?, _):
78+
return "\(name) failed"
79+
default:
80+
return "failed"
81+
}
82+
}
83+
}
84+
85+
private func _XCTAssert(@autoclosure expression: () -> BooleanType, @autoclosure assertion: () -> _XCTAssertion, _ message: String, file: StaticString, line: UInt) {
86+
if !expression().boolValue {
87+
if let test = XCTCurrentTestCase {
88+
test.testFailure(message, failureDescription: assertion().failureDescription, expected: true, file: file, line: line)
89+
}
90+
}
91+
}
92+
1393
/**
14-
The primitive assertion function for XCTest. All other XCTAssert* functions are implemented in terms of this. This function emits a test failure if the general Bool expression passed to it evaluates to false.
94+
This function emits a test failure if the general Bool expression passed to it evaluates to false.
1595
- Parameter expression: A boolean test. If it evaluates to false, the assertion fails and emits a test failure.
16-
- Parameter message: An optional message to use in the failure if the assetion fails. If no message is supplied a default message is used.
96+
- Parameter message: An optional message to use in the failure if the assertion fails.
1797
- Parameter file: The file name to use in the error message if the assertion fails. Default is the file containing the call to this function. It is rare to provide this parameter when calling this function.
1898
- Parameter line: The line number to use in the error message if the assertion fails. Default is the line number of the call to this function in the calling file. It is rare to provide this parameter when calling this function.
1999
*/
20100
public func XCTAssert(@autoclosure expression: () -> BooleanType, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
21-
if !expression().boolValue {
22-
if let test = XCTCurrentTestCase {
23-
test.testFailure(message, expected: true, file: file, line: line)
24-
}
25-
}
101+
XCTAssertTrue(expression, message, file: file, line: line)
26102
}
27103

28104
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> T?, @autoclosure _ expression2: () -> T?, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
29-
XCTAssert(expression1() == expression2(), message, file: file, line: line)
105+
let (value1, value2) = (expression1(), expression2())
106+
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
30107
}
31108

32109
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> ArraySlice<T>, @autoclosure _ expression2: () -> ArraySlice<T>, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
33-
XCTAssert(expression1() == expression2(), message, file: file, line: line)
110+
let (value1, value2) = (expression1(), expression2())
111+
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
34112
}
35113

36114
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> ContiguousArray<T>, @autoclosure _ expression2: () -> ContiguousArray<T>, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
37-
XCTAssert(expression1() == expression2(), message, file: file, line: line)
115+
let (value1, value2) = (expression1(), expression2())
116+
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
38117
}
39118

40119
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> [T], @autoclosure _ expression2: () -> [T], _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
41-
XCTAssert(expression1() == expression2(), message, file: file, line: line)
120+
let (value1, value2) = (expression1(), expression2())
121+
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
42122
}
43123

44124
public func XCTAssertEqual<T, U : Equatable>(@autoclosure expression1: () -> [T : U], @autoclosure _ expression2: () -> [T : U], _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
45-
XCTAssert(expression1() == expression2(), message, file: file, line: line)
125+
let (value1, value2) = (expression1(), expression2())
126+
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
46127
}
47128

48129
public func XCTAssertEqualWithAccuracy<T : FloatingPointType>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, accuracy: T, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
49-
XCTAssert(abs(expression1().distanceTo(expression2())) <= abs(accuracy.distanceTo(T(0))), message, file: file, line: line)
130+
let (value1, value2) = (expression1(), expression2())
131+
_XCTAssert(abs(value1.distanceTo(value2)) <= abs(accuracy.distanceTo(T(0))), assertion: .EqualWithAccuracy(value1, value2, accuracy: accuracy), message, file: file, line: line)
50132
}
51133

52134
public func XCTAssertFalse(@autoclosure expression: () -> BooleanType, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
53-
XCTAssert(!expression().boolValue, message, file: file, line: line)
135+
_XCTAssert(!expression().boolValue, assertion: .False, message, file: file, line: line)
54136
}
55137

56138
public func XCTAssertGreaterThan<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
57-
XCTAssert(expression1() > expression2(), message, file: file, line: line)
139+
let (value1, value2) = (expression1(), expression2())
140+
_XCTAssert(value1 > value2, assertion: .GreaterThan(value1, value2), message, file: file, line: line)
58141
}
59142

60143
public func XCTAssertGreaterThanOrEqual<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
61-
XCTAssert(expression1() >= expression2(), message, file: file, line: line)
144+
let (value1, value2) = (expression1(), expression2())
145+
_XCTAssert(value1 >= value2, assertion: .GreaterThanOrEqual(value1, value2), message, file: file, line: line)
62146
}
63147

64148
public func XCTAssertLessThan<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
65-
XCTAssert(expression1() < expression2(), message, file: file, line: line)
149+
let (value1, value2) = (expression1(), expression2())
150+
_XCTAssert(value1 < value2, assertion: .LessThan(value1, value2), message, file: file, line: line)
66151
}
67152

68153
public func XCTAssertLessThanOrEqual<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
69-
XCTAssert(expression1() <= expression2(), message, file: file, line: line)
154+
let (value1, value2) = (expression1(), expression2())
155+
_XCTAssert(value1 <= value2, assertion: .LessThanOrEqual(value1, value2), message, file: file, line: line)
70156
}
71157

72158
public func XCTAssertNil(@autoclosure expression: () -> Any?, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
73-
XCTAssert(expression() == nil, message, file: file, line: line)
159+
_XCTAssert(expression() == nil, assertion: .Nil, message, file: file, line: line)
74160
}
75161

76162
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> T?, @autoclosure _ expression2: () -> T?, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
77-
XCTAssert(expression1() != expression2(), message, file: file, line: line)
163+
let (value1, value2) = (expression1(), expression2())
164+
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
78165
}
79166

80167
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> ContiguousArray<T>, @autoclosure _ expression2: () -> ContiguousArray<T>, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
81-
XCTAssert(expression1() != expression2(), message, file: file, line: line)
168+
let (value1, value2) = (expression1(), expression2())
169+
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
82170
}
83171

84172
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> ArraySlice<T>, @autoclosure _ expression2: () -> ArraySlice<T>, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
85-
XCTAssert(expression1() != expression2(), message, file: file, line: line)
173+
let (value1, value2) = (expression1(), expression2())
174+
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
86175
}
87176

88177
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> [T], @autoclosure _ expression2: () -> [T], _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
89-
XCTAssert(expression1() != expression2(), message, file: file, line: line)
178+
let (value1, value2) = (expression1(), expression2())
179+
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
90180
}
91181

92182
public func XCTAssertNotEqual<T, U : Equatable>(@autoclosure expression1: () -> [T : U], @autoclosure _ expression2: () -> [T : U], _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
93-
XCTAssert(expression1() != expression2(), message, file: file, line: line)
183+
let (value1, value2) = (expression1(), expression2())
184+
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
94185
}
95186

96187
public func XCTAssertNotEqualWithAccuracy<T : FloatingPointType>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, _ accuracy: T, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
97-
XCTAssert(abs(expression1().distanceTo(expression2())) > abs(accuracy.distanceTo(T(0))), message, file: file, line: line)
188+
let (value1, value2) = (expression1(), expression2())
189+
_XCTAssert(abs(value1.distanceTo(value2)) > abs(accuracy.distanceTo(T(0))), assertion: .NotEqualWithAccuracy(value1, value2, accuracy: accuracy), message, file: file, line: line)
98190
}
99191

100192
public func XCTAssertNotNil(@autoclosure expression: () -> Any?, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
101-
XCTAssert(expression() != nil, message, file: file, line: line)
193+
_XCTAssert(expression() != nil, assertion: .NotNil, message, file: file, line: line)
102194
}
103195

104196
public func XCTAssertTrue(@autoclosure expression: () -> BooleanType, _ message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
105-
XCTAssert(expression().boolValue, message, file: file, line: line)
197+
_XCTAssert(expression().boolValue, assertion: .True, message, file: file, line: line)
106198
}
107199

108200
public func XCTFail(message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
109-
XCTAssert(false, message, file: file, line: line)
201+
_XCTAssert(false, assertion: .Fail, message, file: file, line: line)
110202
}

XCTest/XCTestCase.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ extension XCTestCase {
7777
}
7878

7979
// 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) {
80+
public func testFailure(message: String, failureDescription: String, expected: Bool, file: StaticString, line: UInt) {
8181
if !continueAfterFailure {
8282
assert(false, message, file: file, line: line)
8383
} else {
84-
XCTCurrentFailures.append(XCTFailure(message: message, expected: expected, file: file, line: line))
84+
XCTCurrentFailures.append(XCTFailure(message: message, failureDescription: failureDescription, expected: expected, file: file, line: line))
8585
}
8686
}
8787

XCTest/XCTestMain.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ import Darwin
2020

2121
struct XCTFailure {
2222
var message: String
23+
var failureDescription: String
2324
var expected: Bool
2425
var file: StaticString
2526
var line: UInt
2627

2728
func emit(method: String) {
28-
print("\(file):\(line): \(expected ? "" : "unexpected ")error: \(method) : \(message)")
29+
print("\(file):\(line): \(expected ? "" : "unexpected ")error: \(method) : \(failureDescription) - \(message)")
2930
}
3031
}
3132

0 commit comments

Comments
 (0)