Snapshot Testing
Los tests de instantánea son de gran utilidad cuando se quiere asegurar que la UI no cambia inesperadamente.
Un caso típico de test de instantánea para una aplicación móvil presenta un componente de interfaz, toma una instantánea, y entonces la compara con una imagen referencial guardada al lado del test. El test fallará si las dos imágenes no concuerdan: ya sea porque el cambio es inesperado, o porque la instantánea necesita ser actualizada a la nueva versión del componente de interfaz.
Comprobación Instantánea con Jest #
Se puede tomar un enfoque similar cuando se trata de comprobar tus component de React. En lugar de presentar la interfaz gráfica de usuario, lo cual requeriría construir la app en su totalidad, se puede usar un renderer de tests para rápidamente generar un valor serializable para tu árbol de React. Consider this example test for a simple Link component:
import React from 'react'; import Link from '../Link.react'; import renderer from 'react-test-renderer'; it('renders correctly', () => { const tree = renderer.create( <Link page="http://www.facebook.com">Facebook</Link> ).toJSON(); expect(tree).toMatchSnapshot(); });
The first time this test is run, Jest creates a snapshot file that looks like this:
exports[`renders correctly 1`] = ` <a className="normal" href="http://www.facebook.com" onMouseEnter={[Function]} onMouseLeave={[Function]} > Facebook </a> `;
El artefacto de la instantánea debe ser incluído (commit) con los cambios en el código, y revisado como parte de la revisión de código. Jest utiliza "pretty-format" para crear instantáneas legibles durante la revisión de código. En posteriores ejecuciones de tests, Jest simplemente comparará el resultado renderizado con la instantánea anterior. Si coinciden, pasará el test. Si no coinciden, ya sea porque el "test runner" encontró un "bug" en el código que debe ser arreglado, o la implementación ha cambiado y la instantánea necesita ser actualizada.
Puede encontrarse más información sobre cómo funciona la comprobación de instantánea y por qué la hemos construido en el post de lanzamiento del blog. Recomendamos leer este post del blog para hacerse la idea de cuando se debería usar comprobación de instantánea. We also recommend watching this egghead video on Snapshot Testing with Jest.
Actualizando Instantáneas #
Es muy fácil detectar cuando una prueba de instantánea falla después de introducir un bug. Cuando eso ocurra, siga adelante y arregle el problema, y asegúrese de que sus tests de instantánea se ejecutan con éxito otra vez. A continuación vamos a hablar sobre el caso de cuando un test de instantánea está fallando debido a un cambio intencionado en la implementación.
Tal situación puede presentarse si intencionalmente cambiamos la dirección del enlace del componente Enlace en nuestro ejemplo.
// Test actualizado con un Link hacia un dirección distante en el enlace it('renders correctly', () => { const tree = renderer.create( <Link page="http://www.instagram.com">Instagram</Link> ).toJSON(); expect(tree).toMatchSnapshot(); });
En ese caso, Jest imprimirá esta salida:
Ya que sólo actualizamos nuestro componente para que apunte a una dirección diferente, es razonable esperar cambios en la instantánea de este componente. Nuestro test de instantánea está fallando porque la instantánea de nuestro componente actualizado ya no concuerda con el artefacto de instantáneas para este caso de test.
Para resolver esto, necesitamos actualizar nuestros artefactos de instantánea. Puede ejecutar Jest con un "flag" que le dirá que vuelva a generar las instantáneas:
jest --updateSnapshot
Prosiga y acepte los cambios ejecutando el comando anterior. También puede utilizar equivalente carácter único "flag" -u
para volver a generar instantáneas si lo prefiere. Esto volverá a generar los artefactos de instantánea para todos los tests de instantánea fallidos. Si tuviéramos cualquier test de instantánea fallido adicional debido a un bug no intencionado, necesitaríamos arreglar el "bug" antes de volver a generar instantáneas para impedir grabar instantáneas con un comportamiento defectuoso.
Si se desea limitar que casos de test instantáneos se vuelven a generar, se puede pasar un "flag" adicional: --nombreTestPatrón
para volver a grabar instantáneas sólo para esos tests que coinciden con el patrón.
Se puede probar esta funcionalidad clonando el ejemplo de instantánea, modificando el componente Enlance
, y ejecutando Jest.
Los Tests Deberían Ser Deterministas #
Los tests deben ser deterministas. Es decir, ejecutando los mismos tests multiples veces en un componente que no ha cambiado debería producir los mismos resultados cada vez. Usted es responsable de asegurar que sus instantáneas generadas no incluyen información específica sobre la plataforma o cualquier otra información que no sea determinista.
Por ejemplo, si usted tiene un componente de Reloj que utiliza Date.now()
, la instantánea que se generan a partir de este componente será diferente cada vez que se ejecuta el caso de test. En este caso se puede create un "mock" del método Date.now() para devolver un valor constante cada vez que la prueba se ejecuta:
Date.Now = jest.fn(() = > 1482363367071);
Cada vez que se ejecuta el test de prueba instantánea, Date.now()
devuelve 1482363367071
consistentemente. Esto resultará en la misma instantánea generada para este componente independientemente de cuando se ejecute el test.
Las instantáneas no se escriben automáticamente en los sistemas de Integración Continua (IC) #
A partir de Jest 20, las instantáneas no se escriben automáticamente cuando Jest se ejecuta en un sistema de CI sin pasar explícitamente --updateSnapshot
. Se espera que todas las instantáneas sean parte del código que se ejecuta en el CI, y ya que las nuevas instantáneas pasan automáticamente, no deberían pasar un test ejecutado en un sistema de CI. Se recomienda hacer siempre un "commit" de todas las instantáneas para mantenerlas en el control de versiones.
Preguntas Frecuentes #
¿Deben los archivos de instantáneas ser incluidos en "commits"? #
Sí, todos los archivos de instantánea deben esta en "commits" junto a los módulos que están cubriendo y sus tests. Deberían ser considerados como parte del test, similar al valor de cualquier otra afirmación en Jest. De hecho, las instantáneas representan el estado de los módulos en cualquier momento dado en el tiempo. De esta manera, cuando se modifican los módulos, Jest puede saber lo que cambiado desde la versión anterior. También puede proporcionar mucho contexto adicional durante la revisión del código en la cual los revisores pueden estudiar los cambios mucho mejor.
¿Los tests de instantánea solo funcionan con components de React? #
Los components de React y React Native son un buen caso de uso para tests de instantánea. Sin embargo, las instantáneas pueden capturar cualquier valor serializable y puede usarse en cualquier momento en que el objetivo sea comprobar si el resultado es correcto. El repositorio de Jest contiene muchos ejemplos del "output" de Jest en sí mismo, el "output" de la librería de afirmación de Jest, así como mensajes de "log" de varias partes de la base de código de Jest. See an example of snapshotting CLI output in the Jest repo.
¿Cuál es la diferencia entre tests de instantánea y tests de regresión visual? #
Tests de instantánea y tests de regresión visual son dos maneras distintas de testear interfaces de usuario, y cumplen dos objetivos diferentes. Las herramientas de tests de regresión visual toman capturas de pantalla de páginas web y comparan las imágenes resultantes pixel por pixel. Con tests de instantánea los valores son serializados, guardados en archivos de text y comparados usando un algoritmo de diferenciación. Existen diferentes ventajas y desventajas a tener en cuenta y hemos enumerado las razones por las que los tests de instantánea fueron construídos en el blog de Jest.
¿Substituyen los tests de instantánea a los tests unitarios? #
Los tests de instantánea per-se es sólo una de las más de 20 afirmaciones que están incluidas en Jest. El objetivo de los tests de instantánea no debe reemplazar los tests unitarios ya existentes, sino proporcionar valor adicional a la vez que hace que escribir tests sea menos doloroso. En algunos escenarios, los tests de instantánea pueden potencialmente eliminar la necesidad de tests unitarios para un conjunto particular de funcionalidades (por ejemplo componentes de React), pero también pueden coexistir.
¿Cuál es el rendimiento de tests de instantáneas en cuanto a velocidad y tamaño de los archivos generados? #
Jest ha sido reescrito pensando en rendimiento, y tests de instantánea no es una excepción. Ya que las instantáneas se almacenan en archivos de texto, esta forma de prueba es rápida y fiable. Jest genera un nuevo archivo por cada archivo de test que invoca al marcador toMatchSnapshot
. El tamaño de las instantáneas es bastante pequeño: para referencia, el tamaño de los archivos de instantáneas en Jest en su misma base de código es de menos de 300 KB.
¿Cómo resuelvo conflictos dentro de archivos de instantáneas? #
Los archivos de instantáneas siempre deben representar el estado actual de los módulos que están cubriendo. Por lo tanto, si se están fusionando dos "branches" y se encuentra un conflicto en los archivos de instantáneas, puede o bien resolver el conflicto manualmente o actualizar el archivo de instantánea ejecutando Jest e inspeccionando el resultado.
¿Es posible aplicar los principios de desarrollo orientado a pruebas con tests de instantánea? #
Aunque es posible escribir archivos de instantáneas manualmente, generalmente no es accesible. Las instantáneas ayudan a averiguar si cambia el "output" de los módulos objeto de los tests, en lugar de dar orientación para diseñar el código en primer lugar.
¿Funciona la cobertura de código con tests de instantánea? #
Sí, al igual que con cualquier otro test.