Skip to content

Introducción al unit testing en JavaScript con Jest

Maximo Martinez Soria

Maximo Martinez Soria

  • 5 min to read

Hacer unit testing, realmente no es tan dificil como parece. Veamos como hacerlo en JavaScript con Jest.

Set up

Antes de empezar, vamos a preparar todo lo que necesitamos.

Adentro de una nueva carpeta, vamos a inicializar npm. En este caso le estoy pasando el flag -y para que no me haga preguntas y asigne todo al valor por default.

npm init -y

Posteriormente, vamos a instalar jest.

Como no necesitamos que sea parte del bundle de producción, vamos a instalarlo como dependencia de desarrollo.

npm install --save-dev jest

Y para poder correr los tests, vamos a crear el comando test en el package.json (o modificarlo si tenés el que viene por default con npm).

Así deberían quedar los scripts en package.json:

"scripts": {
		"test": "jest"
}

Finalmente, vamos a crear el archivo donde vamos a escribir el código y el archivo donde vamos a escribir los tests.

touch fizzbuzz.js
touch fizzbuzz.test.js

FizzBuzz

Con el propósito de centrarnos en la parte técnica de los tests, vamos a crear un programa muy conocido que se llama fizzBuzz. Básicamente consiste en una función que recibe un número y devuelve…

  • Fizz, si el número es divisible por 3.
  • Buzz, si el número es divisible por 5.
  • FizzBuzz, si el número es divisible por 3 y por 5.
  • El mismo número, si el número no es divisible ni por 3 ni por 5.

Como vemos, la funcionalidad a implementar es muy sencilla. Esto está bueno para no tener que pensar en una lógica complicada y poder centrarnos en lo que hoy nos importa: los tests.

El programa consiste en 10 lineas muy sencillas de leer y entender, así que para no perder tiempo, te lo dejo acá:

// fizzbuzz.js
function fizzBuzz(n) {
	const isDivisibleBy3 = n % 3 === 0
	const isDivisibleBy5 = n % 5 === 0

	if (isDivisibleBy3 && isDivisibleBy5) return 'FizzBuzz'
	if (isDivisibleBy3) return 'Fizz'
	if (isDivisibleBy5) return 'Buzz'

	return n
}

module.exports = fizzBuzz

Tests

Llegamos a la parte por la cual vinimos.

La función describe, nos sirve para crear una suite de tests. Recibe un string como primer parámetro que nos sirve para describir qué es lo que testea la suite, y una función como segundo parámetro donde vamos a ir metiendo los tests más adelante.

💡

Una suite de tests, es simplemente un conjunto de tests que testean distintas partes o distintos casos de la misma funcionalidad.

describe('descripción', () => { })

Los tests, se crean con la función it, que es muy similar a describe. Recibe un string como primer parámetro, que nos sirve para describir que cosa específica estamos testeando, y una función como segundo parámetro, que es el test en sí.

Además, vamos a hacer uso de la función expect, que recibe solamente un parámetro. Ese parámetro puede ser de cualquier tipo y es el valor que estamos testeando.

Luego, a la función expect le podemos encadenar otras funciones para verificar que el valor sea el esperado. Esos métodos que le encadenamos a expect, se llaman matchers. Con ellos podemos comprobar cosas como que el valor sea truthy o falsy, que sea mayor o menor a algo, que arroje una excepción, y un largo, largo etc. Para ver la lista completa podés entrar a la documentación de Jest: https://jestjs.io/docs/expect.

Veamos un ejemplo un poco tonto pero que nos va a ayudar a entender todo esto que estuvimos hablando sobre la estructura de los tests:

describe('Testeando true', () => {
	it('should be truthy', () => {
		expect(true).toBeTruthy()
	})

	it('should not be falsy', () => {
		expect(true).not.toBeFalsy()
	})
})

Testeando FizzBuzz

En el archivo fizzbuzz.test.js, vamos a importar nuestra función fizzBuzz y a crear nuestra primera suite de tests.

Vamos a testear que la función fizzBuzz nos devuelva el mismo número que recibió, si dicho número no es divisible ni por 3 ni por 5.

const fizzBuzz = require('./fizzbuzz')

describe('FizzBuzz', () => {
	it('should return number when number is not divisible by either 3 nor 5', () => {
		expect(fizzBuzz(1)).toBe(1)
		expect(fizzBuzz(2)).toBe(2)
	})
})

Como ves, a la función expect le pasamos el resultado que devuelve fizzBuzz y le encadenamos el método toBe.

Con esto estamos diciendo algo así: “Esperamos (expect) que la función fizzBuzz con el parámetro 1, devuelva (toBe) 1”.

Corramos los tests…

npm jest

Y deberían salir todos en verde!

Para terminar, vamos a testear los siguientes 3 casos.

const fizzBuzz = require('./fizzbuzz')

describe('FizzBuzz', () => {
	it('should return number when number is not divisible by either 3 nor 5', () => {
		expect(fizzBuzz(1)).toBe(1)
		expect(fizzBuzz(2)).toBe(2)
	})

	it('should return Fizz when number is divisible by 3', () => {
		expect(fizzBuzz(3)).toBe('Fizz')
		expect(fizzBuzz(6)).toBe('Fizz')
	})

	it('should return Buzz when number is divisible by 5', () => {
		expect(fizzBuzz(5)).toBe('Buzz')
		expect(fizzBuzz(10)).toBe('Buzz')
	})

	it('should return FizzBuzz when number is divisible by both 3 and 5', () => {
		expect(fizzBuzz(15)).toBe('FizzBuzz')
		expect(fizzBuzz(30)).toBe('FizzBuzz')
	})
})

Ahora pasemos los tests a lenguaje humano…

  1. expect(fizzBuzz(3)).toBe('Fizz'): Esperamos (expect) que la función fizzBuzz con el parámetro 3, devuelva (toBe) Fizz
  2. expect(fizzBuzz(5)).toBe('Buzz'): Esperamos (expect) que la función fizzBuzz con el parámetro 5, devuelva (toBe) Buzz
  3. expect(fizzBuzz(15)).toBe('FizzBuzz'): Esperamos (expect) que la función fizzBuzz con el parámetro 15, devuelva (toBe) FizzBuzz

Volvamos a correr los tests para verificar que todo esta pasando:

npm test

Y listo! Creaste tu primera suite de tests.

Conclusión

Espero que este post sirva para desmitificar los tests. Realmente no son tan complicados de hacer como parecen.

La parte más dificil es la estrategia, de la cual podemos hablar en otro post.

Te recomiendo leerte la documentación de Jest y seguir practicando!

Maximo Martinez Soria

Maximo Martinez Soria

Software engineer with deep knowledge on web technologies and the JavaScript ecosystem. Currently spending most of my time developing web apps with React, Node, and Typescript.

Comments:

Leave a comment: