Aprende a estructurar un test

3 minutos

Testing

Usar un flujo de testing de algún tipo (TDD, BDD, E2E…) es una buena medida de calidad. No porque te asegure que la función u objeto funcione como esperas, sino porque indica que el proyecto posee una buena arquitectura y detrás hay buenos desarrolladores.

Hacer testing no trata solo sobre crear código que compruebe otro código, sino una metodología de trabajo profesional que amplia la visión del código. Escribes un preciso guión de que buscas, dejando claro como debe comportarse y de que manera reaccionará en casos extraordinarios. Todo ello sin tan siquiera escribir la funcionalidad. Además, de manera indirecta, dejas documentado el funcionamiento.

Suele decirse que hacer testing es artesanal, que todos los casos son únicos. No es cierto, disponemos de patrones o plantillas que nos ayudan a empezar y estructurar. Y entre las más sencillas y conocidos son encontramos con Given-When-Then.

Plantilla Given-When-Then

Creado por Daniel Terhorst-North y Chris Matts como parte de BDD (Behavior-Driven Development), son sugieren un patrón de 3 bloques informales de comentarios para dividir el código.

  1. Given (Dado): Preparas el escenario del test, como la base de datos, variables o condiciones propicias.
  2. When (Cuando): Condiciones que transformarán el contenido.
  3. Then (Entonces): Verificas el resultado final, que se ha cumplido todo lo que esperabas o los casos propuestos.

Pongamos sobre la mesa un ejemplo en prosa. Vamos a escribir un test para el cuento de “los 3 cerditos”. El objetivo es comprobar que están a salvo del lobo.

Dado 3 casas, [‘paja’, ‘madera’, ‘ladrillos’]…

Cuando sople el lobo sobre cada una…

Entonces debe existir 1 o más casas en pie.

Ahora vamos a crear un ejemplo real en JavaScript pero muy simple. Queremos una función que nos informe si una anchura y una altura de una imagen iguales. Tal solo indicaremos cuanto es la anchura y altura, devolviendo un true, false o null dependiendo la situación.

Primero definimos la función, pero sin contenido, en imagenes.js. Podrías considerar que estas documentando.

// imagenes.js

/**
 * Comprueba si es una medida cuadrada o contiene la misma anchura y altura
 * @param float anchura
 * @param float altura
 * @return boolean, en caso de no disponer de argumentos con el tipo correcto devolverá un null
 */
function esAnchuraYAlturaCuadrada(anchura, altura) {
}

// Exportamos para que pueda ser invocado desde otros lugares
module.exports = {
    esAnchuraYAlturaCuadrada
};

Ahora hacemos uso de Jest para hace el test. Creamos siguiente archivo imagenes.test.js.

// imagenes.test.js

const {esAnchuraYAlturaCuadrada} = require('./imagenes');

/* Given */

anchura_1 = 500;
altura_1 = 250;

anchura_2 = 400;
altura_2 = 400;

anchura_3 = 400.2;
altura_3 = 400;

anchura_4 = "foo";
altura_4 = 150;

anchura_5 = false;
altura_5 = "boo";


/* When */

resultados_1 = esAnchuraYAlturaCuadrada(anchura_1, altura_1);
resultados_2 = esAnchuraYAlturaCuadrada(anchura_2, altura_2);
resultados_3 = esAnchuraYAlturaCuadrada(anchura_3, altura_3);
resultados_4 = esAnchuraYAlturaCuadrada(anchura_4, altura_4);
resultados_5 = esAnchuraYAlturaCuadrada(anchura_5, altura_5);


/* Then */

test('No son iguales', () => {
    expect(resultados_1).toBe(false);
});

test('Son iguales', () => {
    expect(resultados_2).toBe(true);
});

test('No son iguales', () => {
    expect(resultados_3).toBe(false);
});

test('No se puede comparar un texto con un número', () => {
    expect(resultados_4).toBe(null);
});

test('No se puede comparar un boolean con un texto', () => {
    expect(resultados_5).toBe(null);
});

Instalamos la librería Jest que será la encargada de realizar los test.

npm install --save-dev jest

Y lo ejecutamos.

./node_modules/jest/bin/jest.js

Obviamente fallarán todas.

Ya sabemos que buscamos, y que debe devolver. Es hora de definir la función.

// imagenes.js

/**
 * Comprueba si es una medida cuadrada o contiene la misma anchura y altura
 * @param float anchura
 * @param float altura
 * @return boolean, en caso de no disponer de argumentos con el tipo correcto devolverá un null
 */
function esAnchuraYAlturaCuadrada(anchura, altura) {
    // Es un número?
    if (anchura === parseFloat(anchura) && altura === parseFloat(altura)) {
        // Es igual?
        return anchura == altura;
    }
    return null;
}

// Exportamos para que pueda ser invocado desde otros lugares
module.exports = {
    esAnchuraYAlturaCuadrada
};

Cuando se vuelva a testear comprobarás que pasa todos los casos.

 PASS  ./imagenes.test.js
  ✓ No son iguales (2 ms)
  ✓ Son iguales (1 ms)
  ✓ No son iguales
  ✓ No se puede comparar un texto con un número (1 ms)
  ✓ No se puede comparar un boolean con un texto

Test Suites: 1 passed, 1 total
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        0.317 s, estimated 1 s
Ran all test suites.

Has sido testigo de todos los pasos típicos en un desarrollo con la metodología TDD.

  1. Documentar.
  2. Crear test.
  3. Ejecutar el test, recibiendo que falla.
  4. Crear la funcionalidad.
  5. Volver a ejecutar, recibiendo un éxito.

Si quieres profundizar, puedes explorar mi curso gratuito de testing donde podrás conocer otras técnicas e implementaciones en otros lenguajes.

Donación con recompensa

  • 1 café: Respondo a tu duda en los comentarios.
  • 2 cafés: Respondo en menos de 24h a tu comentario.
  • 3 cafés: Todo lo anterior y además te doy las gracias en mis redes.
Comprame un café

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario

Tal vez también te interese...