Testing en Javascript con JEST. Parte 1 de 2

¿Por qué hacer testing en Javascript?

El ser humano evoluciona y aprende usando el método heurístico también conocido como prueba y error.

Básicamente consiste en probar un procedimiento y comprobar si funciona. Si no funciona se prueba otra alternativa y si funciona se toma como solución.

En el sector informático/tecnológico es donde la necesidad de realizar pruebas se convierte en una parte importante del desarrollo, ya que el ritmo al que se trabaja en este sector es muy alto, y esto es debido en gran medida a la demanda de los clientes/consumidores por tener nuevas y/o mejores funcionalidades.

Todo esto implica que en muchas ocasiones se deban lanzar al mercado versiones de software en un tiempo reducido y con algunos fallos, pero es el precio que se tiene que pagar en algunas ocasiones.

Para intentar no tener esos fallos y solucionar ese porcentaje de errores, dentro del ciclo de desarrollo del software tenemos la fase de el testing.

Es una fase tan importante que debería realizarse  al comienzo del proceso para evitar que los errores se acumulen en la fase final.

Algunos de los puntos importantes que ofrece la fase de testing son los siguientes

  • Nos permite identificar los errores que han ocurrido en la fase del desarrollo.
  • Tener una buena calidad en el software desarrollado.
  • Minimizamos el mantenimiento y los coste asociados cuando el desarrollo esta muy avanzado.
  • Garantizamos que el software es fiable.

Como programador debemos asumir que desarrollar software libre de errores es una tarea muy complicada y casi imposible, pero con el testing nos acercamos a ese imposible.

¿Qué son las pruebas Unitarias?

Las pruebas unitarias son la forma de comprobar pequeñas unidades de código (bloques de código) y así saber que esta funcionando correctamente.

Las pruebas unitarias comprueban casos estándares (suposición explícita) es decir, no son perfectas.

Las características de las pruebas unitarias son:

  • Automatizable: Deben funcionar sin ningún proceso manual.
  • Total Cobertura: Debemos de pasar por cada bloque escrito.
  • Reutilizables: Podemos usarlas para probar otros bloques.
  • Independientes: No pueden depender de otra prueba para funcionar.
  • Rápidas de crear: Deben de ser algo conciso y que prueben algo muy particular.

Debemos tener en cuenta que realizando el testing lo que estamos asegurando es que nuestro código funcione correctamente, no que la lógica de negocio o el procedimiento sea correcto.

Configurando el entorno de trabajo

Para realizar la fase de testing existen múltiples framewors como Jasmine, Mocha, AVA, Tape, Jest, pero en este caso voy a usar el framework JEST

Jest es un framework creado por Facebook y mantenido por la comunidad con apoyo de Facebook. Es fácil de instalar y no requiere de una configuración muy compleja para poder añadirlo en nuestros proyectos.

Para realizar nuestras pruebas de testing vamos ha crear un proyecto y así poder probar todo lo que necesitemos.

Lo primero que debemos hacer es iniciar nuestro proyecto con el siguiente comando: npm init npm init -y

La diferencia entre un comando u otro, es que la sin opción -y nos pedirá ciertos datos para nuestro proyecto y con la opción usara los datos por defecto.

En ambos caso nos creara el fichero package.json

package.json

{
  "name": "JEST",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Con el proyecto iniciado vamos a instalar Jest, y para eso usaremos npm con el siguiente comando: npm i -D jest.

Ya podemos usar Jest, pero como queremos aprovechar las características de javascript (ES6) para nuestros test, debemos instalar otras dependencias: npm i -D babel-jest babel-polify npm i -D babel-preset-es2015.

Con todas las dependencias instaladas podemos comprobar que nuestro package.json a cambiado:

{
  "name": "JEST",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-jest": "^23.6.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "jest": "^23.6.0"
  }
}

Ahora si, con todas las dependencias instaladas vamos a configurar babel para que entienda ES6.

Crearemos un fichero con el nombre .babelrc donde añadiremos la configuración necesaria:

.babelrc

{
    "presets": ["es2015"]
}

Primera prueba unitaria

Lo primero que vamos hacer es crear un fichero con el código javascript, ya que este sera el código donde realizaremos los test.

Para este ejemplo voy a crear un fichero llamado index.js

