I’ve created a set of two Swift packages that work together, ErrorAssertions and ErrorAssertionExpectations. You can find them on GitHub.
ErrorAssertions
The main benefit of using ErrorAssertions is that you can pass Error
types directly to fatalError()
, assert()
, assertionFailure()
, precondition()
, and preconditionFailure()
. So instead of your code being littered with .localizedDescription
calls, you can take it from this:
doSomething { error in
if let error = error {
fatalError(error.localizedDescription)
}
}
to this:
import ErrorAssertions
doSomething { error in
if let error = error { fatalError(error) }
}
I find this approach much easier to read and write.
ErrorAssertionExpectations
This package is focused on testing. As above, it works with fatalError()
, assert()
, assertionFailure()
, precondition()
, and preconditionFailure()
. ErrorAssertionExpectations allows you to use these assertion methods in code that you test with XCTest without the assertions crashing your test process. To do this, it replaces the implementation of the assertion methods at runtime, so you do need to import ErrorAssertions
on the class you’re testing. The test looks like this:
import ErrorAssertionExpectations
class MyTest: XCTestCase {
func testFatalError() {
expectFatalError { fatalError() }
}
}
You can also use the assertion methods that take Error
types to test for specific errors:
import ErrorAssertionExpectations
class MyTest: XCTestCase {
func testURLError() {
expectPreconditionFailure(expectedError: URLError(.badURL)) {
loadURL("notarealurl")
}
}
}
This lets you test not only that an assertion method was called, but with the correct error, ensuring that you don’t have a false positive and think your code is crashing for the right reasons when it’s really another issue.