Skip to content

Instantly share code, notes, and snippets.

@thijsnado
Last active January 11, 2020 21:58
Show Gist options
  • Save thijsnado/867d69c5cb6e390478dc7fa933e3e296 to your computer and use it in GitHub Desktop.
Save thijsnado/867d69c5cb6e390478dc7fa933e3e296 to your computer and use it in GitHub Desktop.
A collection of useful test extensions which reduce boilerplate in tests.
import XCTest
extension XCTestCase {
// swiftlint:disable unavailable_function
/// A helper function for failing and stoping tests. Marked
///
/// Usage:
/// ~~~
/// guard let value = valueOptional else {
/// failAndStopTests("didn't expect nil")
/// }
/// // rest of test
/// ~~~
///
/// - Parameters:
/// - message: The failure message
/// - file: The file where to report error, defaults to file that called method.
/// - line: The line where to report error, defaults to line that called method.
func failAndStopTests(_ message: String,
file: StaticString = #file,
line: UInt = #line) -> Never {
continueAfterFailure = false
XCTFail(message, file: file, line: line)
// needed to satisfy Never return type, shouldn't be
// reached do to continueAfterFailure being set to false
fatalError("Needed for compiler, will never hit")
}
// swiftlint:enable unavailable_function
/// A helper assertion that can be used to assert an error is thrown in
/// case where error is an equatable error.
///
/// Useage:
/// ~~~
/// assertErrorThrown(sendNetworkingRequest, NetworkingError.notFound)
/// ~~~
///
/// - Parameters:
/// - expression: a throwing expression
/// - expectedError: the expected error
/// - file: the file where error is reported, defaults to file which calls function
/// - line: the line where error is reported, defaults to line which calls function
func assertThrowsError<ErrorType: Error & Equatable, Return>(_ expression: @autoclosure () throws -> Return,
_ expectedError: ErrorType,
file: StaticString = #file,
line: UInt = #line) {
do {
_ = try expression()
XCTFail("Expected function to throw", file: file, line: line)
} catch {
guard let unwrappedError = error as? ErrorType else {
return XCTFail("Expected \(error) to be type \(ErrorType.self)", file: file, line: line)
}
XCTAssertEqual(unwrappedError, expectedError, file: file, line: line)
}
}
/// Using throws in a test gives opaque error messages if error does not inherit
/// from NSError. This one gives a more readable error so it is clearer what
/// error was actually thrown
///
/// Usage:
/// ~~~
/// let value = withBetterCatching(try getValue())
/// // assert something with value
/// ~~~
///
/// - Parameters:
/// - expression: expression which may throw
/// - file: the file in which error will be reported on throw, defaults to file calling function.
/// - line: the line in which error will be reported on throw, defaults to line calling function.
func withBetterCatching<Return>(_ expression: @autoclosure () throws -> Return,
file: StaticString = #file,
line: UInt = #line) -> Return {
do {
return try expression()
} catch {
failAndStopTests("Unexpected error \(error)", file: file, line: line)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment