Escribir test de interfaz de usuario es siempre un poco complicado, y muchos desarrolladores acaban por dejar vistas sin testear o dedicando mucho tiempo y esfuerzo en la elaboración de test. Apple dispone de su propio soporte nativo para testing de UI, pero no da soporte para hacer view-based testing. Esta carencia de funcionalidad hace que mucha gente opte por no escribir test dada su dificultad. Por eso en Apiumhub hemos decidido escribir un articulo sobre iOS Snapshot tests. 

 

iOS Snapshot tests

 

View-based testing

View-based testing significa verificar que lo que el usuario ve es lo que queremos nosotros como desarrolladores que el usuario vea. Gracias a este testing podemos garantizar que en diferentes estados o versiones de nuestras vistas se muestran como deberían.

 

iOS Snapshot Tests. ¿Como funcionan?

El snapshot test toma una captura de una UIView or CALayer i usa el método renderInContext el cual realiza una captura de la vista y la compara con la imagen de referencia guardada en nuestro repositorio. El test falla si ambas imágenes no coinciden y entrega una tercera captura mostrando las diferencias.

 

Configuración

La librería fue creada por Facebook (FBSnapshotTestCase) y ahora se ha renombrado a iOSSnapshotTestCase y es mantenida por uber.

El primer paso, como explican en su página de Github, es añadir la librería a nuestro Podfile.

Seguidamente editamos el esquema de nuestro target para añadir el directorio donde se guardarán nuestras capturas de referencia. Para ello añadimos una variable de entorno con la clave FB_REFERENCE_IMAGE_DIR.

spanshot testing

 

Opcionalmente también podemos añadir la clave IMAGE_DIFF_DIR para indicar el directorio donde se guardarán las capturas diferenciales que se generarán en caso de que nuestros test fallen.

 

Implementación

Para ver la implementación vamos a testear un simple viewcontroller que cambiará de aspecto visual dependiendo de un estado.

ios testing implementation


La vista con los dos estados:

snapshot testing configuration

Configuramos nuestra clase de test haciendo que esta sea una subclase de FBSnapshotTestCase en lugar de XCTestCase.

Definimos nuestros tests instanciando el ViewController, asignando el estado y llamando al método FBSnapshotVerifyView.

viewController ios

 

Primero de todo debemos de ejecutar los test con el recordMode activado para que guarde las imágenes de referencia. Para ello introducimos dentro del método de setUp() recordMode = true.

recordmode ios

Al ejecutar los test con recordMode activado, saldrán Fail. Es normal debido a que no tiene aún otra imágen con la que hacer la comparación.

recordmode ios test

Seguidamente comentamos o eliminamos la línea de recordMode para lanzar otra vez los test y ver que pasan.

A partir de ahora si el aspecto visual de la vista cambia como no debería, nuestros test nos notificarán.

Por ejemplo si cambiamos sin querer la dimensión de los iconos el test nos generará una imagen diferencial con los cambios.

icon mobile app ios

He aumentado para el test 20px el tamaño del icono, y en la imágen diferencial se puede ver reflejado el cambio.

 

Ejecutar vistas de manera aislada

Gracias al snapshot testing y a tener las vistas desacopladas podemos instanciar y ejecutar en el simulador un ViewController determinado. Muy útil en para acelerar el proceso de creación de las vistas y reduciendo así el tiempo de desarrollo.

En nuestro didFinishLaunchingWithOptions comprobamos si estamos corriendo test y en ese caso asignamos al rootViewController un UIViewController plano y vacío.

doing ios testing mobile app

En nuestra clase de Test usamos un XCTWaiter con un timeout elevado y asignamos al rootViewController el controller a ejecutar.

rootViewController

Finalmente en el test llamamos al método debugViewController.

De este modo podemos ejecutar la típica vista que está dentro de un largo flow de pantallas de nuestra app de manera sencilla.

Suscríbete a nuestro newsletter para estar al día de desarrollo de aplicaciónes moviles e iOS Snapshot tests en concreto!

 

Si este artículo sobre iOS Snapshot tests te gustó, te puede interesar:

 

F-Bound en Scala

Tendencias en aplicaciónes móviles

Patrón MVP en iOS

Debugging con Charles Proxy en Android emulator

Por qué Kotlin?   

Integración Continua en iOS usando Fastlane y Jenkins  

Cornerjob – iOS objective-C app un caso de exito