QUnit


🧠 Conceptos Clave

  • Module: Agrupa tests relacionados, proporcionando contexto y reutilización de setup.
  • Test: Unidad individual de verificación, con una o más aserciones.
  • Assertions: Métodos que validan resultados (assert.ok, assert.equal, assert.deepEqual, etc.).
  • Hooks: Funciones (before, beforeEach, after, afterEach) para preparar o limpiar el entorno.
  • Asynchronous Testing: Uso de assert.async() o async/await para gestionar operaciones no bloqueantes.
  • AAA Pattern (Arrange-Act-Assert): Estructura estándar que mejora legibilidad y mantiene consistencia con TDD - Test Driven Development.

🧱 Estructura básica de un test

Cada módulo agrupa casos relacionados; los tests son independientes y usan un estado limpio.

Ejemplo: estructura básica

QUnit.module("Math utilities", hooks => {
  hooks.beforeEach(() => console.log("Preparando entorno de test..."));
  QUnit.test("suma básica", assert => {
    assert.equal(1 + 1, 2, "1 + 1 debe ser igual a 2");
  });
  QUnit.test("comparación profunda", assert => {
    assert.deepEqual({ a: 1 }, { a: 1 }, "Los objetos son equivalentes");
  });
});

⚙️ Integración con node.js

QUnit se integra fácilmente en proyectos Node.js, ejecutándose mediante CLI o CI/CD pipelines.

Ejemplo: integración Node.js

npm install --save-dev qunit
{
  "scripts": {
    "test": "qunit"
  }
}
npm test

Estructura de carpetas recomendada:

tests/
 ├─ unit/         → pruebas de funciones individuales
 ├─ integration/  → interacción entre módulos
 └─ e2e/          → flujos completos simulados

🌐 Ejecución en navegador

Permite probar scripts y componentes frontend directamente, útil para librerías o frameworks DOM.

Ejemplo: navegador

<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.20.0.css">
<script src="https://code.jquery.com/qunit/qunit-2.20.0.js"></script>

<div id="qunit"></div>
<div id="qunit-fixture"></div>

<script>
QUnit.test("Ejemplo básico en navegador", assert => {
  assert.ok(true, "El test pasa correctamente");
});
</script>

🧮 Tests asíncronos

Soporta async/await, callbacks o promesas mediante assert.async().

Ejemplo: test asíncrono

QUnit.test("fetch simulado", async assert => {
  assert.expect(1);
  const done = assert.async();
  setTimeout(() => {
    assert.ok(true, "Datos cargados correctamente");
    done();
  }, 500);
});

💡 Puedes combinarlo con Mocks MSW para interceptar peticiones reales o API simuladas.


🧩 Tipos de Assertions

Método Descripción
assert.ok(value) Verifica que value sea truthy.
assert.notOk(value) Verifica que value sea falsy.
assert.equal(a, b) Compara con ==.
assert.strictEqual(a, b) Compara con ===.
assert.deepEqual(a, b) Compara estructuras anidadas.
assert.throws(fn) Espera una excepción.
assert.rejects(promise) Espera rechazo de promesa.

🧱 Organización de Suites

Agrupa tests por funcionalidad o capa del sistema, promoviendo mantenibilidad y escalabilidad.

Ejemplo: suites

QUnit.module("User module", () => {
  QUnit.test("crea usuario", assert => {
    const user = { id: 1, name: "Edu" };
    assert.deepEqual(user, { id: 1, name: "Edu" });
  });
});

QUnit.module("Auth module", () => {
  QUnit.test("login correcto", assert => {
    assert.ok(true, "Autenticación OK");
  });
});

🧰 Integración con otras herramientas

  • Compatible con Jest, Vitest o Mocha para migraciones progresivas.
  • Ejecutable en pipelines de GitHub Actions, GitLab CI o Jenkins.
  • Ideal para testing incremental en proyectos legacy de node.js o frontend vanilla.

Ejemplo: CI/CD

name: Run QUnit Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test

🧩 Mejores Prácticas

  • Agrupar tests por módulo funcional.
  • Usar assert.expect(n) para validar número de aserciones.
  • Resetear estado en afterEach().
  • Evitar dependencias entre tests.
  • Emplear Mocks MSW o fakes para APIs externas.
  • Combinar con nyc o c8 para medición de cobertura.
  • Adoptar el patrón AAA y nombres expresivos.

🧠 Comparativa 2025

Framework Estilo Ideal para Configuración Ecosistema
QUnit Procedural JS nativo, proyectos simples o legacy Muy baja Ligero
Jest Declarativo React, Node Media Amplio
Vitest Moderno Vite, Vue, ESM Baja Moderna
Mocha + Chai Modular Node, librerías puras Media Flexible

🧰 Extensiones Útiles

  • QUnit CLI Reporter → salida clara en consola.
  • qunit-dom → assertions específicas para DOM.
  • ember-qunit → integración con Ember.js.
  • nyc → cobertura de código compatible con QUnit.

🔍 Diagnóstico Rápido

Problema Causa Solución
Tests no detectados Nombre o export incorrecto Asegurar archivos .test.js válidos
Tests bloqueados Falta de done() Llamar siempre done() en async tests
Estado compartido Falta de beforeEach() Limpiar variables entre tests
Sin resultados en CI Reporter no configurado Añadir --reporter tap o cli

🚀 Conclusión

QUnit en 2025 sigue siendo una opción estable y eficiente para entornos donde la simplicidad y la compatibilidad son prioridad. Su integración fluida con Testing, TDD - Test Driven Development y herramientas modernas lo convierten en un framework confiable para proyectos Node.js, frontend vanilla o migraciones desde sistemas antiguos.


🔗 Referencias