export const sumar = (a, b) => a + b;
export const restar = (a, b) => a - b;
export const multiplicar = (a, b) => a * b;
export const dividir = (a, b) => a / b;

Continuamos creando una carpeta en nuestro proyecto llamada test, ya que allí guardaremos todos nuestros test.

Una vez dentro de la carpeta test crearemos un fichero y lo llamaremos igual que el fichero donde esta el código javascript que vamos a realizar el test, seguido de .test.

El fichero quedaría de la siguiente forma: index.test.js

import { sumar, restar, multiplicar, dividir } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});

Con nuestro fichero ya creado vamos a ejecutar el test, y para eso crearemos una tarea en la sección scripts dentro del package.json:

{
  "name": "JEST",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-jest": "^23.6.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "jest": "^23.6.0"
  }
}

Ahora solo queda ejecutar nuestro test, y para ello usaremos la tarea que habíamos creado en el package.json usando el siguiente comando: npm run test (test es el nombre del key asociado al comando que ejecutara) o npm t (forma abreviada).

Si todo funciona correctamente deberíamos ver en la pantalla el siguiente resultado:

jest

 PASS  test/index.test.js
  Operaciones matemáticas
    √ Realizamos la suma (2ms)
    √ Realizamos la resta
    √ Realizamos la multiplicacion
    √ Realizamos la division

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        1.465s
Ran all test suites.

Matchers

Jest usa los matchers para probar los diferentes valores que puede tener nuestro código.

En nuestro ejemplo voy a usar algunos y así entender como funcionan los test.

Si quieres tener mas detalles o conocer todos los matchers que ofrece jest puedes pulsar aquí para ir a la documentación oficial.

Para el siguiente ejemplo hemos usado los siguientes matchers:

  • .toBe: Usado para comparar valores primitivos
  • .toEqual: Usado para comparar recursívamente todas las propiedades de un objetos, también conocido como igualdad profunda.

index.test.js

import { sumar, restar, multiplicar, dividir } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});
describe('Common matchers', () => {
    const datos = {
        nombre: 'Persona 1',
        edad: 10
    }
    const datos2 = {
        nombre: 'Persona 1',
        edad: 10
    }
    test('Comprobamos que los objectos son iguales', () => {
        expect(datos).toEqual(datos2);
    });
});

Con los matchers anteriores hemos realizado los test sobre un objeto y sobre un valor primitivo que debería ser.

¿Que ocurre si queremos evaluar el test y comprobar si el valor es igual, superior o inferior?, pues jest tiene unos métodos para esa tarea.

  • toBeLessThan: El valor es menor que.
  • toBeLessThanOrEqual: El valor es menor o igual que.
  • toBeGreaterThanOrEqual: El valor es mayor o igual que.
  • toBeGreaterThan: El valor es mayor que.

index.test.js

import { sumar, restar, multiplicar, dividir } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});
describe('Common matchers', () => {
    const datos = {
        nombre: 'Persona 1',
        edad: 10
    }
    const datos2 = {
        nombre: 'Persona 1',
        edad: 10
    }
    test('Comprobamos que los objectos son iguales', () => {
        expect(datos).toEqual(datos2);
    });
});
describe('Matchers numéricos', () => {
    test('Resultado menor que...', () => {
        expect(restar(5,3)).toBeLessThan(3);
    });
    test('Resultado menor o igual que...', () => {
        expect(restar(5,3)).toBeLessThanOrEqual(2);
    });
    test('Resultado mayor o igual que...', () => {
        expect(multiplicar(2,5)).toBeGreaterThanOrEqual(10);
    });
    test('Resultado mayor que...', () => {
        expect(sumar(5,5)).toBeGreaterThan(9);
    });
});

Ahora vamos a crear un test para comprobar los valores boolean, undefined o null, y como en los ejemplos anteriores jest tiene unos métodos para ello.

  • toBeTruthy: El valor es verdadero.
  • toBeFalsy: El valor es falso.
  • toBeUndefined: El valor es ‘undefined’
  • toBeNull: El valor es ‘null’

index.js

export const sumar = (a, b) => a + b;
export const restar = (a, b) => a - b;
export const multiplicar = (a, b) => a * b;
export const dividir = (a, b) => a / b;
export const isNull = () => null;
export const isFalse = () => false;
export const isTrue = () => true;
export const isUndefined = () => undefined;

