Releyendo el libro Diseño Ágil con TDD de Carlos Blé Jurado (que recomiendo ampliamente) y practicando los ejercicios que incluye, he hecho esta extensión de XCTest que es función de test que evalúa 3 cosas:
- que se lance un error
- que el error sea del tipo especificado
- que sea de un caso en específico
1) La cabecera
Primero debemos definir el genérico, en este caso esperamos un Error y que sea Equatable para poder compararlo.
El autoclosure es una técnica que permite esperar a evaluar una expresión hasta el momento en que lo necesitemos.
En este ejemplo, la función es isStrongPassword por que lo expression devuelve un Bool, y necesitamos que espere hasta que sea evaluada por XCTAssertThrowsError
De la que esperamos que lance un error y que sea Equatable para poder hacer los assertions.
Los parámetros file y line permiten saber en que archivo y linea se ha producido el error así que asignamos ese valor por defecto #file y #line.
2)
Esperamos un error y un tipo de error, opcionales (si se llega a producir). Evaluaremos con XCTAssertThrowsError y les asignaremos el error que ha producido y su tipo.
3)
Validamos que efectivamente lance un error expectedError, nuestro propio error, en este caso PasswordError
4)
y además que coincidan el error indicado en la cabecera (expectedError) con el error lanzado por expression
De esta manera al escribir los tests el código es más legible y menos farragoso al tener que evaluar cada caso con XCTAssertThrowsError y en el closure que nos habilita.
Os comparto el código y cualquier mejora es bien recibida.
func XCTAssertThrowsErrorEqual<E: Error & Equatable>(_ expression: @autoclosure () throws -> any Equatable,
_ expectedError: E,
file: StaticString = #file,
line: UInt = #line) {
var thrownError: Error?
var errorType: (any Error.Type)?
XCTAssertThrowsError(try expression()) { error in
thrownError = error
errorType = type(of: error)
}
XCTAssertTrue(thrownError is E,
"Unexpected error type: \(String(describing: errorType)) insted of \(E.Type.self)", file: file, line: line)
if let unwrappedThrownError = thrownError as? E {
XCTAssertEqual(unwrappedThrownError, expectedError,
"Error was not equal to the expected error", file: file, line: line)
}
}
¿Quieres recibir posts, cheatCodes, enlaces y katas en Swift para practicar?
Quincenalmente recibirás en tu correo electrónico la newsletter, solo hace falta tu correo electrónico.