Unit Test fatalError in Swift -
how implement unit test fatalerror code path in swift?
for example, i've following swift code
func divide(x: float, y: float) -> float { guard y != 0 else { fatalerror("zero division") } return x / y } i want unit test case when y = 0.
note, want use fatalerror not other assertion function.
the idea replace built-in fatalerror function own, replaced during unit test's execution, run unit test assertions in it.
however, tricky part fatalerror @noreturn, need override function never returns.
override fatalerror
in app target (don't add unit test target):
// overrides swift global `fatalerror` @noreturn func fatalerror(@autoclosure message: () -> string = "", file: staticstring = __file__, line: uint = __line__) { fatalerrorutil.fatalerrorclosure(message(), file, line) unreachable() } /// `noreturn` function pauses forever @noreturn func unreachable() { repeat { nsrunloop.currentrunloop().run() } while (true) } /// utility functions can replace , restore `fatalerror` global function. struct fatalerrorutil { // called custom implementation of `fatalerror`. static var fatalerrorclosure: (string, staticstring, uint) -> () = defaultfatalerrorclosure // backup of original swift `fatalerror` private static let defaultfatalerrorclosure = { swift.fatalerror($0, file: $1, line: $2) } /// replace `fatalerror` global function else. static func replacefatalerror(closure: (string, staticstring, uint) -> ()) { fatalerrorclosure = closure } /// restore `fatalerror` global function original swift implementation static func restorefatalerror() { fatalerrorclosure = defaultfatalerrorclosure } } extension
add following extension unit test target:
extension xctestcase { func expectfatalerror(expectedmessage: string, testcase: () -> void) { // arrange let expectation = expectationwithdescription("expectingfatalerror") var assertionmessage: string? = nil // override fatalerror. pause forever when fatalerror called. fatalerrorutil.replacefatalerror { message, _, _ in assertionmessage = message expectation.fulfill() } // act, perform on separate thead because call fatalerror pauses forever dispatch_async(dispatch_get_global_queue(qos_class_user_initiated, 0), testcase) waitforexpectationswithtimeout(0.1) { _ in // assert xctassertequal(assertionmessage, expectedmessage) // clean fatalerrorutil.restorefatalerror() } } } testcase
class testcase: xctestcase { func testexpectpreconditionfailure() { expectfatalerror("boom!") { dosomethingthatcallsfatalerror() } } } i got idea post unit testing assert , precondition: testing assertion in swift
Comments
Post a Comment