index.test.js

import { sumar, restar, multiplicar, dividir, isFalse, isNull, isTrue, isUndefined } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});
describe('Common matchers', () => {
    const datos = {
        nombre: 'Persona 1',
        edad: 10
    }
    const datos2 = {
        nombre: 'Persona 1',
        edad: 10
    }
    test('Comprobamos que los objectos son iguales', () => {
        expect(datos).toEqual(datos2);
    });
});
describe('Numeric matchers', () => {
    test('Resultado menor que...', () => {
        expect(restar(5,3)).toBeLessThan(3);
    });
    test('Resultado menor o igual que...', () => {
        expect(restar(5,3)).toBeLessThanOrEqual(2);
    });
    test('Resultado mayor o igual que...', () => {
        expect(multiplicar(2,5)).toBeGreaterThanOrEqual(10);
    });
    test('Resultado mayor que...', () => {
        expect(sumar(5,5)).toBeGreaterThan(9);
    });
});
describe('Matchers Boolean, Undefined o Null', () => {
    test('Resultado true', () => {
        expect(isTrue()).toBeTruthy();
    });
    test('Resultado false', () => {
        expect(isFalse()).toBeFalsy();
    });
    test('Resultado undefined', () => {
        expect(isUndefined()).toBeUndefined();
    });
    test('Resultado null', () => {
        expect(isNull()).toBeNull();
    });
});

Para continuar vamos a realizar testing sobre arrays, y para ello jest tiene algunos métodos.

  • .toContain: Contiene el elemento dentro del array
  • .toHaveLength: El array tiene la longitud

index.js

const provincias = ['Álava','Badajoz','Cáceres','Girona','Huelva','Jaén','La Rioja','Madrid','Navarra'];
const dias = ['Lunes','Martes','Miercoles','Jueves','Viernes','Sabado','Domingo'];
export const sumar = (a, b) => a + b;
export const restar = (a, b) => a - b;
export const multiplicar = (a, b) => a * b;
export const dividir = (a, b) => a / b;
export const isNull = () => null;
export const isFalse = () => false;
export const isTrue = () => true;
export const isUndefined = () => undefined;
export const arrProvincias = () => provincias;
export const arrDias = () => dias;

index.test.js

import { sumar, restar, multiplicar, dividir, isFalse, isNull, isTrue, isUndefined, arrDias, arrProvincias } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});
describe('Common matchers', () => {
    const datos = {
        nombre: 'Persona 1',
        edad: 10
    }
    const datos2 = {
        nombre: 'Persona 1',
        edad: 10
    }
    test('Comprobamos que los objectos son iguales', () => {
        expect(datos).toEqual(datos2);
    });
});
describe('Numeric matchers', () => {
    test('Resultado menor que...', () => {
        expect(restar(5,3)).toBeLessThan(3);
    });
    test('Resultado menor o igual que...', () => {
        expect(restar(5,3)).toBeLessThanOrEqual(2);
    });
    test('Resultado mayor o igual que...', () => {
        expect(multiplicar(2,5)).toBeGreaterThanOrEqual(10);
    });
    test('Resultado mayor que...', () => {
        expect(sumar(5,5)).toBeGreaterThan(9);
    });
});
describe('Matchers Boolean, Undefined o Null', () => {
    test('Resultado true', () => {
        expect(isTrue()).toBeTruthy();
    });
    test('Resultado false', () => {
        expect(isFalse()).toBeFalsy();
    });
    test('Resultado undefined', () => {
        expect(isUndefined()).toBeUndefined();
    });
    test('Resultado null', () => {
        expect(isNull()).toBeNull();
    });
});
describe('Matchers Arrays', () => { 
    test('Madrid existe en el array', () => {
        expect(arrProvincias()).toContain('Madrid');
    });
    test('Guadalajara no existe en el array', () => {
        expect(arrProvincias()).not.toContain('Guadalajara');
    })
    test('El array semana tiene 9 elementos', () => {
        expect(arrProvincias()).toHaveLength(9);
    })
});

Para explicar el matcher string y poder realizar testing, vamos hacer un pequeño test usando expresiones regulares.

  • toMatch: Comprueba que un texto coincide con una expresión regular
  • toHaveLength: Comprueba la longitud.

