"Es dif铆cil encontrar un error cuando lo est谩s buscando; es a煤n m谩s dif铆cil cuando supones que el c贸digo est谩 libre de errores."

-- 鉁嶏笍 Steve McConnell

Las pruebas de c贸digo deben ser f谩ciles de preparar y c贸modas de ejecutar. Estas son las cualidades que aporta Jest al mundo del testing. Son pruebas de caja blanca, d贸nde conocemos y tenemos delante el c贸digo que vamos aprobar. Con Jest hacer las pruebas del c贸digo o el c贸digo que supere las pruebas es sencillo y c贸modo. Vamos a verlo por pasos.

Jest

Jest es un framework para pruebas unitarias. Centrado en determinar que todo tu c贸digo es correcto. Para ello vamos a empezar por el principio.

Instalar Jest

Instalarlo es cosa de ni帽os. Partimos de una aplicaci贸n Node y agregamos la dependencia. Puedes hacerlo con npm o con yarn y guardarlo como dependencia principal o para desarrollo.

yarn add jest
npm i --save jest

Y ya est谩. Aunque yo recomiendo agregar unas dependencias extra para facilitar a煤n mas el uso. Incluyo el analizador de c贸digo eslint , el embellecedor prettier y el empaquetador babel (para evitar usar los require de Node). En VSCode tambi茅n activo la extensi贸n orta.vscode-jest para que me ayude en l铆nea.

{"devDependencies": {"@babel/core": "^7.11.5","@babel/preset-env": "^7.11.5","@types/jest": "^26.0.13","babel-jest": "^26.3.0","eslint": "^7.8.1","eslint-config-prettier": "^6.11.0","eslint-plugin-jest": "^23.20.0","eslint-plugin-prettier": "^3.1.4","jest": "^26.4.2","jest-fetch-mock": "^3.0.3","prettier": "^2.1.1"}}

Configuraci贸n

Nada. Como lo oyes, no hay nada que hacer. Simplemente ejecutarlo y listo. Por supuesto que lo puedes adaptar o manipular, pero s贸lo lo haremos cuando lo necesitemos.

Ya, pero quieres saber c贸mo... Pues hay varias opciones; a mi me gusta configurarlo en su propio fichero jest.config.js.

// For a detailed explanation regarding each configuration property, visit:// https://jestjs.io/docs/en/configuration.html
module.exports = {
  verbose: true};

En este caso le he dicho que quiero explicaciones detalladas de lo que va ocurriendo.

Ejecuci贸n

Las pruebas se pueden lanzar desde l铆nea de comandos o mejor escript谩ndolo en el package.json. Algo as铆 es suficiente para empezar.

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

Aqu铆 le decimos que se lancen todas las pruebas, que vigile los cambios para relanzarlas, pero s贸lo aquellas afectadas desde el 煤ltimo commit. Tienes m谩s informaci贸n en la p谩gina dedicada al CLI de Jest

Desarrollo de pruebas con Jest

驴Ejecutar? 驴El qu茅? Pues una especificaci贸n, o en el argot de Jest un fichero tu-prueba.spec.js.

Vamos a realizar un conjunto de pruebas muy sencillo. Es un Hola Mundo en JavaScript, pero un poco mejorado con alg煤n control de argumentos como este:

export function sayHi(userName) {
  if (isNotAString(userName)) {
    throw `What kind of name is ${userName}?`;
  }
  if (isEmpty(userName)) {
    return `I don麓t know your name`;
  }
  return `Hello ${userName}!`;
}

function isNotAString(userName) {
  return typeof userName !== 'string' && !(userName instanceof String);
}

function isEmpty(userName) {
  return userName.length === 0;
}

Ya lo s茅, es muy b谩sico; pero esto es solo un Hola Mundo.

Hola Mundo

import { sayHi } from './0-hello-world';

test('Say Hi', () => {
  expect(sayHi('Jest')).toBe('Hello Jest!');
});

Evidente, 驴no?. Si somos novatos en las pruebas s贸lo tenemos que familiarizarnos con un concepto com煤n a otros frameworks.

Las pruebas se definen como funciones dentro de otras funciones que las ejecutan.

En este caso la funci贸n test(), tambi茅n usable bajo el alias it() es la funci贸n clave de todas tus pruebas Jest.

Es una funci贸n que recibe dos argumentos. El primero es una cadena que describe la prueba y el segundo es otra funci贸n con la prueba en s铆.

Dentro de esa funci贸n interna encontraremos llamadas a m谩s funciones del framework; que casi siempre seguir谩n una sint谩is similar a esta expect(actual).toEqual(expected);

C贸digo cubierto

Al lanzar las pruebas se ejecuta tambi茅n el sujeto de pruebas, el SUT. Pero 驴Cu谩ntas l铆neas se ejercitan? Pues depende de lo cuidadoso que seas al especificar las condiciones y las expectativas. Al porcentaje de l铆neas que se ejecutan sobre el total se le llama cobertura.

En principio una mayor cobertura es un signo de mayor confianza en la prueba. Pero no es determinante. De todas formas se considera que 80% es un buen indicador y Jest te ofrece ese dato y otros muchos.

Como siempre, te sugiero que escriptes todos tus comando de consola.

  {"coverage": "jest src/unit/basic/basic.spec.js --collect-coverage",}

Solicitar el informe de cobertura de c贸digo es as铆 de simple; pero necesita que en la configuraci贸n le especifique qu茅 umbrales consideras aptos. Yo suelo utilizar algo as铆 en el jest.config.js:

En el se incluyen el famoso 80% para l铆neas, ramas condicionales y funciones.

module.exports = {
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80
    },
  },
}

Al s贸lo haber probado el Happy Path vemos que nuestra cobertura deja mucho que desear. As铆 que vamos a帽adiendo pruebas hasta que alcancemos los l铆mites propuestos.

import { sayHi } from './0-hello-world';

test('Say Hi', () => {
  expect(sayHi('Jest')).toBe('Hello Jest!');
  expect(sayHi('')).toBe('I don麓t know your name');
  expect(() => sayHi(42)).toThrow('What kind of name is 42?');
});

Si est谩s empezando con las pruebas no te obsesiones con esta m茅trica. Cada test que hagas estar谩s m谩s cerca del objetivo: tener confianza en tu c贸digo y dormir tranquilamente.

Tienes el ejemplo completo en el laboratorio del curso de Testing con Jest.