Pruebas Unitarias en Home View Model: Implementación y Validación
Clase 7 de 15 • Curso de Swift Unit Testing
Resumen
La implementación de pruebas unitarias es fundamental para garantizar la calidad y robustez de nuestras aplicaciones iOS. En este artículo, exploraremos cómo probar correctamente un HomeViewModel y sus funciones en Swift, utilizando técnicas de testing asíncronas y simulación de dependencias para verificar el comportamiento esperado de nuestra aplicación.
¿Cómo probar un HomeViewModel y sus funciones?
Cuando desarrollamos aplicaciones siguiendo el patrón MVVM (Model-View-ViewModel), es crucial verificar que nuestros ViewModels funcionen correctamente. Vamos a analizar paso a paso cómo implementar pruebas unitarias para diferentes tipos de funciones en un HomeViewModel.
Probando funciones asíncronas con expectativas
Las funciones asíncronas requieren un enfoque especial para su testing. Veamos cómo probar la función getTotals()
:
- Primero, necesitamos inicializar nuestro ViewModel con un servicio simulado:
func testGetTotals() async {
// Inicialización del ViewModel con un servicio simulado
viewModel = HomeViewModel(databaseService: mockDatabaseService)
// Creación de la expectativa
let expectation = XCTestExpectation(description: "Update totals")
// Ejecución de la función asíncrona
Task {
await viewModel.getTotals()
expectation.fulfill()
}
// Espera a que se cumpla la expectativa
await fulfillment(of: [expectation], timeout: 1.0)
// Verificaciones
XCTAssertEqual(viewModel.totalIncome, 1000)
XCTAssertEqual(viewModel.totalOutcome, 500)
}
En este test:
- Creamos una expectativa que nos permite esperar a que termine la operación asíncrona
- Ejecutamos la función dentro de un Task para manejar la asincronía
- Utilizamos
await fulfillment
para esperar que la expectativa se cumpla - Finalmente, verificamos que los valores se hayan actualizado correctamente
Probando la obtención de registros
Para probar la función que obtiene registros, seguimos un patrón similar:
func testGetRecords() async {
viewModel = HomeViewModel(databaseService: mockDatabaseService)
let expectation = XCTestExpectation(description: "Fetch records")
Task {
await viewModel.getRecords()
expectation.fulfill()
}
await fulfillment(of: [expectation], timeout: 1.0)
XCTAssertGreaterThanOrEqual(viewModel.records.count, 2, "Should have at least 2 records")
}
Es importante verificar que la lista de registros tenga al menos la cantidad esperada según nuestro servicio simulado.
Probando la selección de filtros
La función de selección de filtros también requiere un enfoque asíncrono:
func testFilterSelected() async {
viewModel = HomeViewModel(databaseService: mockDatabaseService)
let expectation = XCTestExpectation(description: "Filter selection")
Task {
viewModel.filterSelected("dmonth")
expectation.fulfill()
}
await fulfillment(of: [expectation], timeout: 1.0)
XCTAssertEqual(viewModel.activeFilter, "dmonth")
XCTAssertEqual(viewModel.records.count, 2)
}
Aquí verificamos que:
- El filtro activo se actualice correctamente
- Los registros se obtengan según el filtro seleccionado
Probando funciones síncronas
Para funciones que no son asíncronas, el enfoque es más directo:
func testGoDetail() {
viewModel = HomeViewModel(databaseService: stopDatabaseService)
let testRecord = Record(id: "test", title: "Test", amount: 100)
viewModel.goDetail(record: testRecord)
XCTAssertGreaterThanOrEqual(viewModel.path.count, 1, "Should have added a path")
XCTAssertEqual(viewModel.path.first, .recordDetail(testRecord), "First path should be record detail")
}
En este caso, no necesitamos expectativas ya que la función es síncrona. Simplemente verificamos que:
- Se haya agregado una ruta a la navegación
- La ruta agregada sea del tipo correcto
Probando la visualización de nuevos registros
Similar al caso anterior:
func testShowNewRecordSheet() {
viewModel = HomeViewModel(databaseService: stopDatabaseService)
viewModel.showNewRecordSheet()
XCTAssertEqual(viewModel.sheetType, .newRecord, "Sheet type should be new record")
}
¿Cómo ejecutar las pruebas de manera eficiente?
Para ejecutar nuestras pruebas, podemos utilizar el atajo de teclado Command+U o seleccionar la opción "Test" en el menú de Xcode. Es recomendable desactivar la paralelización de pruebas si nuestra máquina no tiene suficientes recursos:
- Ve al plan de pruebas
- En "Options", selecciona "Parallelization"
- Marca "Disable"
Esto evitará que se ejecuten múltiples simuladores simultáneamente, lo que podría afectar el rendimiento.
Una vez completadas las pruebas, podemos verificar los resultados en la pestaña con el ícono de verificación (✓) en Xcode, donde veremos un desglose de todas las pruebas ejecutadas y su estado.
Es fundamental que todas nuestras pruebas pasen correctamente para garantizar que nuestro ViewModel funcione como se espera.
La implementación de pruebas unitarias robustas nos permite detectar problemas temprano en el ciclo de desarrollo y nos da confianza al realizar cambios en nuestro código. ¿Has implementado pruebas unitarias en tus proyectos? Comparte tu experiencia en los comentarios y cuéntanos cómo te fue implementando pruebas para los demás ViewModels del proyecto.