index.js

const provincias = ['Álava','Badajoz','Cáceres','Girona','Huelva','Jaén','La Rioja','Madrid','Navarra'];
const dias = ['Lunes','Martes','Miercoles','Jueves','Viernes','Sabado','Domingo'];
const expReg = {
    responseOK: 'Response OK',
    responseFAIL: 'Response FAIL',
    email: 'test@test.com',
    telefono: '919784852'
}
export const sumar = (a, b) => a + b;
export const restar = (a, b) => a - b;
export const multiplicar = (a, b) => a * b;
export const dividir = (a, b) => a / b;
export const isNull = () => null;
export const isFalse = () => false;
export const isTrue = () => true;
export const isUndefined = () => undefined;
export const arrProvincias = () => provincias;
export const arrDias = () => dias;
export const objExpReg = () => expReg;

index.test.js

import { sumar, restar, multiplicar, dividir, isFalse, isNull, isTrue, isUndefined, arrDias, arrProvincias, objExpReg } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});
describe('Common matchers', () => {
    const datos = {
        nombre: 'Persona 1',
        edad: 10
    }
    const datos2 = {
        nombre: 'Persona 1',
        edad: 10
    }
    test('Comprobamos que los objectos son iguales', () => {
        expect(datos).toEqual(datos2);
    });
});
describe('Numeric matchers', () => {
    test('Resultado menor que...', () => {
        expect(restar(5,3)).toBeLessThan(3);
    });
    test('Resultado menor o igual que...', () => {
        expect(restar(5,3)).toBeLessThanOrEqual(2);
    });
    test('Resultado mayor o igual que...', () => {
        expect(multiplicar(2,5)).toBeGreaterThanOrEqual(10);
    });
    test('Resultado mayor que...', () => {
        expect(sumar(5,5)).toBeGreaterThan(9);
    });
});
describe('Matchers Boolean, Undefined o Null', () => {
    test('Resultado true', () => {
        expect(isTrue()).toBeTruthy();
    });
    test('Resultado false', () => {
        expect(isFalse()).toBeFalsy();
    });
    test('Resultado undefined', () => {
        expect(isUndefined()).toBeUndefined();
    });
    test('Resultado null', () => {
        expect(isNull()).toBeNull();
    });
});
describe('Matchers Arrays', () => { 
    test('Madrid existe en el array', () => {
        expect(arrProvincias()).toContain('Madrid');
    });
    test('Guadalajara no existe en el array', () => {
        expect(arrProvincias()).not.toContain('Guadalajara');
    });
    test('El array semana tiene 9 elementos', () => {
        expect(arrProvincias()).toHaveLength(9);
    });
    test('Existe Lunes en el array semana', () => {
        expect(arrDias()).toContain('Lunes');
    });
});
describe('Matchers Strings', () => {
    const exp = objExpReg();
    test('Comprobamos si la respuesta es correcta', () => {
        expect(exp.responseOK).toMatch(/OK/);
    });
    test('Comprobamos si la respuesta es incorrecta', () => {
        expect(exp.responseFAIL).toMatch(/FAIL/);
    });
    test('Comprobamos si la respuesta tiene una longitud', () => {
        expect(exp.responseFAIL).toHaveLength(13);
    });
    test('Comprobamos dirección de email', () => {
        expect(exp.email).toMatch(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.([a-zA-Z]{2,4})+$/);
    })
    test('Comprobamos número de teléfono', () => {
        expect(exp.telefono).toMatch(/^[9|6|7][0-9]{8}$/);
    });
});

Como hemos podido comprobar, la cantidad de pruebas a realizar son bastantes y puede ocurrirnos que en algún momento por un descuido no realicemos las pruebas sobre alguna parte de nuestro código.

¿Y como podemos asegurarnos que nuestro código no se queda sin testear?. Bien, jest nos ofrece el flag –coverage en la linea de comandos para comprobar la cobertura de nuestros test.

Para que sea mucho mas cómodo vamos hacer un nuevo valor dentro de la sección de scripts en nuestro package.json.

package.json

{
  "name": "JEST",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest",
    "test:cobertura": "jest --coverage"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-jest": "^23.6.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "jest": "^23.6.0"
  }
}

