Created
July 10, 2015 19:06
-
-
Save nschum/208b3dde43785afd439a to your computer and use it in GitHub Desktop.
Testing precondition (or assert) in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Our custom drop-in replacement `precondition`. | |
/// | |
/// This will call Swift's `precondition` by default (and terminate the program). | |
/// But it can be changed at runtime to be tested instead of terminating. | |
func precondition(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UWord = __LINE__) { | |
preconditionClosure(condition(), message(), file, line) | |
} | |
/// The actual function called by our custom `precondition`. | |
var preconditionClosure: (Bool, String, StaticString, UWord) -> () = defaultPreconditionClosure | |
let defaultPreconditionClosure = {Swift.precondition($0, $1, file: $2, line: $3)} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
extension XCTestCase { | |
func expectingPreconditionFailure(expectedMessage: String, @noescape block: () -> ()) { | |
let expectation = expectationWithDescription("failing precondition") | |
// Overwrite `precondition` with something that doesn't terminate but verifies it happened. | |
preconditionClosure = { | |
(condition, message, file, line) in | |
if !condition { | |
expectation.fulfill() | |
XCTAssertEqual(message, expectedMessage, "precondition message didn't match", file: file.stringValue, line: line) | |
} | |
} | |
// Call code. | |
block(); | |
// Verify precondition "failed". | |
waitForExpectationsWithTimeout(0.0, handler: nil) | |
// Reset precondition. | |
preconditionClosure = defaultPreconditionClosure | |
} | |
} | |
// example ///////////////////////////////////////////////////////////////////////////////////////// | |
func doSomething() { | |
precondition(false, "just not true") | |
} | |
class TestCase: XCTestCase { | |
func testExpectPreconditionFailure() { | |
expectingPreconditionFailure("just not true") { | |
doSomething(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you very much @nschum for providing your solution. In order to make it work with Swift 5.6 you need to change a few things. I have provided a working version below. I have also done some minor refactoring as of personal preference, which are not required for it to work.
Precondition.swift
XCTest+Precondition.swift
This version can be used like the example @nschum provided.