Hola a todos! El curso para
desarrolladores de JavaScript comienza este jueves. En este sentido, decidimos compartir la traducción de otro material interesante. Que tengas una buena lectura.
Jest siempre ha sido mi herramienta de prueba de unidad indispensable. Es tan confiable que empiezo a pensar que siempre lo he infrautilizado. Aunque las pruebas funcionaron, con el tiempo las refactoré aquà y allá, porque no sabÃa que Jest podÃa hacer eso. Cada vez que se trata de un código nuevo cuando reviso la documentación de Jest.
Por lo tanto, voy a compartir algunos de mis trucos favoritos de Jest que algunos de ustedes ya saben porque leyeron la documentación y no me gustaron (vergüenza), pero espero que esto ayude a aquellos que lo revisaron rápidamente !
Por cierto, uso Jest v24.8.0 como material de referencia, asà que tenga cuidado, algunas cosas pueden no funcionar en la versión de Jest que está utilizando actualmente. Además, los ejemplos no representan el código de prueba real, esto es solo una demostración.
# 1 .toBe vs .toEqual
Al principio, todas estas declaraciones me parecieron normales:
expect('foo').toEqual('foo') expect(1).toEqual(1) expect(['foo']).toEqual(['foo'])
Basado en el uso de
chai para declaraciones de igualdad (to.equal), esto es simplemente natural. De hecho, Jest no se quejará, y estas declaraciones pasan como de costumbre.
Sin embargo, Jest tiene .toBe y .toEqual. El primero se usa para afirmar la igualdad usando
Object.is , y el segundo es proporcionar una comparación profunda de objetos y matrices. .toEqual tiene una alternativa al uso de
Object.is si resulta que no necesita una comparación profunda, como afirmar igualdades para valores primitivos, lo que explica por qué el ejemplo anterior fue muy bueno.
expect('foo').toBe('foo') expect(1).toBe(1) expect(['foo']).toEqual(['foo'])
De esa manera, puede omitir todos los
if-else
en
.toEqual
usando
.toBe
si ya sabe qué valores está probando.
Un error común es que usará
.toBe
para afirmar la igualdad de valores primitivos.
expect(['foo']).toBe(['foo'])
Si observa el
código fuente cuando se bloquea .toBe, intentará determinar si realmente cometió este error
llamando a la función que utiliza .toEqual. Esto puede ser un cuello de botella al optimizar su prueba.
Si está seguro de que está utilizando valores primitivos, su código puede reorganizarse como tal para fines de optimización:
expect(Object.is('foo', 'foo')).toBe(true)
Más detalles en la
documentación .
# 2 Comparaciones más adecuadas.
Técnicamente, puede usar
.toBe
para validar cualquier valor. Con Jest, puede usar especÃficamente ciertas herramientas de comparación para hacer que su prueba sea más legible (y en algunos casos más corta).
Estos son solo algunos de los que seleccioné de la larga lista de compiladores de Jest en la documentación, puede ver el resto usted mismo.
# 3 Prueba de instantáneas en elementos sin una interfaz de usuario
Es posible que haya escuchado sobre
las pruebas de instantáneas en Jest , donde ayuda a rastrear los cambios en los elementos de su interfaz de usuario. Pero las pruebas con instantáneas no se limitan a esto.
Considere este ejemplo:
const allEmployees = getEmployees() const happyEmployees = giveIncrementByPosition(allEmployees) expect(happyEmployees[0].nextMonthPaycheck).toBe(1000) expect(happyEmployees[1].nextMonthPaycheck).toBe(5000) expect(happyEmployees[2].nextMonthPaycheck).toBe(4000)
SerÃa agotador si reclamara cada vez más empleados. Además, si resulta que se necesitan más reclamos para cada empleado, multiplique el número de reclamos nuevos por el número de empleados y obtendrá una idea.
Con la prueba de instantáneas, todo esto se puede hacer simplemente asÃ:
const allEmployees = getEmployees() const happyEmployees = giveIncrementByPosition(allEmployees) expect(happyEmployees).toMatchSnapshot()
Siempre que ocurran regresiones, sabrÃa exactamente qué árbol en el nodo no coincide con la imagen.
Pero la conveniencia tiene un precio: este método es más propenso a errores. Existe la posibilidad de que no sepa que la imagen es realmente incorrecta, y al final la tomará de todos modos. Por lo tanto, verifique su instantánea como si fuera su propio código de aprobación (porque lo es).
Por supuesto, las pruebas no se limitan a las instantáneas. Lea la
documentación completa.
# 4 describe.each y test.each
¿Alguna vez has escrito una prueba que sea algo similar a esto?
describe('When I am a supervisor', () => { test('I should have a supervisor badge', () => { const employee = new Employee({ level: 'supervisor' }) expect(employee.badges).toContain('badge-supervisor') }) test('I should have a supervisor level', () => { const employee = new Employee({ level: 'supervisor' }) expect(employee.level).toBe('supervisor') }) }) describe('When I am a manager', () => { test('I should have a manager badge', () => { const employee = new Employee({ level: 'manager' }) expect(employee.badges).toContain('badge-manager') }) test('I should have a manager level', () => { const employee = new Employee({ level: 'manager' }) expect(employee.level).toBe('manager') }) })
Esto es monótono y rutinario, ¿verdad? Imagina hacer esto con muchos casos.
Con
description.each
y
test.each
puede comprimir el código de la siguiente manera:
const levels = [['manager'], ['supervisor']] const privileges = [['badges', 'toContain', 'badge-'], ['level', 'toBe', '']] describe.each(levels)('When I am a %s', (level) => { test.each(privileges)(`I should have a ${level} %s`, (kind, assert, prefix) => { const employee = new Employee({ level }) expect(employee[kind])[assert](`${prefix}${level}`) }) })
Sin embargo, todavÃa tengo que usar esto en mi propia prueba, ya que prefiero que mi prueba sea detallada, pero pensé que serÃa un truco interesante.
Consulte la
documentación para obtener más detalles sobre los argumentos (spoiler: la sintaxis de la tabla es realmente genial).
# 5 Imitación única de funciones globales.
En algún momento, tendrá que probar algo que depende de las funciones globales en un caso de prueba en particular. Por ejemplo, una función que recibe información sobre la fecha actual utilizando el objeto JavaScript de fecha, o una biblioteca que se basa en él. La dificultad es que cuando se trata de la fecha actual, nunca se puede obtener la declaración correcta.
function foo () { return Date.now() } expect(foo()).toBe(Date.now())
Al final, tendrÃa que redefinir el objeto Fecha global para que sea coherente y manejable:
function foo () { return Date.now() } Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
Sin embargo, esto se considera una mala práctica, ya que la redefinición se mantiene entre pruebas. No lo notará si no hay otra prueba basada en Date.now, pero también se filtrará.
test('First test', () => { function foo () { return Date.now() Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
SolÃa ​​"romperlo" para que no goteara:
test('First test', () => { function foo () { return Date.now() const oriDateNow = Date.now Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
Sin embargo, hay una forma mucho mejor y menos hacker de hacer esto:
test('First test', () => { function foo () { return Date.now() jest.spyOn(Date, 'now').mockImplementationOnce(() => 1234567890123) expect(foo()).toBe(1234567890123)
Por lo tanto,
jest.spyOn
sigue al objeto global Date e imita la implementación de la función now para una sola llamada. Esto a su vez dejará Date.now intacto para el resto de las pruebas.
Definitivamente hay más información sobre los talones en Jest. Consulte la
documentación completa para más detalles.
Este artÃculo se está haciendo lo suficientemente largo, asà que creo que eso es todo por ahora. Esto afecta solo una pequeña parte de las capacidades de Jest, y solo destaco mis favoritos. Si tiene otros datos interesantes, hágamelo saber.
Además, si ha usado Jest con frecuencia, consulte
Majestic , que es una GUI sin GUI para Jest, una muy buena alternativa a la salida de terminal aburrida. No estoy seguro si el autor está en dev.to, pero no obstante respeto por esta persona.
Como siempre, ¡gracias por su atención!
Eso es todo. Nos vemos en el curso.