Cuando ejecutemos el comando y termine, nos mostrara en pantalla los tests que ha realizado, un pequeño informe en pantalla y creara un directorio con el informe en formato web.

Informe en consola

> jest --coverage

 PASS  test/index.test.js
  Operaciones matemáticas
    √ Realizamos la suma (2ms)
    √ Realizamos la resta
    √ Realizamos la multiplicacion (1ms)
    √ Realizamos la division
  Common matchers
    √ Comprobamos que los objectos son iguales (1ms)
  Numeric matchers
    √ Resultado menor que...
    √ Resultado menor o igual que...
    √ Resultado mayor o igual que... (1ms)
    √ Resultado mayor que...
  Matchers Boolean, Undefined o Null
    √ Resultado true
    √ Resultado false
    √ Resultado undefined (1ms)
    √ Resultado null
  Matchers Arrays
    √ Madrid existe en el array
    √ Guadalajara no existe en el array
    √ El array semana tiene 9 elementos (1ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |    95.45 |      100 |       90 |      100 |                   |
 index.js |    95.45 |      100 |       90 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       16 passed, 16 total
Snapshots:   0 total
Time:        1.347s
Ran all test suites.

Informe en web

Dentro del informe web si queremos tener mas detalles sobre los test realizados, pulsaremos sobre el fichero donde se han realizado las pruebas.

En el nuevo informe veremos un informe detallado de nuestras pruebas realizadas.

Como podemos observar, en el nuevo informe nos damos cuenta que nunca hicimos el test para la función arrDias.

Añadimos el test y veremos el informe para comprobar que todo es correcto.

Informe en consola

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|

Informe en web

Llegados a este punto ya sabemos hacer testing, como usar los diferentes tipos de datos y saber si nuestros test se realizan sobre todo el código o no.

El único problema es que tenemos que estar ejecutando nuestro script cada vez que deseamos realizar los test.

Esto no es un problema si es poco código, si tienes que modificar algún test o simplemente quieres hacer alguna prueba, pero…, ¿si quieres que se comprueben constantemente los cambios que ocurren sobre tus test, y no tener que ejecutar una y otra vez el script?.

Pues tranquilo, ya que jest nos ofrece el flag –watchAll para que este escuchando constantemente los cambios y pueda hacer las pruebas sobre los cambios realizados.

Como hicimos con el flag –coverage haremos lo mismo con el flag –watchAll, añadiendo un nuevo script dentro de nuestro package.json.

package.json

{
  "name": "JEST",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest",
    "test:cobertura": "jest --coverage",
    "test:vigilar": "jest --watchAll"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-jest": "^23.6.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "jest": "^23.6.0"
  }
}

Resultado en la consola

npm run test:vigilar

> JEST@1.0.0 test:vigilar D:\www\JEST
> jest --watchAll
 PASS  test/index.test.js
  Operaciones matemáticas
    √ Realizamos la suma (3ms)
    √ Realizamos la resta (1ms)
    √ Realizamos la multiplicacion
    √ Realizamos la division
  Common matchers
    √ Comprobamos que los objectos son iguales (1ms)
  Numeric matchers
    √ Resultado menor que...
    √ Resultado menor o igual que... (1ms)
    √ Resultado mayor o igual que...
    √ Resultado mayor que... (1ms)
  Matchers Boolean, Undefined o Null
    √ Resultado true
    √ Resultado false (1ms)
    √ Resultado undefined
    √ Resultado null (1ms)
  Matchers Arrays
    √ Madrid existe en el array
    √ Guadalajara no existe en el array
    √ El array semana tiene 9 elementos (1ms)
    √ Existe Lunes en el array semana
  Matchers Strings
    √ Comprobamos si la respuesta es correcta (1ms)
    √ Comprobamos si la respuesta es incorrecta
    √ Comprobamos si la respuesta tiene una longitud (1ms)
    √ Comprobamos dirección de email
    √ Comprobamos número de teléfono

Test Suites: 1 passed, 1 total
Tests:       22 passed, 22 total
Snapshots:   0 total
Time:        1.064s
Ran all test suites.

Watch Usage
 › Press f to run only failed tests.
 › Press o to only run tests related to changed files.
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press q to quit watch mode.
 › Press Enter to trigger a test run.

