Testing con Swift Testing
El nuevo framework de tests de Apple: @Test y #expect, más expresivo y moderno que XCTest. Prueba tu lógica con confianza y duerme tranquilo al publicar.
Los tests no son burocracia: son la red que te deja cambiar código sin miedo. Swift Testing, el framework moderno de Apple, hace escribirlos casi agradable, con una sintaxis limpia que aprovecha las macros. Si inyectaste bien tus dependencias (lección anterior), probar es fácil.
- Escribir tests con
@Testy#expect. - Verificar condiciones y desenvolver con
#require. - Organizar tests en suites.
- Qué probar (y qué no).
Un test con @Test y #expect
Swift Testing usa la macro @Test para marcar una función de test y #expect para las comprobaciones:
import Testing
@Test func laSumaFunciona() {
let resultado = 2 + 3
#expect(resultado == 5)
}
@Test func elFiltroDejaSoloPendientes() {
let modelo = BibliotecaModel()
modelo.libros = [Libro(titulo: "A", leido: true),
Libro(titulo: "B", leido: false)]
#expect(modelo.pendientes.count == 1)
#expect(modelo.pendientes.first?.titulo == "B")
}
#expect toma cualquier expresión booleana. Si falla, el mensaje de error muestra los valores reales — sabes al instante qué esperaba y qué obtuvo.
En XCTest tenías una función distinta para cada comparación (XCTAssertEqual, XCTAssertTrue, XCTAssertNil…). Swift Testing tiene una sola: #expect(cualquier condición). Y como es una macro, cuando falla descompone la expresión y te enseña el valor de cada parte. #expect(usuario.edad == 18) fallido te dice “esperaba 18, era 25”, sin que escribas nada extra. Menos API que memorizar, mejores mensajes de error. Es el tipo de mejora que hace que de verdad quieras escribir tests.
#require: desenvolver o fallar
Cuando algo debe existir para que el test siga, #require lo desenvuelve y falla limpiamente si es nil:
@Test func elPrimerLibroTieneTitulo() throws {
let modelo = BibliotecaModel()
modelo.libros = [Libro(titulo: "Swift", leido: false)]
let primero = try #require(modelo.libros.first) // falla si es nil
#expect(primero.titulo == "Swift")
}
Parámetros y suites
Prueba muchos casos con un solo test parametrizado, y agrupa tests relacionados en una struct suite:
@Test(arguments: [1, 2, 3, 100])
func todoNumeroPositivoEsMayorQueCero(_ n: Int) {
#expect(n > 0)
}
struct PruebasCarrito {
@Test func empiezaVacio() {
#expect(CarritoModel().items.isEmpty)
}
}
El test parametrizado corre una vez por argumento — un solo test cubre cuatro casos.
Qué probar (y qué no)
Prueba la lógica
Cálculos, filtros, validaciones, transformaciones, tu capa de datos. Aquí viven los bugs y aquí rinden los tests.
Prueba con dependencias falsas
Inyecta servicios falsos (lección 6.2) para probar sin red ni base de datos real.
No pruebes el framework
No hace falta comprobar que SwiftUI dibuja un Text. Confía en Apple; prueba lo tuyo.
La recompensa real de los tests no es “encontrar bugs hoy”: es poder cambiar el código mañana con confianza. Cuando refactorices una función o migres a una API nueva, una suite verde te dice al instante si rompiste algo. Sin tests, cada cambio es una apuesta; con ellos, es una operación segura. Esa tranquilidad, especialmente antes de publicar, no tiene precio.
- Escribe un
@Testcon#expectpara una función pura tuya. - Prueba un método de un modelo
@Observable(p. ej. un filtro). - Usa
#requirepara desenvolver un opcional en un test. - Escribe un test parametrizado con
@Test(arguments:). - Inyecta un servicio falso y prueba un modelo sin tocar la red.