Skip to content

Commit de4938d

Browse files
committed
Refactor messaging further.
Rather than have the _XCTAssertion enum carry the asserted values and generate the message, use a new _XCTAssertionResult to indicate success or failure and have it carry the message and generate the full failure description. This is necessary to be able to use an _XCTAssertion to generate an assertion name in a context where the values aren't necessarily available, and also puts the assertion failure messages back in the assertions themselves. Reviewed by @mike-ferris-apple.
1 parent 8d1940d commit de4938d

File tree

1 file changed

+200
-84
lines changed

1 file changed

+200
-84
lines changed

Sources/XCTest/XCTAssert.swift

Lines changed: 200 additions & 84 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
@@ -11,15 +11,15 @@
1111
//
1212

1313
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(Any)
14+
case Equal
15+
case EqualWithAccuracy
16+
case GreaterThan
17+
case GreaterThanOrEqual
18+
case LessThan
19+
case LessThanOrEqual
20+
case NotEqual
21+
case NotEqualWithAccuracy
22+
case Nil
2323
case NotNil
2424
case True
2525
case False
@@ -42,50 +42,41 @@ private enum _XCTAssertion {
4242
case .Fail: return nil
4343
}
4444
}
45+
}
4546

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(let value):
65-
return "\"\(value)\""
66-
case .NotNil: return nil
67-
case .True: return nil
68-
case .False: return nil
69-
case .Fail: return nil
47+
private enum _XCTAssertionResult {
48+
case Success
49+
case ExpectedFailure(String?)
50+
51+
func failureDescription(assertion: _XCTAssertion) -> String {
52+
let explanation: String
53+
switch (self) {
54+
case .Success:
55+
explanation = "passed"
56+
case .ExpectedFailure(let details?):
57+
explanation = "failed: \(details)"
58+
case .ExpectedFailure(_):
59+
explanation = "failed"
7060
}
71-
}
7261

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"
62+
if let name = assertion.name {
63+
return "\(name) \(explanation)"
64+
} else {
65+
return explanation
8166
}
8267
}
8368
}
8469

85-
private func _XCTAssert(@autoclosure expression: () -> BooleanType, @autoclosure assertion: () -> _XCTAssertion, @autoclosure _ message: () -> String, file: StaticString, line: UInt) {
86-
if !expression().boolValue {
70+
private func _XCTEvaluateAssertion(assertion: _XCTAssertion, @autoclosure message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__, @noescape expression: () -> _XCTAssertionResult) {
71+
let result = expression()
72+
73+
switch result {
74+
case .Success:
75+
return
76+
77+
default:
8778
if let handler = XCTFailureHandler {
88-
handler(XCTFailure(message: message(), failureDescription: assertion().failureDescription, expected: true, file: file, line: line))
79+
handler(XCTFailure(message: message(), failureDescription: result.failureDescription(assertion), expected: true, file: file, line: line))
8980
}
9081
}
9182
}
@@ -150,102 +141,227 @@ public func XCTAssert(@autoclosure expression: () -> BooleanType, @autoclosure _
150141
}
151142

152143
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> T?, @autoclosure _ expression2: () -> T?, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
153-
let (value1, value2) = (expression1(), expression2())
154-
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
144+
_XCTEvaluateAssertion(.Equal, message: message, file: file, line: line) {
145+
let (value1, value2) = (expression1(), expression2())
146+
if value1 == value2 {
147+
return .Success
148+
} else {
149+
return .ExpectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\")")
150+
}
151+
}
155152
}
156153

157154
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> ArraySlice<T>, @autoclosure _ expression2: () -> ArraySlice<T>, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
158-
let (value1, value2) = (expression1(), expression2())
159-
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
155+
_XCTEvaluateAssertion(.Equal, message: message, file: file, line: line) {
156+
let (value1, value2) = (expression1(), expression2())
157+
if value1 == value2 {
158+
return .Success
159+
} else {
160+
return .ExpectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\")")
161+
}
162+
}
160163
}
161164

162165
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> ContiguousArray<T>, @autoclosure _ expression2: () -> ContiguousArray<T>, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
163-
let (value1, value2) = (expression1(), expression2())
164-
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
166+
_XCTEvaluateAssertion(.Equal, message: message, file: file, line: line) {
167+
let (value1, value2) = (expression1(), expression2())
168+
if value1 == value2 {
169+
return .Success
170+
} else {
171+
return .ExpectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\")")
172+
}
173+
}
165174
}
166175

167176
public func XCTAssertEqual<T : Equatable>(@autoclosure expression1: () -> [T], @autoclosure _ expression2: () -> [T], @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
168-
let (value1, value2) = (expression1(), expression2())
169-
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
177+
_XCTEvaluateAssertion(.Equal, message: message, file: file, line: line) {
178+
let (value1, value2) = (expression1(), expression2())
179+
if value1 == value2 {
180+
return .Success
181+
} else {
182+
return .ExpectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\")")
183+
}
184+
}
170185
}
171186