Cuando ejecutemos por primera vez el script, este pasara todos los test y a continuación nos mostrara un menú con todas las opciones.

Si no seleccionamos ninguna opción, jest estará esperando a que realicemos algún cambio sobre nuestro test para volver a ejecutarse.

Para terminar esta primera parte usaremos unas funciones que nos ofrece jest, y que nos permite poder ejecutar antes, durante o después nuestras pruebas.

  • afterEach(): Después de cada prueba.
  • afterAll(): Después de todas las pruebas.
  • beforeEach(): Antes de cada prueba.
  • beforeAll(): Antes de todas las pruebas.

index.test.js

import { sumar, restar, multiplicar, dividir, isFalse, isNull, isTrue, isUndefined, arrDias, arrProvincias, objExpReg } from '../index.js';

describe('Operaciones matemáticas', () => {
    test('Realizamos la suma', () => {
        expect(sumar(1,1)).toBe(2);
    });
    test('Realizamos la resta', () => {
        expect(restar(1,1)).toBe(0);
    });
    test('Realizamos la multiplicacion', () => {
        expect(multiplicar(1,1)).toBe(1);
    });
    test('Realizamos la division', () => {
        expect(dividir(1,1)).toBe(1);
    });
});
describe('Common matchers', () => {
    const datos = {
        nombre: 'Persona 1',
        edad: 10
    }
    const datos2 = {
        nombre: 'Persona 1',
        edad: 10
    }
    test('Comprobamos que los objectos son iguales', () => {
        expect(datos).toEqual(datos2);
    });
});
describe('Numeric matchers', () => {
    test('Resultado menor que...', () => {
        expect(restar(5,3)).toBeLessThan(3);
    });
    test('Resultado menor o igual que...', () => {
        expect(restar(5,3)).toBeLessThanOrEqual(2);
    });
    test('Resultado mayor o igual que...', () => {
        expect(multiplicar(2,5)).toBeGreaterThanOrEqual(10);
    });
    test('Resultado mayor que...', () => {
        expect(sumar(5,5)).toBeGreaterThan(9);
    });
});
describe('Matchers Boolean, Undefined o Null', () => {
    test('Resultado true', () => {
        expect(isTrue()).toBeTruthy();
    });
    test('Resultado false', () => {
        expect(isFalse()).toBeFalsy();
    });
    test('Resultado undefined', () => {
        expect(isUndefined()).toBeUndefined();
    });
    test('Resultado null', () => {
        expect(isNull()).toBeNull();
    });
});
describe('Matchers Arrays', () => { 
    test('Madrid existe en el array', () => {
        expect(arrProvincias()).toContain('Madrid');
    });
    test('Guadalajara no existe en el array', () => {
        expect(arrProvincias()).not.toContain('Guadalajara');
    });
    test('El array semana tiene 9 elementos', () => {
        expect(arrProvincias()).toHaveLength(9);
    });
    test('Existe Lunes en el array semana', () => {
        expect(arrDias()).toContain('Lunes');
    });
});
describe('Matchers Strings', () => {
    const exp = objExpReg();
    test('Comprobamos si la respuesta es correcta', () => {
        expect(exp.responseOK).toMatch(/OK/);
    });
    test('Comprobamos si la respuesta es incorrecta', () => {
        expect(exp.responseFAIL).toMatch(/FAIL/);
    });
    test('Comprobamos si la respuesta tiene una longitud', () => {
        expect(exp.responseFAIL).toHaveLength(13);
    });
    test('Comprobamos dirección de email', () => {
        expect(exp.email).toMatch(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.([a-zA-Z]{2,4})+$/);
    })
    test('Comprobamos número de teléfono', () => {
        expect(exp.telefono).toMatch(/^[9|6|7][0-9]{8}$/);
    });
});
afterEach(() => console.log('Despues de cada prueba'));
afterAll(() => console.log("Despues de todas las pruebas"));
beforeEach(() => console.log('Antes de cada prueba'));
beforeAll(() => console.log('Antes de todas las pruebas'));

Con estos últimos métodos podemos tener controlado el ciclo de vida de nuestras pruebas y saber en que punto se encuentran.

Para la segunda parte de jest aprenderemos a realizar testing asincrono, snapshot testing e intentaremos implementar jest en algún framework como VueJS o ExpressJS.