172187
public func XCTAssertEqual<T, U : Equatable>(@autoclosure expression1: () -> [T : U], @autoclosure _ expression2: () -> [T : U], @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
173-
let (value1, value2) = (expression1(), expression2())
174-
_XCTAssert(value1 == value2, assertion: .Equal(value1, value2), message, file: file, line: line)
188+
_XCTEvaluateAssertion(.Equal, message: message, file: file, line: line) {
189+
let (value1, value2) = (expression1(), expression2())
190+
if value1 == value2 {
191+
return .Success
192+
} else {
193+
return .ExpectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\")")
194+
}
195+
}
175196
}
176197

177198
public func XCTAssertEqualWithAccuracy<T : FloatingPointType>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, accuracy: T, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
178-
let (value1, value2) = (expression1(), expression2())
179-
_XCTAssert(abs(value1.distanceTo(value2)) <= abs(accuracy.distanceTo(T(0))), assertion: .EqualWithAccuracy(value1, value2, accuracy: accuracy), message, file: file, line: line)
199+
_XCTEvaluateAssertion(.EqualWithAccuracy, message: message, file: file, line: line) {
200+
let (value1, value2) = (expression1(), expression2())
201+
if abs(value1.distanceTo(value2)) <= abs(accuracy.distanceTo(T(0))) {
202+
return .Success
203+
} else {
204+
return .ExpectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\") +/- (\"\(accuracy)\")")
205+
}
206+
}
180207
}
181208

182209
public func XCTAssertFalse(@autoclosure expression: () -> BooleanType, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
183-
_XCTAssert(!expression().boolValue, assertion: .False, message, file: file, line: line)
210+
_XCTEvaluateAssertion(.False, message: message, file: file, line: line) {
211+
let value = expression()
212+
if !value.boolValue {
213+
return .Success
214+
} else {
215+
return .ExpectedFailure(nil)
216+
}
217+
}
184218
}
185219

186220
public func XCTAssertGreaterThan<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
187-
let (value1, value2) = (expression1(), expression2())
188-
_XCTAssert(value1 > value2, assertion: .GreaterThan(value1, value2), message, file: file, line: line)
221+
_XCTEvaluateAssertion(.GreaterThan, message: message, file: file, line: line) {
222+
let (value1, value2) = (expression1(), expression2())
223+
if value1 > value2 {
224+
return .Success
225+
} else {
226+
return .ExpectedFailure("(\"\(value1)\") is not greater than (\"\(value2)\")")
227+
}
228+
}
189229
}
190230

191231
public func XCTAssertGreaterThanOrEqual<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
192-
let (value1, value2) = (expression1(), expression2())
193-
_XCTAssert(value1 >= value2, assertion: .GreaterThanOrEqual(value1, value2), message, file: file, line: line)
232+
_XCTEvaluateAssertion(.GreaterThanOrEqual, message: message, file: file, line: line) {
233+
let (value1, value2) = (expression1(), expression2())
234+
if value1 >= value2 {
235+
return .Success
236+
} else {
237+
return .ExpectedFailure("(\"\(value1)\") is less than (\"\(value2)\")")
238+
}
239+
}
194240
}
195241

196242
public func XCTAssertLessThan<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
197-
let (value1, value2) = (expression1(), expression2())
198-
_XCTAssert(value1 < value2, assertion: .LessThan(value1, value2), message, file: file, line: line)
243+
_XCTEvaluateAssertion(.LessThan, message: message, file: file, line: line) {
244+
let (value1, value2) = (expression1(), expression2())
245+
if value1 < value2 {
246+
return .Success
247+
} else {
248+
return .ExpectedFailure("(\"\(value1)\") is not less than (\"\(value2)\")")
249+
}
250+
}
199251
}
200252

201253
public func XCTAssertLessThanOrEqual<T : Comparable>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
202-
let (value1, value2) = (expression1(), expression2())
203-
_XCTAssert(value1 <= value2, assertion: .LessThanOrEqual(value1, value2), message, file: file, line: line)
254+
_XCTEvaluateAssertion(.LessThanOrEqual, message: message, file: file, line: line) {
255+
let (value1, value2) = (expression1(), expression2())
256+
if value1 <= value2 {
257+
return .Success
258+
} else {
259+
return .ExpectedFailure("(\"\(value1)\") is greater than (\"\(value2)\")")
260+
}
261+
}
204262
}
205263

206264
public func XCTAssertNil(@autoclosure expression: () -> Any?, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
207-
let value = expression()
208-
_XCTAssert(value == nil, assertion: value == nil ? .Nil(()) : .Nil(value!), message, file: file, line: line)
265+
_XCTEvaluateAssertion(.Nil, message: message, file: file, line: line) {
266+
let value = expression()
267+
if value == nil {
268+
return .Success
269+
} else {
270+
return .ExpectedFailure("\"\(value)\"")
271+
}
272+
}
209273
}
210274

211275
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> T?, @autoclosure _ expression2: () -> T?, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
212-
let (value1, value2) = (expression1(), expression2())
213-
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
276+
_XCTEvaluateAssertion(.NotEqual, message: message, file: file, line: line) {
277+
let (value1, value2) = (expression1(), expression2())
278+
if value1 != value2 {
279+
return .Success
280+
} else {
281+
return .ExpectedFailure("(\"\(value1)\") is equal to (\"\(value2)\")")
282+
}
283+
}
214284
}
215285

216286
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> ContiguousArray<T>, @autoclosure _ expression2: () -> ContiguousArray<T>, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
217-
let (value1, value2) = (expression1(), expression2())
218-
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
287+
_XCTEvaluateAssertion(.NotEqual, message: message, file: file, line: line) {
288+
let (value1, value2) = (expression1(), expression2())
289+
if value1 != value2 {
290+
return .Success
291+
} else {
292+
return .ExpectedFailure("(\"\(value1)\") is equal to (\"\(value2)\")")
293+
}
294+
}
219295
}
220296

221297
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> ArraySlice<T>, @autoclosure _ expression2: () -> ArraySlice<T>, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
222-
let (value1, value2) = (expression1(), expression2())
223-
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
298+
_XCTEvaluateAssertion(.NotEqual, message: message, file: file, line: line) {
299+
let (value1, value2) = (expression1(), expression2())
300+
if value1 != value2 {
301+
return .Success
302+
} else {
303+
return .ExpectedFailure("(\"\(value1)\") is equal to (\"\(value2)\")")
304+
}
305+
}
224306
}
225307

226308
public func XCTAssertNotEqual<T : Equatable>(@autoclosure expression1: () -> [T], @autoclosure _ expression2: () -> [T], @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
227-
let (value1, value2) = (expression1(), expression2())
228-
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
309+
_XCTEvaluateAssertion(.NotEqual, message: message, file: file, line: line) {
310+
let (value1, value2) = (expression1(), expression2())
311+
if value1 != value2 {
312+
return .Success
313+
} else {
314+
return .ExpectedFailure("(\"\(value1)\") is equal to (\"\(value2)\")")
315+
}
316+
}
229317
}
230318

231319
public func XCTAssertNotEqual<T, U : Equatable>(@autoclosure expression1: () -> [T : U], @autoclosure _ expression2: () -> [T : U], @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
232-
let (value1, value2) = (expression1(), expression2())
233-
_XCTAssert(value1 != value2, assertion: .NotEqual(value1, value2), message, file: file, line: line)
320+
_XCTEvaluateAssertion(.NotEqual, message: message, file: file, line: line) {
321+
let (value1, value2) = (expression1(), expression2())
322+
if value1 != value2 {
323+
return .Success
324+
} else {
325+
return .ExpectedFailure("(\"\(value1)\") is equal to (\"\(value2)\")")
326+
}
327+
}
234328
}
235329

236330
public func XCTAssertNotEqualWithAccuracy<T : FloatingPointType>(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, _ accuracy: T, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
237-
let (value1, value2) = (expression1(), expression2())
238-
_XCTAssert(abs(value1.distanceTo(value2)) > abs(accuracy.distanceTo(T(0))), assertion: .NotEqualWithAccuracy(value1, value2, accuracy: accuracy), message, file: file, line: line)
331+
_XCTEvaluateAssertion(.NotEqualWithAccuracy, message: message, file: file, line: line) {
332+
let (value1, value2) = (expression1(), expression2())
333+
if abs(value1.distanceTo(value2)) > abs(accuracy.distanceTo(T(0))) {
334+
return .Success
335+
} else {
336+
return .ExpectedFailure("(\"\(value1)\") is equal to (\"\(value2)\") +/- (\"\(accuracy)\")")
337+
}
338+
}
239339
}
240340

241341
public func XCTAssertNotNil(@autoclosure expression: () -> Any?, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
242-
_XCTAssert(expression() != nil, assertion: .NotNil, message, file: file, line: line)
342+
_XCTEvaluateAssertion(.Nil, message: message, file: file, line: line) {
343+
let value = expression()
344+
if value != nil {
345+
return .Success
346+
} else {
347+
return .ExpectedFailure(nil)
348+
}
349+
}
243350
}
244351

245352
public func XCTAssertTrue(@autoclosure expression: () -> BooleanType, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
246-
_XCTAssert(expression().boolValue, assertion: .True, message, file: file, line: line)
353+
_XCTEvaluateAssertion(.True, message: message, file: file, line: line) {
354+
let value = expression()
355+
if value.boolValue {
356+
return .Success
357+
} else {
358+
return .ExpectedFailure(nil)
359+
}
360+
}
247361
}
248362

249363
public func XCTFail(message: String = "", file: StaticString = __FILE__, line: UInt = __LINE__) {
250-
_XCTAssert(false, assertion: .Fail, message, file: file, line: line)
364+
_XCTEvaluateAssertion(.Fail, message: message, file: file, line: line) {
365+
return .ExpectedFailure(nil)
366+
}
251367
}

0 commit comments

Comments
 (0)