Ejecutor de pruebas
[Historial]
Versión | Cambios |
---|---|
v20.0.0 | El ejecutor de pruebas ahora es estable. |
v18.0.0, v16.17.0 | Agregado en: v18.0.0, v16.17.0 |
[Estable: 2 - Estable]
Estable: 2 Estabilidad: 2 - Estable
Código Fuente: lib/test.js
El módulo node:test
facilita la creación de pruebas de JavaScript. Para acceder a él:
import test from 'node:test';
const test = require('node:test');
Este módulo solo está disponible bajo el esquema node:
.
Las pruebas creadas a través del módulo test
consisten en una sola función que se procesa de una de tres maneras:
El siguiente ejemplo ilustra cómo se escriben las pruebas usando el módulo test
.
test('prueba síncrona exitosa', (t) => {
// Esta prueba pasa porque no lanza una excepción.
assert.strictEqual(1, 1);
});
test('prueba síncrona fallida', (t) => {
// Esta prueba falla porque lanza una excepción.
assert.strictEqual(1, 2);
});
test('prueba asíncrona exitosa', async (t) => {
// Esta prueba pasa porque la Promise devuelta por la función async
// se resuelve y no se rechaza.
assert.strictEqual(1, 1);
});
test('prueba asíncrona fallida', async (t) => {
// Esta prueba falla porque la Promise devuelta por la función async
// se rechaza.
assert.strictEqual(1, 2);
});
test('prueba fallida usando Promises', (t) => {
// Las Promises también se pueden usar directamente.
return new Promise((resolve, reject) => {
setImmediate(() => {
reject(new Error('esto hará que la prueba falle'));
});
});
});
test('prueba exitosa de callback', (t, done) => {
// done() es la función de callback. Cuando se ejecuta setImmediate(), invoca
// done() sin argumentos.
setImmediate(done);
});
test('prueba fallida de callback', (t, done) => {
// Cuando se ejecuta setImmediate(), se invoca done() con un objeto Error y
// la prueba falla.
setImmediate(() => {
done(new Error('fallo de callback'));
});
});
Si alguna prueba falla, el código de salida del proceso se establece en 1
.
Subpruebas
El método test()
del contexto de prueba permite la creación de subpruebas. Permite estructurar las pruebas de forma jerárquica, donde se pueden crear pruebas anidadas dentro de una prueba mayor. Este método se comporta de forma idéntica a la función test()
de nivel superior. El siguiente ejemplo demuestra la creación de una prueba de nivel superior con dos subpruebas.
test('prueba de nivel superior', async (t) => {
await t.test('subprueba 1', (t) => {
assert.strictEqual(1, 1);
});
await t.test('subprueba 2', (t) => {
assert.strictEqual(2, 2);
});
});
En este ejemplo, se utiliza await
para asegurar que ambas subpruebas se hayan completado. Esto es necesario porque las pruebas no esperan a que sus subpruebas se completen, a diferencia de las pruebas creadas dentro de los conjuntos de pruebas. Cualquier subprueba que aún esté pendiente cuando su padre finalice se cancela y se trata como un fallo. Cualquier fallo de subprueba provoca que la prueba padre falle.
Omitir pruebas
Las pruebas individuales se pueden omitir pasando la opción skip
a la prueba, o llamando al método skip()
del contexto de la prueba, como se muestra en el siguiente ejemplo.
// Se utiliza la opción skip, pero no se proporciona ningún mensaje.
test('opción skip', { skip: true }, (t) => {
// Este código nunca se ejecuta.
});
// Se utiliza la opción skip, y se proporciona un mensaje.
test('opción skip con mensaje', { skip: 'esto se omite' }, (t) => {
// Este código nunca se ejecuta.
});
test('método skip()', (t) => {
// Asegúrese de retornar aquí también si la prueba contiene lógica adicional.
t.skip();
});
test('método skip() con mensaje', (t) => {
// Asegúrese de retornar aquí también si la prueba contiene lógica adicional.
t.skip('esto se omite');
});
Pruebas TODO
Las pruebas individuales se pueden marcar como inestables o incompletas pasando la opción todo
a la prueba, o llamando al método todo()
del contexto de la prueba, como se muestra en el siguiente ejemplo. Estas pruebas representan una implementación pendiente o un error que necesita ser corregido. Las pruebas TODO se ejecutan, pero no se tratan como fallos de prueba, y por lo tanto no afectan al código de salida del proceso. Si una prueba se marca como TODO y se omite, la opción TODO se ignora.
// Se utiliza la opción todo, pero no se proporciona ningún mensaje.
test('opción todo', { todo: true }, (t) => {
// Este código se ejecuta, pero no se trata como un fallo.
throw new Error('esto no hace que la prueba falle');
});
// Se utiliza la opción todo, y se proporciona un mensaje.
test('opción todo con mensaje', { todo: 'esta es una prueba todo' }, (t) => {
// Este código se ejecuta.
});
test('método todo()', (t) => {
t.todo();
});
test('método todo() con mensaje', (t) => {
t.todo('esta es una prueba todo y no se trata como un fallo');
throw new Error('esto no hace que la prueba falle');
});
Alias de describe()
y it()
Las suites y las pruebas también se pueden escribir usando las funciones describe()
y it()
. describe()
es un alias de suite()
, e it()
es un alias de test()
.
describe('Una cosa', () => {
it('debería funcionar', () => {
assert.strictEqual(1, 1);
});
it('debería estar bien', () => {
assert.strictEqual(2, 2);
});
describe('una cosa anidada', () => {
it('debería funcionar', () => {
assert.strictEqual(3, 3);
});
});
});
describe()
e it()
se importan desde el módulo node:test
.
import { describe, it } from 'node:test';
const { describe, it } = require('node:test');
Pruebas only
Si Node.js se inicia con la opción de línea de comandos --test-only
, o si el aislamiento de pruebas está desactivado, es posible omitir todas las pruebas excepto un subconjunto seleccionado pasando la opción only
a las pruebas que se deben ejecutar. Cuando se establece una prueba con la opción only
, también se ejecutan todas las subpruebas. Si una suite tiene establecida la opción only
, se ejecutan todas las pruebas dentro de la suite, a menos que tenga descendientes con la opción only
establecida, en cuyo caso solo se ejecutan esas pruebas.
Cuando se utilizan subpruebas dentro de un test()
/it()
, es necesario marcar todas las pruebas ascendientes con la opción only
para ejecutar solo un subconjunto seleccionado de pruebas.
El método runOnly()
del contexto de prueba se puede utilizar para implementar el mismo comportamiento a nivel de subprueba. Las pruebas que no se ejecutan se omiten de la salida del ejecutor de pruebas.
// Supongamos que Node.js se ejecuta con la opción de línea de comandos --test-only.
// La opción 'only' de la suite está establecida, por lo que estas pruebas se ejecutan.
test('esta prueba se ejecuta', { only: true }, async (t) => {
// Dentro de esta prueba, todas las subpruebas se ejecutan de forma predeterminada.
await t.test('subprueba en ejecución');
// El contexto de la prueba se puede actualizar para ejecutar subpruebas con la opción 'only'.
t.runOnly(true);
await t.test('esta subprueba ahora se omite');
await t.test('esta subprueba se ejecuta', { only: true });
// Cambia el contexto de nuevo para ejecutar todas las pruebas.
t.runOnly(false);
await t.test('esta subprueba ahora se ejecuta');
// No ejecutar explícitamente estas pruebas.
await t.test('subprueba omitida 3', { only: false });
await t.test('subprueba omitida 4', { skip: true });
});
// La opción 'only' no está establecida, por lo que esta prueba se omite.
test('esta prueba no se ejecuta', () => {
// Este código no se ejecuta.
throw new Error('fail');
});
describe('una suite', () => {
// La opción 'only' está establecida, por lo que esta prueba se ejecuta.
it('esta prueba se ejecuta', { only: true }, () => {
// Este código se ejecuta.
});
it('esta prueba no se ejecuta', () => {
// Este código no se ejecuta.
throw new Error('fail');
});
});
describe.only('una suite', () => {
// La opción 'only' está establecida, por lo que esta prueba se ejecuta.
it('esta prueba se ejecuta', () => {
// Este código se ejecuta.
});
it('esta prueba se ejecuta', () => {
// Este código se ejecuta.
});
});
Filtrado de pruebas por nombre
La opción de línea de comandos --test-name-pattern
se puede usar para ejecutar solo las pruebas cuyo nombre coincida con el patrón proporcionado, y la opción --test-skip-pattern
se puede usar para omitir las pruebas cuyo nombre coincida con el patrón proporcionado. Los patrones de nombres de prueba se interpretan como expresiones regulares de JavaScript. Las opciones --test-name-pattern
y --test-skip-pattern
se pueden especificar varias veces para ejecutar pruebas anidadas. Para cada prueba que se ejecuta, también se ejecutan los ganchos de prueba correspondientes, como beforeEach()
. Las pruebas que no se ejecutan se omiten de la salida del ejecutor de pruebas.
Dado el siguiente archivo de prueba, iniciar Node.js con la opción --test-name-pattern="test [1-3]"
haría que el ejecutor de pruebas ejecute test 1
, test 2
y test 3
. Si test 1
no coincidiera con el patrón de nombre de prueba, entonces sus subpruebas no se ejecutarían, a pesar de coincidir con el patrón. El mismo conjunto de pruebas también se podría ejecutar pasando --test-name-pattern
varias veces (por ejemplo, --test-name-pattern="test 1"
, --test-name-pattern="test 2"
, etc.).
test('test 1', async (t) => {
await t.test('test 2');
await t.test('test 3');
});
test('Test 4', async (t) => {
await t.test('Test 5');
await t.test('test 6');
});
Los patrones de nombres de prueba también se pueden especificar usando literales de expresiones regulares. Esto permite usar flags de expresiones regulares. En el ejemplo anterior, iniciar Node.js con --test-name-pattern="/test [4-5]/i"
(o --test-skip-pattern="/test [4-5]/i"
) coincidiría con Test 4
y Test 5
porque el patrón no distingue entre mayúsculas y minúsculas.
Para que coincida una sola prueba con un patrón, puede prefijarla con todos los nombres de sus pruebas antecesoras separados por un espacio, para asegurarse de que sea única. Por ejemplo, dado el siguiente archivo de prueba:
describe('test 1', (t) => {
it('some test');
});
describe('test 2', (t) => {
it('some test');
});
Iniciar Node.js con --test-name-pattern="test 1 some test"
solo coincidiría con some test
en test 1
.
Los patrones de nombres de prueba no cambian el conjunto de archivos que ejecuta el ejecutor de pruebas.
Si se proporcionan tanto --test-name-pattern
como --test-skip-pattern
, las pruebas deben satisfacer ambos requisitos para que se ejecuten.
Actividad asíncrona superflua
Una vez que una función de prueba termina de ejecutarse, los resultados se informan lo más rápido posible manteniendo el orden de las pruebas. Sin embargo, es posible que la función de prueba genere actividad asíncrona que sobreviva a la propia prueba. El ejecutor de pruebas maneja este tipo de actividad, pero no retrasa el informe de los resultados de las pruebas para acomodarla.
En el siguiente ejemplo, una prueba se completa con dos operaciones setImmediate()
aún pendientes. El primer setImmediate()
intenta crear una nueva subprueba. Debido a que la prueba principal ya ha finalizado y emitido sus resultados, la nueva subprueba se marca inmediatamente como fallida y se informa más tarde al <TestsStream>.
El segundo setImmediate()
crea un evento uncaughtException
. Los eventos uncaughtException
y unhandledRejection
que se originan en una prueba completada son marcados como fallidos por el módulo test
e informados como advertencias de diagnóstico en el nivel superior por el <TestsStream>.
test('una prueba que crea actividad asíncrona', (t) => {
setImmediate(() => {
t.test('subprueba que se crea demasiado tarde', (t) => {
throw new Error('error1');
});
});
setImmediate(() => {
throw new Error('error2');
});
// La prueba termina después de esta línea.
});
Modo de vigilancia
Añadido en: v19.2.0, v18.13.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1 - Experimental
El ejecutor de pruebas de Node.js admite la ejecución en modo de vigilancia pasando el flag --watch
:
node --test --watch
En el modo de vigilancia, el ejecutor de pruebas vigilará los cambios en los archivos de prueba y sus dependencias. Cuando se detecta un cambio, el ejecutor de pruebas volverá a ejecutar las pruebas afectadas por el cambio. El ejecutor de pruebas seguirá ejecutándose hasta que se termine el proceso.
Ejecución de pruebas desde la línea de comandos
El ejecutor de pruebas de Node.js se puede invocar desde la línea de comandos pasando el flag --test
:
node --test
De forma predeterminada, Node.js ejecutará todos los archivos que coincidan con estos patrones:
**/*.test.{cjs,mjs,js}
**/*-test.{cjs,mjs,js}
**/*_test.{cjs,mjs,js}
**/test-*.{cjs,mjs,js}
**/test.{cjs,mjs,js}
**/test/**/*.{cjs,mjs,js}
Cuando se proporciona --experimental-strip-types
, se comparan los siguientes patrones adicionales:
**/*.test.{cts,mts,ts}
**/*-test.{cts,mts,ts}
**/*_test.{cts,mts,ts}
**/test-*.{cts,mts,ts}
**/test.{cts,mts,ts}
**/test/**/*.{cts,mts,ts}
Alternativamente, se pueden proporcionar uno o más patrones glob como los argumentos finales al comando Node.js, como se muestra a continuación. Los patrones glob siguen el comportamiento de glob(7)
. Los patrones glob deben estar encerrados entre comillas dobles en la línea de comandos para evitar la expansión del shell, lo que puede reducir la portabilidad entre sistemas.
node --test "**/*.test.js" "**/*.spec.js"
Los archivos coincidentes se ejecutan como archivos de prueba. Se puede encontrar más información sobre la ejecución del archivo de prueba en la sección modelo de ejecución del ejecutor de pruebas.
Modelo de ejecución del ejecutor de pruebas
Cuando el aislamiento de pruebas a nivel de proceso está habilitado, cada archivo de prueba coincidente se ejecuta en un proceso hijo separado. El número máximo de procesos hijos que se ejecutan en cualquier momento se controla mediante el indicador --test-concurrency
. Si el proceso hijo termina con un código de salida de 0, la prueba se considera aprobada. De lo contrario, la prueba se considera un fallo. Los archivos de prueba deben ser ejecutables por Node.js, pero no es necesario que utilicen el módulo node:test
internamente.
Cada archivo de prueba se ejecuta como si fuera un script regular. Es decir, si el propio archivo de prueba utiliza node:test
para definir pruebas, todas esas pruebas se ejecutarán dentro de un único hilo de aplicación, independientemente del valor de la opción concurrency
de test()
.
Cuando el aislamiento de pruebas a nivel de proceso está deshabilitado, cada archivo de prueba coincidente se importa al proceso del ejecutor de pruebas. Una vez que se han cargado todos los archivos de prueba, las pruebas de nivel superior se ejecutan con una concurrencia de uno. Debido a que todos los archivos de prueba se ejecutan dentro del mismo contexto, es posible que las pruebas interactúen entre sí de formas que no son posibles cuando el aislamiento está habilitado. Por ejemplo, si una prueba se basa en el estado global, es posible que ese estado sea modificado por una prueba que se origine en otro archivo.
Recopilación de la cobertura de código
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1 - Experimental
Cuando Node.js se inicia con el indicador de línea de comandos --experimental-test-coverage
, la cobertura de código se recopila y las estadísticas se informan una vez que se han completado todas las pruebas. Si la variable de entorno NODE_V8_COVERAGE
se utiliza para especificar un directorio de cobertura de código, los archivos de cobertura V8 generados se escriben en ese directorio. Los módulos centrales de Node.js y los archivos dentro de los directorios node_modules/
no se incluyen, de forma predeterminada, en el informe de cobertura. Sin embargo, se pueden incluir explícitamente a través del indicador --test-coverage-include
. De forma predeterminada, todos los archivos de prueba coincidentes se excluyen del informe de cobertura. Las exclusiones se pueden anular utilizando el indicador --test-coverage-exclude
. Si la cobertura está habilitada, el informe de cobertura se envía a cualquier informador de pruebas a través del evento 'test:coverage'
.
La cobertura se puede deshabilitar en una serie de líneas utilizando la siguiente sintaxis de comentario:
/* node:coverage disable */
if (anAlwaysFalseCondition) {
// El código en esta rama nunca se ejecutará, pero las líneas se ignoran para
// propósitos de cobertura. Todas las líneas que siguen al comentario 'disable' se ignoran
// hasta que se encuentre un comentario 'enable' correspondiente.
console.log('this is never executed');
}
/* node:coverage enable */
La cobertura también se puede deshabilitar para un número específico de líneas. Después del número especificado de líneas, la cobertura se volverá a habilitar automáticamente. Si el número de líneas no se proporciona explícitamente, se ignora una sola línea.
/* node:coverage ignore next */
if (anAlwaysFalseCondition) { console.log('this is never executed'); }
/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
console.log('this is never executed');
}
Informes de cobertura
Los informes tap y spec imprimirán un resumen de las estadísticas de cobertura. También hay un informe lcov que generará un archivo lcov que se puede utilizar como un informe de cobertura en profundidad.
node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info
- Este informe no reporta resultados de pruebas.
- Idealmente, este informe debería usarse junto con otro informe.
Mocking (Simulación)
El módulo node:test
admite el mocking durante las pruebas a través de un objeto mock
de nivel superior. El siguiente ejemplo crea un espía en una función que suma dos números. Luego, el espía se usa para afirmar que la función se llamó como se esperaba.
import assert from 'node:assert';
import { mock, test } from 'node:test';
test('espía una función', () => {
const sum = mock.fn((a, b) => {
return a + b;
});
assert.strictEqual(sum.mock.callCount(), 0);
assert.strictEqual(sum(3, 4), 7);
assert.strictEqual(sum.mock.callCount(), 1);
const call = sum.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3, 4]);
assert.strictEqual(call.result, 7);
assert.strictEqual(call.error, undefined);
// Restablece los mocks rastreados globalmente.
mock.reset();
});
'use strict';
const assert = require('node:assert');
const { mock, test } = require('node:test');
test('espía una función', () => {
const sum = mock.fn((a, b) => {
return a + b;
});
assert.strictEqual(sum.mock.callCount(), 0);
assert.strictEqual(sum(3, 4), 7);
assert.strictEqual(sum.mock.callCount(), 1);
const call = sum.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3, 4]);
assert.strictEqual(call.result, 7);
assert.strictEqual(call.error, undefined);
// Restablece los mocks rastreados globalmente.
mock.reset();
});
La misma funcionalidad de mocking también se expone en el objeto TestContext
de cada prueba. El siguiente ejemplo crea un espía en un método de objeto utilizando la API expuesta en TestContext
. El beneficio de hacer mocking a través del contexto de prueba es que el ejecutor de pruebas restaurará automáticamente toda la funcionalidad simulada una vez que finalice la prueba.
test('espía un método de objeto', (t) => {
const number = {
value: 5,
add(a) {
return this.value + a;
},
};
t.mock.method(number, 'add');
assert.strictEqual(number.add.mock.callCount(), 0);
assert.strictEqual(number.add(3), 8);
assert.strictEqual(number.add.mock.callCount(), 1);
const call = number.add.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3]);
assert.strictEqual(call.result, 8);
assert.strictEqual(call.target, undefined);
assert.strictEqual(call.this, number);
});
Temporizadores
La simulación de temporizadores es una técnica comúnmente utilizada en las pruebas de software para simular y controlar el comportamiento de los temporizadores, como setInterval
y setTimeout
, sin tener que esperar realmente los intervalos de tiempo especificados.
Consulte la clase MockTimers
para obtener una lista completa de métodos y características.
Esto permite a los desarrolladores escribir pruebas más confiables y predecibles para la funcionalidad dependiente del tiempo.
El siguiente ejemplo muestra cómo simular setTimeout
. Usando .enable({ apis: ['setTimeout'] });
simulará las funciones setTimeout
en los módulos node:timers y node:timers/promises, así como desde el contexto global de Node.js.
Nota: La desestructuración de funciones como import { setTimeout } from 'node:timers'
no es compatible actualmente con esta API.
import assert from 'node:assert';
import { mock, test } from 'node:test';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', () => {
const fn = mock.fn();
// Opcionalmente, elija qué simular
mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Avanzar en el tiempo
mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
// Restablecer las simulaciones rastreadas globalmente.
mock.timers.reset();
// Si llama a reset mock instance, también restablecerá la instancia de los temporizadores
mock.reset();
});
const assert = require('node:assert');
const { mock, test } = require('node:test');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', () => {
const fn = mock.fn();
// Opcionalmente, elija qué simular
mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Avanzar en el tiempo
mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
// Restablecer las simulaciones rastreadas globalmente.
mock.timers.reset();
// Si llama a reset mock instance, también restablecerá la instancia de los temporizadores
mock.reset();
});
La misma funcionalidad de simulación también se expone en la propiedad mock del objeto TestContext
de cada prueba. El beneficio de la simulación a través del contexto de la prueba es que el ejecutor de pruebas restaurará automáticamente toda la funcionalidad de temporizadores simulados una vez que finalice la prueba.
import assert from 'node:assert';
import { test } from 'node:test';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
// Opcionalmente, elija qué simular
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
// Opcionalmente, elija qué simular
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
Fechas
La API de temporizadores simulados también permite la simulación del objeto Date
. Esta es una característica útil para probar la funcionalidad dependiente del tiempo, o para simular funciones internas del calendario como Date.now()
.
La implementación de fechas también forma parte de la clase MockTimers
. Consulta allí la lista completa de métodos y características.
Nota: Las fechas y los temporizadores son dependientes cuando se simulan juntos. Esto significa que si tienes tanto Date
como setTimeout
simulados, avanzar en el tiempo también avanzará la fecha simulada, ya que simulan un único reloj interno.
El siguiente ejemplo muestra cómo simular el objeto Date
y obtener el valor actual de Date.now()
.
import assert from 'node:assert';
import { test } from 'node:test';
test('simula el objeto Date', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['Date'] });
// Si no se especifica, la fecha inicial se basará en 0 en la época UNIX
assert.strictEqual(Date.now(), 0);
// Avanzar en el tiempo también avanzará la fecha
context.mock.timers.tick(9999);
assert.strictEqual(Date.now(), 9999);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula el objeto Date', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['Date'] });
// Si no se especifica, la fecha inicial se basará en 0 en la época UNIX
assert.strictEqual(Date.now(), 0);
// Avanzar en el tiempo también avanzará la fecha
context.mock.timers.tick(9999);
assert.strictEqual(Date.now(), 9999);
});
Si no se establece ninguna época inicial, la fecha inicial se basará en 0 en la época de Unix. Esto es el 1 de enero de 1970, 00:00:00 UTC. Puedes establecer una fecha inicial pasando una propiedad now
al método .enable()
. Este valor se utilizará como la fecha inicial para el objeto Date
simulado. Puede ser un entero positivo u otro objeto Date.
import assert from 'node:assert';
import { test } from 'node:test';
test('simula el objeto Date con tiempo inicial', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Avanzar en el tiempo también avanzará la fecha
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 300);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula el objeto Date con tiempo inicial', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Avanzar en el tiempo también avanzará la fecha
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 300);
});
Puedes usar el método .setTime()
para mover manualmente la fecha simulada a otra hora. Este método solo acepta un entero positivo.
Nota: Este método ejecutará cualquier temporizador simulado que esté en el pasado a partir de la nueva hora.
En el siguiente ejemplo, estamos configurando una nueva hora para la fecha simulada.
import assert from 'node:assert';
import { test } from 'node:test';
test('establece la hora de un objeto Date', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Avanzar en el tiempo también avanzará la fecha
context.mock.timers.setTime(1000);
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 1200);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('establece la hora de un objeto Date', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Avanzar en el tiempo también avanzará la fecha
context.mock.timers.setTime(1000);
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 1200);
});
Si tienes algún temporizador configurado para ejecutarse en el pasado, se ejecutará como si se hubiera llamado al método .tick()
. Esto es útil si deseas probar la funcionalidad dependiente del tiempo que ya está en el pasado.
import assert from 'node:assert';
import { test } from 'node:test';
test('ejecuta temporizadores cuando setTime pasa ticks', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
context.mock.timers.setTime(800);
// El temporizador no se ejecuta ya que aún no se alcanza la hora
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 800);
context.mock.timers.setTime(1200);
// El temporizador se ejecuta ya que ahora se alcanza la hora
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 1200);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('ejecuta temporizadores cuando setTime pasa ticks', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
context.mock.timers.setTime(800);
// El temporizador no se ejecuta ya que aún no se alcanza la hora
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 800);
context.mock.timers.setTime(1200);
// El temporizador se ejecuta ya que ahora se alcanza la hora
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 1200);
});
Usar .runAll()
ejecutará todos los temporizadores que están actualmente en la cola. Esto también avanzará la fecha simulada a la hora del último temporizador que se ejecutó como si el tiempo hubiera pasado.
import assert from 'node:assert';
import { test } from 'node:test';
test('ejecuta temporizadores cuando setTime pasa ticks', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
context.mock.timers.runAll();
// Todos los temporizadores se ejecutan ya que ahora se alcanza la hora
assert.strictEqual(fn.mock.callCount(), 3);
assert.strictEqual(Date.now(), 3000);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('ejecuta temporizadores cuando setTime pasa ticks', (context) => {
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
context.mock.timers.runAll();
// Todos los temporizadores se ejecutan ya que ahora se alcanza la hora
assert.strictEqual(fn.mock.callCount(), 3);
assert.strictEqual(Date.now(), 3000);
});
Pruebas de instantáneas (Snapshot testing)
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
Las pruebas de instantáneas permiten serializar valores arbitrarios en valores de cadena y compararlos con un conjunto de valores correctos conocidos. Los valores correctos conocidos se conocen como instantáneas y se almacenan en un archivo de instantáneas. Los archivos de instantáneas son gestionados por el ejecutor de pruebas, pero están diseñados para ser legibles por humanos para ayudar en la depuración. La mejor práctica es que los archivos de instantáneas se registren en el control de código fuente junto con sus archivos de prueba.
Los archivos de instantáneas se generan iniciando Node.js con el indicador de línea de comandos --test-update-snapshots
. Se genera un archivo de instantáneas separado para cada archivo de prueba. De forma predeterminada, el archivo de instantáneas tiene el mismo nombre que el archivo de prueba con una extensión de archivo .snapshot
. Este comportamiento se puede configurar utilizando la función snapshot.setResolveSnapshotPath()
. Cada aserción de instantánea corresponde a una exportación en el archivo de instantáneas.
A continuación, se muestra un ejemplo de prueba de instantánea. La primera vez que se ejecuta esta prueba, fallará porque el archivo de instantáneas correspondiente no existe.
// test.js
suite('suite de pruebas de instantáneas', () => {
test('prueba de instantánea', (t) => {
t.assert.snapshot({ value1: 1, value2: 2 });
t.assert.snapshot(5);
});
});
Genere el archivo de instantáneas ejecutando el archivo de prueba con --test-update-snapshots
. La prueba debería pasar y se crea un archivo llamado test.js.snapshot
en el mismo directorio que el archivo de prueba. El contenido del archivo de instantáneas se muestra a continuación. Cada instantánea se identifica con el nombre completo de la prueba y un contador para diferenciar entre instantáneas en la misma prueba.
exports[`suite de pruebas de instantáneas > prueba de instantánea 1`] = `
{
"value1": 1,
"value2": 2
}
`;
exports[`suite de pruebas de instantáneas > prueba de instantánea 2`] = `
5
`;
Una vez que se crea el archivo de instantáneas, vuelva a ejecutar las pruebas sin el indicador --test-update-snapshots
. Las pruebas deberían pasar ahora.
Reportadores de pruebas
[Historial]
Versión | Cambios |
---|---|
v19.9.0, v18.17.0 | Los reportadores ahora están expuestos en node:test/reporters . |
v19.6.0, v18.15.0 | Agregado en: v19.6.0, v18.15.0 |
El módulo node:test
admite el paso de indicadores --test-reporter
para que el ejecutor de pruebas use un reportador específico.
Se admiten los siguientes reportadores integrados:
spec
El reportadorspec
muestra los resultados de la prueba en un formato legible por humanos. Este es el reportador predeterminado.tap
El reportadortap
muestra los resultados de la prueba en el formato TAP.dot
El reportadordot
muestra los resultados de la prueba en un formato compacto, donde cada prueba que pasa está representada por un.
, y cada prueba fallida está representada por unaX
.junit
El reportador junit genera los resultados de las pruebas en un formato XML jUnitlcov
El reportadorlcov
muestra la cobertura de la prueba cuando se usa con el indicador--experimental-test-coverage
.
La salida exacta de estos reportadores está sujeta a cambios entre las versiones de Node.js y no se debe confiar en ella programáticamente. Si se requiere acceso programático a la salida del ejecutor de pruebas, use los eventos emitidos por el <TestsStream>.
Los reportadores están disponibles a través del módulo node:test/reporters
:
import { tap, spec, dot, junit, lcov } from 'node:test/reporters';
const { tap, spec, dot, junit, lcov } = require('node:test/reporters');
Reportadores personalizados
--test-reporter
se puede utilizar para especificar una ruta a un reportador personalizado. Un reportador personalizado es un módulo que exporta un valor aceptado por stream.compose. Los reportadores deben transformar los eventos emitidos por un <TestsStream>
Ejemplo de un reportador personalizado que usa <stream.Transform>:
import { Transform } from 'node:stream';
const customReporter = new Transform({
writableObjectMode: true,
transform(event, encoding, callback) {
switch (event.type) {
case 'test:dequeue':
callback(null, `test ${event.data.name} dequeued`);
break;
case 'test:enqueue':
callback(null, `test ${event.data.name} enqueued`);
break;
case 'test:watch:drained':
callback(null, 'test watch queue drained');
break;
case 'test:start':
callback(null, `test ${event.data.name} started`);
break;
case 'test:pass':
callback(null, `test ${event.data.name} passed`);
break;
case 'test:fail':
callback(null, `test ${event.data.name} failed`);
break;
case 'test:plan':
callback(null, 'test plan');
break;
case 'test:diagnostic':
case 'test:stderr':
case 'test:stdout':
callback(null, event.data.message);
break;
case 'test:coverage': {
const { totalLineCount } = event.data.summary.totals;
callback(null, `total line count: ${totalLineCount}\n`);
break;
}
}
},
});
export default customReporter;
const { Transform } = require('node:stream');
const customReporter = new Transform({
writableObjectMode: true,
transform(event, encoding, callback) {
switch (event.type) {
case 'test:dequeue':
callback(null, `test ${event.data.name} dequeued`);
break;
case 'test:enqueue':
callback(null, `test ${event.data.name} enqueued`);
break;
case 'test:watch:drained':
callback(null, 'test watch queue drained');
break;
case 'test:start':
callback(null, `test ${event.data.name} started`);
break;
case 'test:pass':
callback(null, `test ${event.data.name} passed`);
break;
case 'test:fail':
callback(null, `test ${event.data.name} failed`);
break;
case 'test:plan':
callback(null, 'test plan');
break;
case 'test:diagnostic':
case 'test:stderr':
case 'test:stdout':
callback(null, event.data.message);
break;
case 'test:coverage': {
const { totalLineCount } = event.data.summary.totals;
callback(null, `total line count: ${totalLineCount}\n`);
break;
}
}
},
});
module.exports = customReporter;
Ejemplo de un reportador personalizado que usa una función generadora:
export default async function * customReporter(source) {
for await (const event of source) {
switch (event.type) {
case 'test:dequeue':
yield `test ${event.data.name} dequeued\n`;
break;
case 'test:enqueue':
yield `test ${event.data.name} enqueued\n`;
break;
case 'test:watch:drained':
yield 'test watch queue drained\n';
break;
case 'test:start':
yield `test ${event.data.name} started\n`;
break;
case 'test:pass':
yield `test ${event.data.name} passed\n`;
break;
case 'test:fail':
yield `test ${event.data.name} failed\n`;
break;
case 'test:plan':
yield 'test plan\n';
break;
case 'test:diagnostic':
case 'test:stderr':
case 'test:stdout':
yield `${event.data.message}\n`;
break;
case 'test:coverage': {
const { totalLineCount } = event.data.summary.totals;
yield `total line count: ${totalLineCount}\n`;
break;
}
}
}
}
module.exports = async function * customReporter(source) {
for await (const event of source) {
switch (event.type) {
case 'test:dequeue':
yield `test ${event.data.name} dequeued\n`;
break;
case 'test:enqueue':
yield `test ${event.data.name} enqueued\n`;
break;
case 'test:watch:drained':
yield 'test watch queue drained\n';
break;
case 'test:start':
yield `test ${event.data.name} started\n`;
break;
case 'test:pass':
yield `test ${event.data.name} passed\n`;
break;
case 'test:fail':
yield `test ${event.data.name} failed\n`;
break;
case 'test:plan':
yield 'test plan\n';
break;
case 'test:diagnostic':
case 'test:stderr':
case 'test:stdout':
yield `${event.data.message}\n`;
break;
case 'test:coverage': {
const { totalLineCount } = event.data.summary.totals;
yield `total line count: ${totalLineCount}\n`;
break;
}
}
}
};
El valor proporcionado a --test-reporter
debe ser una cadena como la que se usa en un import()
en el código JavaScript, o un valor proporcionado para --import
.
Múltiples reporters
El flag --test-reporter
se puede especificar varias veces para reportar los resultados de las pruebas en varios formatos. En esta situación, es necesario especificar un destino para cada reporter utilizando --test-reporter-destination
. El destino puede ser stdout
, stderr
o una ruta de archivo. Los reporters y los destinos se emparejan según el orden en que se especificaron.
En el siguiente ejemplo, el reporter spec
se enviará a stdout
y el reporter dot
se enviará a file.txt
:
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txt
Cuando se especifica un solo reporter, el destino predeterminado será stdout
, a menos que se proporcione explícitamente un destino.
run([options])
[Historial]
Versión | Cambios |
---|---|
v23.0.0 | Se agregó la opción cwd . |
v23.0.0 | Se agregaron opciones de cobertura. |
v22.8.0 | Se agregó la opción isolation . |
v22.6.0 | Se agregó la opción globPatterns . |
v22.0.0, v20.14.0 | Se agregó la opción forceExit . |
v20.1.0, v18.17.0 | Se agregó una opción testNamePatterns. |
v18.9.0, v16.19.0 | Agregado en: v18.9.0, v16.19.0 |
options
<Object> Opciones de configuración para ejecutar pruebas. Se admiten las siguientes propiedades:concurrency
<number> | <boolean> Si se proporciona un número, esa cantidad de procesos de prueba se ejecutarían en paralelo, donde cada proceso corresponde a un archivo de prueba. Si estrue
, ejecutaríaos.availableParallelism() - 1
archivos de prueba en paralelo. Si esfalse
, solo ejecutaría un archivo de prueba a la vez. Predeterminado:false
.cwd
: <string> Especifica el directorio de trabajo actual que utilizará el ejecutor de pruebas. Sirve como la ruta base para resolver archivos de acuerdo con el modelo de ejecución del ejecutor de pruebas. Predeterminado:process.cwd()
.files
: <Array> Un array que contiene la lista de archivos para ejecutar. Predeterminado: archivos coincidentes del modelo de ejecución del ejecutor de pruebas.forceExit
: <boolean> Configura el ejecutor de pruebas para salir del proceso una vez que todas las pruebas conocidas hayan terminado de ejecutarse, incluso si el bucle de eventos permaneciera activo. Predeterminado:false
.globPatterns
: <Array> Un array que contiene la lista de patrones glob para que coincidan con los archivos de prueba. Esta opción no se puede utilizar junto confiles
. Predeterminado: archivos coincidentes del modelo de ejecución del ejecutor de pruebas.inspectPort
<number> | <Function> Establece el puerto del inspector del proceso hijo de prueba. Esto puede ser un número o una función que no toma argumentos y devuelve un número. Si se proporciona un valor nulo, cada proceso obtiene su propio puerto, incrementado desde elprocess.debugPort
del principal. Esta opción se ignora si la opciónisolation
está establecida en'none'
ya que no se generan procesos secundarios. Predeterminado:undefined
.isolation
<string> Configura el tipo de aislamiento de prueba. Si se establece en'process'
, cada archivo de prueba se ejecuta en un proceso hijo separado. Si se establece en'none'
, todos los archivos de prueba se ejecutan en el proceso actual. Predeterminado:'process'
.only
: <boolean> Si es verdadero, el contexto de prueba solo ejecutará las pruebas que tengan la opciónonly
establecida.setup
<Function> Una función que acepta la instanciaTestsStream
y se puede utilizar para configurar listeners antes de que se ejecuten las pruebas. Predeterminado:undefined
.execArgv
<Array> Un array de flags de la CLI para pasar al ejecutablenode
al generar los subprocesos. Esta opción no tiene ningún efecto cuandoisolation
es'none'
. Predeterminado:[]
argv
<Array> Un array de flags de la CLI para pasar a cada archivo de prueba al generar los subprocesos. Esta opción no tiene ningún efecto cuandoisolation
es'none'
. Predeterminado:[]
.signal
<AbortSignal> Permite abortar una ejecución de prueba en curso.testNamePatterns
<string> | <RegExp> | <Array> Una cadena, RegExp o un Array de RegExp, que se puede utilizar para ejecutar solo las pruebas cuyo nombre coincida con el patrón proporcionado. Los patrones de nombre de prueba se interpretan como expresiones regulares de JavaScript. Para cada prueba que se ejecuta, también se ejecutan los ganchos de prueba correspondientes, comobeforeEach()
. Predeterminado:undefined
.testSkipPatterns
<string> | <RegExp> | <Array> Una cadena, RegExp o un Array de RegExp, que se puede utilizar para excluir la ejecución de pruebas cuyo nombre coincida con el patrón proporcionado. Los patrones de nombre de prueba se interpretan como expresiones regulares de JavaScript. Para cada prueba que se ejecuta, también se ejecutan los ganchos de prueba correspondientes, comobeforeEach()
. Predeterminado:undefined
.timeout
<number> Un número de milisegundos después del cual fallará la ejecución de la prueba. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.watch
<boolean> Si se debe ejecutar en modo de observación o no. Predeterminado:false
.shard
<Object> Ejecutar pruebas en un shard específico. Predeterminado:undefined
.coverage
<boolean> habilita la recopilación de cobertura de código. Predeterminado:false
.coverageExcludeGlobs
<string> | <Array> Excluye archivos específicos de la cobertura de código utilizando un patrón glob, que puede coincidir con rutas de archivo absolutas y relativas. Esta propiedad solo es aplicable cuandocoverage
se estableció entrue
. Si se proporcionan tantocoverageExcludeGlobs
comocoverageIncludeGlobs
, los archivos deben cumplir ambos criterios para ser incluidos en el informe de cobertura. Predeterminado:undefined
.coverageIncludeGlobs
<string> | <Array> Incluye archivos específicos en la cobertura de código utilizando un patrón glob, que puede coincidir con rutas de archivo absolutas y relativas. Esta propiedad solo es aplicable cuandocoverage
se estableció entrue
. Si se proporcionan tantocoverageExcludeGlobs
comocoverageIncludeGlobs
, los archivos deben cumplir ambos criterios para ser incluidos en el informe de cobertura. Predeterminado:undefined
.lineCoverage
<number> Requiere un porcentaje mínimo de líneas cubiertas. Si la cobertura de código no alcanza el umbral especificado, el proceso saldrá con el código1
. Predeterminado:0
.branchCoverage
<number> Requiere un porcentaje mínimo de ramas cubiertas. Si la cobertura de código no alcanza el umbral especificado, el proceso saldrá con el código1
. Predeterminado:0
.functionCoverage
<number> Requiere un porcentaje mínimo de funciones cubiertas. Si la cobertura de código no alcanza el umbral especificado, el proceso saldrá con el código1
. Predeterminado:0
.
Devuelve: <TestsStream>
Nota: shard
se utiliza para paralelizar horizontalmente la ejecución de pruebas en máquinas o procesos, ideal para ejecuciones a gran escala en diversos entornos. Es incompatible con el modo watch
, diseñado para una rápida iteración de código al volver a ejecutar automáticamente las pruebas en los cambios de archivo.
import { tap } from 'node:test/reporters';
import { run } from 'node:test';
import process from 'node:process';
import path from 'node:path';
run({ files: [path.resolve('./tests/test.js')] })
.on('test:fail', () => {
process.exitCode = 1;
})
.compose(tap)
.pipe(process.stdout);
const { tap } = require('node:test/reporters');
const { run } = require('node:test');
const path = require('node:path');
run({ files: [path.resolve('./tests/test.js')] })
.on('test:fail', () => {
process.exitCode = 1;
})
.compose(tap)
.pipe(process.stdout);
suite([name][, options][, fn])
Añadido en: v22.0.0, v20.13.0
name
<string> El nombre del conjunto de pruebas, que se muestra al informar de los resultados de las pruebas. Predeterminado: La propiedadname
defn
, o'\<anonymous\>'
sifn
no tiene nombre.options
<Object> Opciones de configuración opcionales para el conjunto de pruebas. Esto admite las mismas opciones quetest([name][, options][, fn])
.fn
<Function> | <AsyncFunction> La función del conjunto de pruebas que declara pruebas y conjuntos de pruebas anidados. El primer argumento de esta función es un objetoSuiteContext
. Predeterminado: Una función no operativa.- Devuelve: <Promise> Cumplida inmediatamente con
undefined
.
La función suite()
se importa del módulo node:test
.
suite.skip([name][, options][, fn])
Añadido en: v22.0.0, v20.13.0
Abreviatura para omitir un conjunto de pruebas. Esto es lo mismo que suite([name], { skip: true }[, fn])
.
suite.todo([name][, options][, fn])
Añadido en: v22.0.0, v20.13.0
Abreviatura para marcar un conjunto de pruebas como TODO
. Esto es lo mismo que suite([name], { todo: true }[, fn])
.
suite.only([name][, options][, fn])
Añadido en: v22.0.0, v20.13.0
Abreviatura para marcar un conjunto de pruebas como only
. Esto es lo mismo que suite([name], { only: true }[, fn])
.
test([name][, options][, fn])
[Historial]
Versión | Cambios |
---|---|
v20.2.0, v18.17.0 | Se añadieron las abreviaturas skip , todo y only . |
v18.8.0, v16.18.0 | Se añadió una opción signal . |
v18.7.0, v16.17.0 | Se añadió una opción timeout . |
v18.0.0, v16.17.0 | Añadido en: v18.0.0, v16.17.0 |
name
<string> El nombre de la prueba, que se muestra al informar de los resultados de las pruebas. Predeterminado: La propiedadname
defn
, o'\<anonymous\>'
sifn
no tiene nombre.options
<Object> Opciones de configuración para la prueba. Se admiten las siguientes propiedades:concurrency
<number> | <boolean> Si se proporciona un número, esa cantidad de pruebas se ejecutaría en paralelo dentro del hilo de la aplicación. Si estrue
, todas las pruebas asíncronas programadas se ejecutan concurrentemente dentro del hilo. Si esfalse
, solo se ejecuta una prueba a la vez. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:false
.only
<boolean> Si es verdadero, y el contexto de la prueba está configurado para ejecutar pruebasonly
, entonces esta prueba se ejecutará. De lo contrario, la prueba se omite. Predeterminado:false
.signal
<AbortSignal> Permite abortar una prueba en curso.skip
<boolean> | <string> Si es verdadero, la prueba se omite. Si se proporciona una cadena, esa cadena se muestra en los resultados de la prueba como la razón para omitir la prueba. Predeterminado:false
.todo
<boolean> | <string> Si es verdadero, la prueba se marca comoTODO
. Si se proporciona una cadena, esa cadena se muestra en los resultados de la prueba como la razón por la que la prueba esTODO
. Predeterminado:false
.timeout
<number> Un número de milisegundos después de los cuales la prueba fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.plan
<number> El número de aserciones y subpruebas que se espera que se ejecuten en la prueba. Si el número de aserciones ejecutadas en la prueba no coincide con el número especificado en el plan, la prueba fallará. Predeterminado:undefined
.
fn
<Function> | <AsyncFunction> La función bajo prueba. El primer argumento de esta función es un objetoTestContext
. Si la prueba utiliza devoluciones de llamada, la función de devolución de llamada se pasa como el segundo argumento. Predeterminado: Una función no operativa.Devuelve: <Promise> Cumplida con
undefined
una vez que se completa la prueba, o inmediatamente si la prueba se ejecuta dentro de un conjunto de pruebas.
La función test()
es el valor importado del módulo test
. Cada invocación de esta función resulta en informar de la prueba al <TestsStream>.
El objeto TestContext
pasado al argumento fn
se puede utilizar para realizar acciones relacionadas con la prueba actual. Los ejemplos incluyen omitir la prueba, añadir información de diagnóstico adicional o crear subpruebas.
test()
devuelve una Promise
que se cumple una vez que se completa la prueba. Si test()
se llama dentro de un conjunto de pruebas, se cumple inmediatamente. El valor de retorno normalmente se puede descartar para las pruebas de nivel superior. Sin embargo, el valor de retorno de las subpruebas debe utilizarse para evitar que la prueba principal termine primero y cancele la subprueba como se muestra en el siguiente ejemplo.
test('prueba de nivel superior', async (t) => {
// El setTimeout() en la siguiente subprueba haría que sobreviviera a su
// prueba principal si se elimina 'await' en la siguiente línea. Una vez que la prueba principal
// se completa, cancelará cualquier subprueba pendiente.
await t.test('subprueba de mayor duración', async (t) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
});
});
});
La opción timeout
se puede utilizar para hacer que la prueba falle si tarda más de timeout
milisegundos en completarse. Sin embargo, no es un mecanismo fiable para cancelar pruebas porque una prueba en ejecución podría bloquear el hilo de la aplicación y, por lo tanto, impedir la cancelación programada.
test.skip([name][, options][, fn])
Forma abreviada para omitir una prueba, igual que test([name], { skip: true }[, fn])
.
test.todo([name][, options][, fn])
Forma abreviada para marcar una prueba como TODO
, igual que test([name], { todo: true }[, fn])
.
test.only([name][, options][, fn])
Forma abreviada para marcar una prueba como only
, igual que test([name], { only: true }[, fn])
.
describe([name][, options][, fn])
Alias para suite()
.
La función describe()
se importa desde el módulo node:test
.
describe.skip([name][, options][, fn])
Forma abreviada para omitir un conjunto de pruebas. Esto es lo mismo que describe([name], { skip: true }[, fn])
.
describe.todo([name][, options][, fn])
Forma abreviada para marcar un conjunto de pruebas como TODO
. Esto es lo mismo que describe([name], { todo: true }[, fn])
.
describe.only([name][, options][, fn])
Agregado en: v19.8.0, v18.15.0
Forma abreviada para marcar un conjunto de pruebas como only
. Esto es lo mismo que describe([name], { only: true }[, fn])
.
it([name][, options][, fn])
[Historial]
Versión | Cambios |
---|---|
v19.8.0, v18.16.0 | Llamar a it() ahora es equivalente a llamar a test() . |
v18.6.0, v16.17.0 | Agregado en: v18.6.0, v16.17.0 |
Alias para test()
.
La función it()
se importa desde el módulo node:test
.
it.skip([name][, options][, fn])
Forma abreviada para omitir una prueba, igual que it([name], { skip: true }[, fn])
.
it.todo([name][, options][, fn])
Forma abreviada para marcar una prueba como TODO
, igual que it([name], { todo: true }[, fn])
.
it.only([name][, options][, fn])
Agregado en: v19.8.0, v18.15.0
Forma abreviada para marcar una prueba como only
, igual que it([name], { only: true }[, fn])
.
before([fn][, options])
Añadido en: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> La función hook. Si el hook usa callbacks, la función callback se pasa como el segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el hook. Se admiten las siguientes propiedades:signal
<AbortSignal> Permite abortar un hook en curso.timeout
<number> Un número de milisegundos después de los cuales el hook fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función crea un hook que se ejecuta antes de ejecutar una suite.
describe('tests', async () => {
before(() => console.log('a punto de ejecutar alguna prueba'));
it('es una subprueba', () => {
assert.ok('alguna aserción relevante aquí');
});
});
after([fn][, options])
Añadido en: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> La función hook. Si el hook usa callbacks, la función callback se pasa como el segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el hook. Se admiten las siguientes propiedades:signal
<AbortSignal> Permite abortar un hook en curso.timeout
<number> Un número de milisegundos después de los cuales el hook fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función crea un hook que se ejecuta después de ejecutar una suite.
describe('tests', async () => {
after(() => console.log('terminó de ejecutar pruebas'));
it('es una subprueba', () => {
assert.ok('alguna aserción relevante aquí');
});
});
Nota: Se garantiza que el hook after
se ejecutará, incluso si las pruebas dentro de la suite fallan.
beforeEach([fn][, options])
Añadido en: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> La función de hook. Si el hook utiliza callbacks, la función de callback se pasa como segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el hook. Se admiten las siguientes propiedades:signal
<AbortSignal> Permite abortar un hook en curso.timeout
<number> Un número de milisegundos después del cual el hook fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función crea un hook que se ejecuta antes de cada prueba en la suite actual.
describe('tests', async () => {
beforeEach(() => console.log('a punto de ejecutar una prueba'));
it('es una subprueba', () => {
assert.ok('alguna aserción relevante aquí');
});
});
afterEach([fn][, options])
Añadido en: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> La función de hook. Si el hook utiliza callbacks, la función de callback se pasa como segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el hook. Se admiten las siguientes propiedades:signal
<AbortSignal> Permite abortar un hook en curso.timeout
<number> Un número de milisegundos después del cual el hook fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función crea un hook que se ejecuta después de cada prueba en la suite actual. El hook afterEach()
se ejecuta incluso si la prueba falla.
describe('tests', async () => {
afterEach(() => console.log('terminó de ejecutar una prueba'));
it('es una subprueba', () => {
assert.ok('alguna aserción relevante aquí');
});
});
snapshot
Añadido en: v22.3.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
Un objeto cuyos métodos se utilizan para configurar los ajustes predeterminados de las instantáneas en el proceso actual. Es posible aplicar la misma configuración a todos los archivos colocando código de configuración común en un módulo precargado con --require
o --import
.
snapshot.setDefaultSnapshotSerializers(serializers)
Añadido en: v22.3.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
serializers
<Array> Un array de funciones síncronas utilizadas como serializadores predeterminados para las pruebas de instantáneas.
Esta función se utiliza para personalizar el mecanismo de serialización predeterminado utilizado por el ejecutor de pruebas. Por defecto, el ejecutor de pruebas realiza la serialización llamando a JSON.stringify(value, null, 2)
en el valor proporcionado. JSON.stringify()
tiene limitaciones con respecto a las estructuras circulares y los tipos de datos admitidos. Si se requiere un mecanismo de serialización más robusto, se debe utilizar esta función.
snapshot.setResolveSnapshotPath(fn)
Añadido en: v22.3.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
fn
<Function> Una función utilizada para calcular la ubicación del archivo de instantáneas. La función recibe la ruta del archivo de prueba como su único argumento. Si la prueba no está asociada a un archivo (por ejemplo, en el REPL), la entrada no está definida.fn()
debe devolver una cadena que especifique la ubicación del archivo de instantáneas.
Esta función se utiliza para personalizar la ubicación del archivo de instantáneas utilizado para las pruebas de instantáneas. Por defecto, el nombre del archivo de instantáneas es el mismo que el nombre del archivo del punto de entrada con una extensión de archivo .snapshot
.
Clase: MockFunctionContext
Agregado en: v19.1.0, v18.13.0
La clase MockFunctionContext
se utiliza para inspeccionar o manipular el comportamiento de los mocks creados a través de las API de MockTracker
.
ctx.calls
Agregado en: v19.1.0, v18.13.0
Un getter que devuelve una copia del array interno utilizado para rastrear las llamadas al mock. Cada entrada en el array es un objeto con las siguientes propiedades.
arguments
<Array> Un array de los argumentos pasados a la función mock.error
<any> Si la función simulada lanzó un error, entonces esta propiedad contiene el valor lanzado. Predeterminado:undefined
.result
<any> El valor devuelto por la función simulada.stack
<Error> Un objetoError
cuya pila puede utilizarse para determinar el callsite de la invocación de la función simulada.target
<Function> | <undefined> Si la función simulada es un constructor, este campo contiene la clase que se está construyendo. De lo contrario, seráundefined
.this
<any> El valorthis
de la función simulada.
ctx.callCount()
Agregado en: v19.1.0, v18.13.0
- Devuelve: <integer> El número de veces que se ha invocado este mock.
Esta función devuelve el número de veces que se ha invocado este mock. Esta función es más eficiente que comprobar ctx.calls.length
porque ctx.calls
es un getter que crea una copia del array interno de seguimiento de llamadas.
ctx.mockImplementation(implementation)
Añadido en: v19.1.0, v18.13.0
implementation
<Function> | <AsyncFunction> La función que se utilizará como la nueva implementación del mock.
Esta función se utiliza para cambiar el comportamiento de un mock existente.
El siguiente ejemplo crea una función mock utilizando t.mock.fn()
, llama a la función mock y luego cambia la implementación del mock a una función diferente.
test('cambia el comportamiento de un mock', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
cnt += 2;
return cnt;
}
const fn = t.mock.fn(addOne);
assert.strictEqual(fn(), 1);
fn.mock.mockImplementation(addTwo);
assert.strictEqual(fn(), 3);
assert.strictEqual(fn(), 5);
});
ctx.mockImplementationOnce(implementation[, onCall])
Añadido en: v19.1.0, v18.13.0
implementation
<Function> | <AsyncFunction> La función que se utilizará como la implementación del mock para el número de invocación especificado poronCall
.onCall
<integer> El número de invocación que usaráimplementation
. Si la invocación especificada ya ha ocurrido, se lanza una excepción. Predeterminado: El número de la siguiente invocación.
Esta función se utiliza para cambiar el comportamiento de un mock existente para una sola invocación. Una vez que la invocación onCall
ha ocurrido, el mock volverá al comportamiento que habría usado si mockImplementationOnce()
no se hubiera llamado.
El siguiente ejemplo crea una función mock utilizando t.mock.fn()
, llama a la función mock, cambia la implementación del mock a una función diferente para la siguiente invocación y luego reanuda su comportamiento anterior.
test('cambia el comportamiento de un mock una vez', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
cnt += 2;
return cnt;
}
const fn = t.mock.fn(addOne);
assert.strictEqual(fn(), 1);
fn.mock.mockImplementationOnce(addTwo);
assert.strictEqual(fn(), 3);
assert.strictEqual(fn(), 4);
});
ctx.resetCalls()
Agregado en: v19.3.0, v18.13.0
Restablece el historial de llamadas de la función simulada.
ctx.restore()
Agregado en: v19.1.0, v18.13.0
Restablece la implementación de la función simulada a su comportamiento original. La simulación todavía se puede usar después de llamar a esta función.
Clase: MockModuleContext
Agregado en: v22.3.0, v20.18.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
La clase MockModuleContext
se usa para manipular el comportamiento de las simulaciones de módulos creadas a través de las API de MockTracker
.
ctx.restore()
Agregado en: v22.3.0, v20.18.0
Restablece la implementación del módulo simulado.
Clase: MockTracker
Agregado en: v19.1.0, v18.13.0
La clase MockTracker
se usa para administrar la funcionalidad de simulación. El módulo de ejecución de pruebas proporciona una exportación mock
de nivel superior que es una instancia de MockTracker
. Cada prueba también proporciona su propia instancia de MockTracker
a través de la propiedad mock
del contexto de la prueba.
mock.fn([original[, implementation]][, options])
Agregado en: v19.1.0, v18.13.0
original
<Function> | <AsyncFunction> Una función opcional para crear una simulación. Predeterminado: Una función no operativa.implementation
<Function> | <AsyncFunction> Una función opcional que se usa como la implementación de la simulación paraoriginal
. Esto es útil para crear simulaciones que exhiben un comportamiento para un número específico de llamadas y luego restauran el comportamiento deoriginal
. Predeterminado: La función especificada pororiginal
.options
<Object> Opciones de configuración opcionales para la función simulada. Se admiten las siguientes propiedades:times
<integer> El número de veces que la simulación usará el comportamiento deimplementation
. Una vez que se ha llamado a la función simuladatimes
veces, restaurará automáticamente el comportamiento deoriginal
. Este valor debe ser un entero mayor que cero. Predeterminado:Infinity
.
Devuelve: <Proxy> La función simulada. La función simulada contiene una propiedad
mock
especial, que es una instancia deMockFunctionContext
, y se puede usar para inspeccionar y cambiar el comportamiento de la función simulada.
Esta función se usa para crear una función simulada.
El siguiente ejemplo crea una función simulada que incrementa un contador en uno en cada invocación. La opción times
se usa para modificar el comportamiento de la simulación de modo que las dos primeras invocaciones agreguen dos al contador en lugar de uno.
test('simula una función de conteo', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
cnt += 2;
return cnt;
}
const fn = t.mock.fn(addOne, addTwo, { times: 2 });
assert.strictEqual(fn(), 2);
assert.strictEqual(fn(), 4);
assert.strictEqual(fn(), 5);
assert.strictEqual(fn(), 6);
});
mock.getter(object, methodName[, implementation][, options])
Añadido en: v19.3.0, v18.13.0
Esta función es azúcar sintáctica para MockTracker.method
con options.getter
establecido en true
.
mock.method(object, methodName[, implementation][, options])
Añadido en: v19.1.0, v18.13.0
object
<Object> El objeto cuyo método se está simulando.methodName
<string> | <symbol> El identificador del método enobject
para simular. Siobject[methodName]
no es una función, se lanza un error.implementation
<Function> | <AsyncFunction> Una función opcional utilizada como implementación simulada paraobject[methodName]
. Predeterminado: El método original especificado porobject[methodName]
.options
<Object> Opciones de configuración opcionales para el método simulado. Se admiten las siguientes propiedades:getter
<boolean> Si estrue
,object[methodName]
se trata como un getter. Esta opción no se puede utilizar con la opciónsetter
. Predeterminado: false.setter
<boolean> Si estrue
,object[methodName]
se trata como un setter. Esta opción no se puede utilizar con la opcióngetter
. Predeterminado: false.times
<integer> El número de veces que la simulación utilizará el comportamiento deimplementation
. Una vez que el método simulado se ha llamadotimes
veces, restaurará automáticamente el comportamiento original. Este valor debe ser un entero mayor que cero. Predeterminado:Infinity
.
Devuelve: <Proxy> El método simulado. El método simulado contiene una propiedad especial
mock
, que es una instancia deMockFunctionContext
, y se puede utilizar para inspeccionar y cambiar el comportamiento del método simulado.
Esta función se utiliza para crear una simulación en un método de objeto existente. El siguiente ejemplo demuestra cómo se crea una simulación en un método de objeto existente.
test('espía un método de objeto', (t) => {
const number = {
value: 5,
subtract(a) {
return this.value - a;
},
};
t.mock.method(number, 'subtract');
assert.strictEqual(number.subtract.mock.callCount(), 0);
assert.strictEqual(number.subtract(3), 2);
assert.strictEqual(number.subtract.mock.callCount(), 1);
const call = number.subtract.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3]);
assert.strictEqual(call.result, 2);
assert.strictEqual(call.error, undefined);
assert.strictEqual(call.target, undefined);
assert.strictEqual(call.this, number);
});
mock.module(specifier[, options])
Agregado en: v22.3.0, v20.18.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
specifier
<string> | <URL> Una cadena que identifica el módulo a simular.options
<Object> Opciones de configuración opcionales para el módulo simulado. Se admiten las siguientes propiedades:cache
<boolean> Si esfalse
, cada llamada arequire()
oimport()
genera un nuevo módulo simulado. Si estrue
, las llamadas posteriores devolverán el mismo módulo simulado y el módulo simulado se insertará en la caché de CommonJS. Predeterminado: false.defaultExport
<any> Un valor opcional utilizado como la exportación predeterminada del módulo simulado. Si no se proporciona este valor, las simulaciones de ESM no incluyen una exportación predeterminada. Si la simulación es un módulo CommonJS o incorporado, esta configuración se utiliza como el valor demodule.exports
. Si no se proporciona este valor, las simulaciones de CJS e incorporadas utilizan un objeto vacío como el valor demodule.exports
.namedExports
<Object> Un objeto opcional cuyas claves y valores se utilizan para crear las exportaciones nombradas del módulo simulado. Si la simulación es un módulo CommonJS o incorporado, estos valores se copian enmodule.exports
. Por lo tanto, si se crea una simulación con exportaciones nombradas y una exportación predeterminada que no es un objeto, la simulación generará una excepción cuando se utilice como un módulo CJS o incorporado.
Devuelve: <MockModuleContext> Un objeto que se puede utilizar para manipular la simulación.
Esta función se utiliza para simular las exportaciones de módulos ECMAScript, módulos CommonJS y módulos incorporados de Node.js. Cualquier referencia al módulo original antes de la simulación no se ve afectada. Para habilitar la simulación de módulos, Node.js debe iniciarse con el indicador de línea de comandos --experimental-test-module-mocks
.
El siguiente ejemplo demuestra cómo se crea una simulación para un módulo.
test('simula un módulo incorporado en ambos sistemas de módulos', async (t) => {
// Crea una simulación de 'node:readline' con una exportación nombrada llamada 'fn', que
// no existe en el módulo original 'node:readline'.
const mock = t.mock.module('node:readline', {
namedExports: { fn() { return 42; } },
});
let esmImpl = await import('node:readline');
let cjsImpl = require('node:readline');
// cursorTo() es una exportación del módulo original 'node:readline'.
assert.strictEqual(esmImpl.cursorTo, undefined);
assert.strictEqual(cjsImpl.cursorTo, undefined);
assert.strictEqual(esmImpl.fn(), 42);
assert.strictEqual(cjsImpl.fn(), 42);
mock.restore();
// Se restaura la simulación, por lo que se devuelve el módulo incorporado original.
esmImpl = await import('node:readline');
cjsImpl = require('node:readline');
assert.strictEqual(typeof esmImpl.cursorTo, 'function');
assert.strictEqual(typeof cjsImpl.cursorTo, 'function');
assert.strictEqual(esmImpl.fn, undefined);
assert.strictEqual(cjsImpl.fn, undefined);
});
mock.reset()
Añadido en: v19.1.0, v18.13.0
Esta función restaura el comportamiento predeterminado de todas las simulaciones que fueron creadas previamente por este MockTracker
y desasocia las simulaciones de la instancia de MockTracker
. Una vez desasociadas, las simulaciones aún se pueden usar, pero la instancia de MockTracker
ya no se puede usar para restablecer su comportamiento o interactuar con ellas de otra manera.
Después de que se completa cada prueba, esta función se llama en el MockTracker
del contexto de la prueba. Si el MockTracker
global se usa extensivamente, se recomienda llamar a esta función manualmente.
mock.restoreAll()
Añadido en: v19.1.0, v18.13.0
Esta función restaura el comportamiento predeterminado de todas las simulaciones que fueron creadas previamente por este MockTracker
. A diferencia de mock.reset()
, mock.restoreAll()
no desasocia las simulaciones de la instancia de MockTracker
.
mock.setter(object, methodName[, implementation][, options])
Añadido en: v19.3.0, v18.13.0
Esta función es azúcar sintáctico para MockTracker.method
con options.setter
establecido en true
.
Clase: MockTimers
[Historial]
Versión | Cambios |
---|---|
v23.1.0 | Los Mock Timers ahora son estables. |
v20.4.0, v18.19.0 | Añadido en: v20.4.0, v18.19.0 |
[Estable: 2 - Estable]
Estable: 2 Estabilidad: 2 - Estable
La simulación de temporizadores es una técnica comúnmente utilizada en las pruebas de software para simular y controlar el comportamiento de los temporizadores, como setInterval
y setTimeout
, sin esperar realmente los intervalos de tiempo especificados.
MockTimers también puede simular el objeto Date
.
El MockTracker
proporciona una exportación timers
de nivel superior que es una instancia de MockTimers
.
timers.enable([enableOptions])
[Historial]
Versión | Cambios |
---|---|
v21.2.0, v20.11.0 | Parámetros actualizados para ser un objeto de opción con APIs disponibles y la época inicial predeterminada. |
v20.4.0, v18.19.0 | Añadido en: v20.4.0, v18.19.0 |
Habilita la simulación de temporizadores para los temporizadores especificados.
enableOptions
<Objeto> Opciones de configuración opcionales para habilitar la simulación de temporizadores. Se admiten las siguientes propiedades:apis
<Array> Una matriz opcional que contiene los temporizadores para simular. Los valores de temporizador admitidos actualmente son'setInterval'
,'setTimeout'
,'setImmediate'
y'Date'
. Predeterminado:['setInterval', 'setTimeout', 'setImmediate', 'Date']
. Si no se proporciona ninguna matriz, todas las APIs relacionadas con el tiempo ('setInterval'
,'clearInterval'
,'setTimeout'
,'clearTimeout'
,'setImmediate'
,'clearImmediate'
y'Date'
) se simularán de forma predeterminada.now
<number> | <Date> Un número opcional u objeto Date que representa la hora inicial (en milisegundos) para usar como valor paraDate.now()
. Predeterminado:0
.
Nota: Cuando habilita la simulación para un temporizador específico, su función de limpieza asociada también se simulará implícitamente.
Nota: La simulación de Date
afectará el comportamiento de los temporizadores simulados, ya que utilizan el mismo reloj interno.
Ejemplo de uso sin establecer la hora inicial:
import { mock } from 'node:test';
mock.timers.enable({ apis: ['setInterval'] });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['setInterval'] });
El ejemplo anterior habilita la simulación para el temporizador setInterval
e implícitamente simula la función clearInterval
. Solo se simularán las funciones setInterval
y clearInterval
de node:timers, node:timers/promises y globalThis
.
Ejemplo de uso con la hora inicial establecida
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: 1000 });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: 1000 });
Ejemplo de uso con un objeto Date inicial como hora establecida
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: new Date() });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: new Date() });
Alternativamente, si llama a mock.timers.enable()
sin ningún parámetro:
Todos los temporizadores ('setInterval'
, 'clearInterval'
, 'setTimeout'
, 'clearTimeout'
, 'setImmediate'
y 'clearImmediate'
) se simularán. Las funciones setInterval
, clearInterval
, setTimeout
, clearTimeout
, setImmediate
y clearImmediate
de node:timers
, node:timers/promises
y globalThis
se simularán. Así como el objeto global Date
.
timers.reset()
Añadido en: v20.4.0, v18.19.0
Esta función restaura el comportamiento predeterminado de todas las simulaciones que fueron creadas previamente por esta instancia de MockTimers
y desvincula las simulaciones de la instancia de MockTracker
.
Nota: Después de que cada prueba se completa, esta función es llamada en el MockTracker
del contexto de prueba.
import { mock } from 'node:test';
mock.timers.reset();
const { mock } = require('node:test');
mock.timers.reset();
timers[Symbol.dispose]()
Llama a timers.reset()
.
timers.tick([milliseconds])
Añadido en: v20.4.0, v18.19.0
Avanza el tiempo para todos los temporizadores simulados.
milliseconds
<number> La cantidad de tiempo, en milisegundos, para avanzar los temporizadores. Predeterminado:1
.
Nota: Esto difiere de cómo se comporta setTimeout
en Node.js y acepta solo números positivos. En Node.js, setTimeout
con números negativos solo se admite por razones de compatibilidad web.
El siguiente ejemplo simula una función setTimeout
y, al usar .tick
, avanza en el tiempo activando todos los temporizadores pendientes.
import assert from 'node:assert';
import { test } from 'node:test';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
Alternativamente, la función .tick
se puede llamar muchas veces
import assert from 'node:assert';
import { test } from 'node:test';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout'] });
const nineSecs = 9000;
setTimeout(fn, nineSecs);
const threeSeconds = 3000;
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
assert.strictEqual(fn.mock.callCount(), 1);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout'] });
const nineSecs = 9000;
setTimeout(fn, nineSecs);
const threeSeconds = 3000;
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
assert.strictEqual(fn.mock.callCount(), 1);
});
Avanzar en el tiempo usando .tick
también avanzará el tiempo para cualquier objeto Date
creado después de que la simulación se habilitó (si Date
también se configuró para ser simulado).
import assert from 'node:assert';
import { test } from 'node:test';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 0);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 9999);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 0);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 9999);
});
Usando funciones de limpieza
Como se mencionó, todas las funciones de limpieza de temporizadores (clearTimeout
, clearInterval
y clearImmediate
) se simulan implícitamente. Echa un vistazo a este ejemplo usando setTimeout
:
import assert from 'node:assert';
import { test } from 'node:test';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout'] });
const id = setTimeout(fn, 9999);
// También simulado implícitamente
clearTimeout(id);
context.mock.timers.tick(9999);
// Como ese setTimeout fue limpiado, la función simulada nunca será llamada
assert.strictEqual(fn.mock.callCount(), 0);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', (context) => {
const fn = context.mock.fn();
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout'] });
const id = setTimeout(fn, 9999);
// También simulado implícitamente
clearTimeout(id);
context.mock.timers.tick(9999);
// Como ese setTimeout fue limpiado, la función simulada nunca será llamada
assert.strictEqual(fn.mock.callCount(), 0);
});
Trabajando con módulos de temporizadores de Node.js
Una vez que habilitas la simulación de temporizadores, los módulos node:timers, node:timers/promises y los temporizadores del contexto global de Node.js están habilitados:
Nota: La desestructuración de funciones como import { setTimeout } from 'node:timers'
actualmente no es compatible con esta API.
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimers from 'node:timers';
import nodeTimersPromises from 'node:timers/promises';
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', async (context) => {
const globalTimeoutObjectSpy = context.mock.fn();
const nodeTimerSpy = context.mock.fn();
const nodeTimerPromiseSpy = context.mock.fn();
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(globalTimeoutObjectSpy, 9999);
nodeTimers.setTimeout(nodeTimerSpy, 9999);
const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1);
assert.strictEqual(nodeTimerSpy.mock.callCount(), 1);
await promise;
assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1);
});
const assert = require('node:assert');
const { test } = require('node:test');
const nodeTimers = require('node:timers');
const nodeTimersPromises = require('node:timers/promises');
test('simula setTimeout para que se ejecute sincrónicamente sin tener que esperar realmente', async (context) => {
const globalTimeoutObjectSpy = context.mock.fn();
const nodeTimerSpy = context.mock.fn();
const nodeTimerPromiseSpy = context.mock.fn();
// Opcionalmente elige qué simular
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(globalTimeoutObjectSpy, 9999);
nodeTimers.setTimeout(nodeTimerSpy, 9999);
const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);
// Avanzar en el tiempo
context.mock.timers.tick(9999);
assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1);
assert.strictEqual(nodeTimerSpy.mock.callCount(), 1);
await promise;
assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1);
});
En Node.js, setInterval
de node:timers/promises es un AsyncGenerator
y también es compatible con esta API:
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimersPromises from 'node:timers/promises';
test('debería avanzar cinco veces probando un caso de uso real', async (context) => {
context.mock.timers.enable({ apis: ['setInterval'] });
const expectedIterations = 3;
const interval = 1000;
const startedAt = Date.now();
async function run() {
const times = [];
for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
times.push(time);
if (times.length === expectedIterations) break;
}
return times;
}
const r = run();
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
const timeResults = await r;
assert.strictEqual(timeResults.length, expectedIterations);
for (let it = 1; it < expectedIterations; it++) {
assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
}
});
const assert = require('node:assert');
const { test } = require('node:test');
const nodeTimersPromises = require('node:timers/promises');
test('debería avanzar cinco veces probando un caso de uso real', async (context) => {
context.mock.timers.enable({ apis: ['setInterval'] });
const expectedIterations = 3;
const interval = 1000;
const startedAt = Date.now();
async function run() {
const times = [];
for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
times.push(time);
if (times.length === expectedIterations) break;
}
return times;
}
const r = run();
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
const timeResults = await r;
assert.strictEqual(timeResults.length, expectedIterations);
for (let it = 1; it < expectedIterations; it++) {
assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
}
});
timers.runAll()
Añadido en: v20.4.0, v18.19.0
Activa todos los temporizadores simulados pendientes inmediatamente. Si el objeto Date
también está simulado, también avanzará el objeto Date
al tiempo del temporizador más lejano.
El ejemplo siguiente activa todos los temporizadores pendientes inmediatamente, lo que hace que se ejecuten sin demora.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
// Notice that if both timers have the same timeout,
// the order of execution is guaranteed
setTimeout(() => results.push(3), 8888);
setTimeout(() => results.push(2), 8888);
assert.deepStrictEqual(results, []);
context.mock.timers.runAll();
assert.deepStrictEqual(results, [3, 2, 1]);
// The Date object is also advanced to the furthest timer's time
assert.strictEqual(Date.now(), 9999);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
// Notice that if both timers have the same timeout,
// the order of execution is guaranteed
setTimeout(() => results.push(3), 8888);
setTimeout(() => results.push(2), 8888);
assert.deepStrictEqual(results, []);
context.mock.timers.runAll();
assert.deepStrictEqual(results, [3, 2, 1]);
// The Date object is also advanced to the furthest timer's time
assert.strictEqual(Date.now(), 9999);
});
Nota: La función runAll()
está diseñada específicamente para activar temporizadores en el contexto de la simulación de temporizadores. No tiene ningún efecto en los relojes del sistema en tiempo real ni en los temporizadores reales fuera del entorno de simulación.
timers.setTime(milliseconds)
Añadido en: v21.2.0, v20.11.0
Establece la marca de tiempo Unix actual que se utilizará como referencia para cualquier objeto Date
simulado.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
const now = Date.now();
const setTime = 1000;
// Date.now is not mocked
assert.deepStrictEqual(Date.now(), now);
context.mock.timers.enable({ apis: ['Date'] });
context.mock.timers.setTime(setTime);
// Date.now is now 1000
assert.strictEqual(Date.now(), setTime);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('setTime replaces current time', (context) => {
const now = Date.now();
const setTime = 1000;
// Date.now is not mocked
assert.deepStrictEqual(Date.now(), now);
context.mock.timers.enable({ apis: ['Date'] });
context.mock.timers.setTime(setTime);
// Date.now is now 1000
assert.strictEqual(Date.now(), setTime);
});
Fechas y temporizadores trabajando juntos
Las fechas y los objetos temporizadores dependen unos de otros. Si usas setTime()
para pasar la hora actual al objeto Date
simulado, los temporizadores establecidos con setTimeout
y setInterval
no se verán afectados.
Sin embargo, el método tick
avanzará el objeto Date
simulado.
import assert from 'node:assert';
import { test } from 'node:test';
test('ejecuta todas las funciones siguiendo el orden dado', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
assert.deepStrictEqual(results, []);
context.mock.timers.setTime(12000);
assert.deepStrictEqual(results, []);
// La fecha avanza pero los temporizadores no hacen tick
assert.strictEqual(Date.now(), 12000);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('ejecuta todas las funciones siguiendo el orden dado', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
assert.deepStrictEqual(results, []);
context.mock.timers.setTime(12000);
assert.deepStrictEqual(results, []);
// La fecha avanza pero los temporizadores no hacen tick
assert.strictEqual(Date.now(), 12000);
});
Clase: TestsStream
[Historia]
Versión | Cambios |
---|---|
v20.0.0, v19.9.0, v18.17.0 | se agregó el tipo a los eventos test:pass y test:fail para cuando la prueba es una suite. |
v18.9.0, v16.19.0 | Agregado en: v18.9.0, v16.19.0 |
- Extiende <Readable>
Una llamada exitosa al método run()
devolverá un nuevo objeto <TestsStream>, transmitiendo una serie de eventos que representan la ejecución de las pruebas. TestsStream
emitirá eventos, en el orden de la definición de las pruebas.
Se garantiza que algunos de los eventos se emitirán en el mismo orden en que se definen las pruebas, mientras que otros se emiten en el orden en que se ejecutan las pruebas.
Evento: 'test:coverage'
data
<Object>summary
<Object> Un objeto que contiene el informe de cobertura.files
<Array> Un array de informes de cobertura para archivos individuales. Cada informe es un objeto con el siguiente esquema:path
<string> La ruta absoluta del archivo.totalLineCount
<number> El número total de líneas.totalBranchCount
<number> El número total de ramas.totalFunctionCount
<number> El número total de funciones.coveredLineCount
<number> El número de líneas cubiertas.coveredBranchCount
<number> El número de ramas cubiertas.coveredFunctionCount
<number> El número de funciones cubiertas.coveredLinePercent
<number> El porcentaje de líneas cubiertas.coveredBranchPercent
<number> El porcentaje de ramas cubiertas.coveredFunctionPercent
<number> El porcentaje de funciones cubiertas.functions
<Array> Un array de funciones que representa la cobertura de funciones.name
<string> El nombre de la función.line
<number> El número de línea donde se define la función.count
<number> El número de veces que se llamó a la función.branches
<Array> Un array de ramas que representa la cobertura de ramas.line
<number> El número de línea donde se define la rama.count
<number> El número de veces que se tomó la rama.lines
<Array> Un array de líneas que representa los números de línea y el número de veces que se cubrieron.line
<number> El número de línea.count
<number> El número de veces que se cubrió la línea.thresholds
<Object> Un objeto que contiene si se alcanzó o no la cobertura para cada tipo de cobertura.function
<number> El umbral de cobertura de función.branch
<number> El umbral de cobertura de rama.line
<number> El umbral de cobertura de línea.totals
<Object> Un objeto que contiene un resumen de la cobertura de todos los archivos.totalLineCount
<number> El número total de líneas.totalBranchCount
<number> El número total de ramas.totalFunctionCount
<number> El número total de funciones.coveredLineCount
<number> El número de líneas cubiertas.coveredBranchCount
<number> El número de ramas cubiertas.coveredFunctionCount
<number> El número de funciones cubiertas.coveredLinePercent
<number> El porcentaje de líneas cubiertas.coveredBranchPercent
<number> El porcentaje de ramas cubiertas.coveredFunctionPercent
<number> El porcentaje de funciones cubiertas.workingDirectory
<string> El directorio de trabajo cuando comenzó la cobertura de código. Esto es útil para mostrar nombres de ruta relativos en caso de que las pruebas cambien el directorio de trabajo del proceso de Node.js.nesting
<number> El nivel de anidamiento de la prueba.
Se emite cuando la cobertura de código está habilitada y todas las pruebas se han completado.
Evento: 'test:complete'
data
<Object>column
<number> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través del REPL.details
<Object> Metadatos de ejecución adicionales.passed
<boolean> Indica si la prueba pasó o no.duration_ms
<number> La duración de la prueba en milisegundos.error
<Error> | <undefined> Un error que envuelve el error lanzado por la prueba si no pasó.cause
<Error> El error real lanzado por la prueba.type
<string> | <undefined> El tipo de la prueba, utilizado para indicar si se trata de una suite.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través del REPL.line
<number> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través del REPL.name
<string> El nombre de la prueba.nesting
<number> El nivel de anidamiento de la prueba.testNumber
<number> El número ordinal de la prueba.todo
<string> | <boolean> | <undefined> Presente si se llama acontext.todo
skip
<string> | <boolean> | <undefined> Presente si se llama acontext.skip
Se emite cuando una prueba completa su ejecución. Este evento no se emite en el mismo orden en que se definen las pruebas. Los eventos ordenados de declaración correspondientes son 'test:pass'
y 'test:fail'
.
Evento: 'test:dequeue'
data
<Object>column
<number> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través de REPL.line
<number> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.name
<string> El nombre de la prueba.nesting
<number> El nivel de anidamiento de la prueba.
Se emite cuando una prueba se saca de la cola, justo antes de que se ejecute. No se garantiza que este evento se emita en el mismo orden en que se definen las pruebas. El evento ordenado de declaración correspondiente es 'test:start'
.
Evento: 'test:diagnostic'
data
<Object>column
<number> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través de REPL.line
<number> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.message
<string> El mensaje de diagnóstico.nesting
<number> El nivel de anidamiento de la prueba.
Se emite cuando se llama a context.diagnostic
. Se garantiza que este evento se emita en el mismo orden en que se definen las pruebas.
Evento: 'test:enqueue'
data
<Objeto>column
<número> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través de REPL.line
<número> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.name
<string> El nombre de la prueba.nesting
<número> El nivel de anidación de la prueba.
Emitido cuando una prueba se pone en cola para su ejecución.
Evento: 'test:fail'
data
<Objeto>column
<número> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.details
<Objeto> Metadatos de ejecución adicionales.duration_ms
<número> La duración de la prueba en milisegundos.error
<Error> Un error que envuelve el error lanzado por la prueba.cause
<Error> El error real lanzado por la prueba.type
<string> | <undefined> El tipo de la prueba, utilizado para denotar si se trata de un conjunto de pruebas.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través de REPL.line
<número> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.name
<string> El nombre de la prueba.nesting
<número> El nivel de anidación de la prueba.testNumber
<número> El número ordinal de la prueba.todo
<string> | <boolean> | <undefined> Presente si se llamacontext.todo
skip
<string> | <boolean> | <undefined> Presente si se llamacontext.skip
Emitido cuando una prueba falla. Se garantiza que este evento se emitirá en el mismo orden en que se definen las pruebas. El evento ordenado de ejecución correspondiente es 'test:complete'
.
Evento: 'test:pass'
data
<Object>column
<number> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través del REPL.details
<Object> Metadatos de ejecución adicionales.duration_ms
<number> La duración de la prueba en milisegundos.type
<string> | <undefined> El tipo de la prueba, utilizado para denotar si se trata de un conjunto de pruebas.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través del REPL.line
<number> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través del REPL.name
<string> El nombre de la prueba.nesting
<number> El nivel de anidamiento de la prueba.testNumber
<number> El número ordinal de la prueba.todo
<string> | <boolean> | <undefined> Presente si se llama acontext.todo
skip
<string> | <boolean> | <undefined> Presente si se llama acontext.skip
Se emite cuando una prueba pasa. Se garantiza que este evento se emite en el mismo orden en que se definen las pruebas. El evento correspondiente ordenado por ejecución es 'test:complete'
.
Evento: 'test:plan'
data
<Object>column
<number> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través de REPL.line
<number> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.nesting
<number> El nivel de anidación de la prueba.count
<number> El número de subpruebas que se han ejecutado.
Se emite cuando todas las subpruebas se han completado para una prueba dada. Se garantiza que este evento se emite en el mismo orden en que se definen las pruebas.
Evento: 'test:start'
data
<Object>column
<number> | <undefined> El número de columna donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.file
<string> | <undefined> La ruta del archivo de prueba,undefined
si la prueba se ejecutó a través de REPL.line
<number> | <undefined> El número de línea donde se define la prueba, oundefined
si la prueba se ejecutó a través de REPL.name
<string> El nombre de la prueba.nesting
<number> El nivel de anidación de la prueba.
Se emite cuando una prueba comienza a informar su propio estado y el de sus subpruebas. Se garantiza que este evento se emite en el mismo orden en que se definen las pruebas. El evento ordenado de ejecución correspondiente es 'test:dequeue'
.
Evento: 'test:stderr'
data
<Object>
Se emite cuando una prueba en ejecución escribe en stderr
. Este evento solo se emite si se pasa el indicador --test
. No se garantiza que este evento se emita en el mismo orden en que se definen las pruebas.
Evento: 'test:stdout'
data
<Object>
Se emite cuando una prueba en ejecución escribe en stdout
. Este evento solo se emite si se pasa el indicador --test
. No se garantiza que este evento se emita en el mismo orden en que se definen las pruebas.
Evento: 'test:summary'
data
<Object>counts
<Object> Un objeto que contiene los recuentos de varios resultados de pruebas.cancelled
<number> El número total de pruebas canceladas.failed
<number> El número total de pruebas fallidas.passed
<number> El número total de pruebas aprobadas.skipped
<number> El número total de pruebas omitidas.suites
<number> El número total de suites ejecutadas.tests
<number> El número total de pruebas ejecutadas, excluyendo las suites.todo
<number> El número total de pruebas TODO.topLevel
<number> El número total de pruebas y suites de nivel superior.duration_ms
<number> La duración de la ejecución de la prueba en milisegundos.file
<string> | <undefined> La ruta del archivo de prueba que generó el resumen. Si el resumen corresponde a varios archivos, este valor esundefined
.success
<boolean> Indica si la ejecución de la prueba se considera exitosa o no. Si ocurre alguna condición de error, como una prueba fallida o un umbral de cobertura no cumplido, este valor se establecerá enfalse
.
Se emite cuando se completa una ejecución de prueba. Este evento contiene métricas pertenecientes a la ejecución de prueba completada y es útil para determinar si una ejecución de prueba pasó o falló. Si se utiliza el aislamiento de prueba a nivel de proceso, se genera un evento 'test:summary'
para cada archivo de prueba, además de un resumen acumulativo final.
Evento: 'test:watch:drained'
Emitido cuando no hay más pruebas en cola para su ejecución en modo de observación.
Clase: TestContext
[Historial]
Versión | Cambios |
---|---|
v20.1.0, v18.17.0 | La función before se agregó a TestContext. |
v18.0.0, v16.17.0 | Agregado en: v18.0.0, v16.17.0 |
Se pasa una instancia de TestContext
a cada función de prueba para interactuar con el ejecutor de pruebas. Sin embargo, el constructor TestContext
no se expone como parte de la API.
context.before([fn][, options])
Agregado en: v20.1.0, v18.17.0
fn
<Function> | <AsyncFunction> La función de enganche. El primer argumento para esta función es un objetoTestContext
. Si el enganche usa retrollamadas, la función de retrollamada se pasa como el segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el enganche. Se admiten las siguientes propiedades:signal
<AbortSignal> Permite anular un enganche en curso.timeout
<number> Un número de milisegundos después de los cuales el enganche fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función se utiliza para crear un enganche que se ejecuta antes de la subprueba de la prueba actual.
context.beforeEach([fn][, options])
Agregado en: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> La función de enganche. El primer argumento para esta función es un objetoTestContext
. Si el enganche usa retrollamadas, la función de retrollamada se pasa como el segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el enganche. Se admiten las siguientes propiedades:signal
<AbortSignal> Permite anular un enganche en curso.timeout
<number> Un número de milisegundos después de los cuales el enganche fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función se utiliza para crear un enganche que se ejecuta antes de cada subprueba de la prueba actual.
test('prueba de nivel superior', async (t) => {
t.beforeEach((t) => t.diagnostic(`a punto de ejecutar ${t.name}`));
await t.test(
'Esta es una subprueba',
(t) => {
assert.ok('alguna aserción relevante aquí');
},
);
});
context.after([fn][, options])
Agregado en: v19.3.0, v18.13.0
fn
<Function> | <AsyncFunction> La función de gancho. El primer argumento para esta función es un objetoTestContext
. Si el gancho usa retrollamadas, la función de retrollamada se pasa como el segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el gancho. Las siguientes propiedades son compatibles:signal
<AbortSignal> Permite abortar un gancho en curso.timeout
<number> Un número de milisegundos después de los cuales el gancho fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función se utiliza para crear un gancho que se ejecuta después de que finaliza la prueba actual.
test('prueba de nivel superior', async (t) => {
t.after((t) => t.diagnostic(`terminó de ejecutar ${t.name}`));
assert.ok('alguna aserción relevante aquí');
});
context.afterEach([fn][, options])
Agregado en: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> La función de gancho. El primer argumento para esta función es un objetoTestContext
. Si el gancho usa retrollamadas, la función de retrollamada se pasa como el segundo argumento. Predeterminado: Una función no operativa.options
<Object> Opciones de configuración para el gancho. Las siguientes propiedades son compatibles:signal
<AbortSignal> Permite abortar un gancho en curso.timeout
<number> Un número de milisegundos después de los cuales el gancho fallará. Si no se especifica, las subpruebas heredan este valor de su padre. Predeterminado:Infinity
.
Esta función se utiliza para crear un gancho que se ejecuta después de cada subprueba de la prueba actual.
test('prueba de nivel superior', async (t) => {
t.afterEach((t) => t.diagnostic(`terminó de ejecutar ${t.name}`));
await t.test(
'Esta es una subprueba',
(t) => {
assert.ok('alguna aserción relevante aquí');
},
);
});
context.assert
Añadido en: v22.2.0, v20.15.0
Un objeto que contiene métodos de aserción vinculados a context
. Las funciones de nivel superior del módulo node:assert
se exponen aquí con el propósito de crear planes de prueba.
test('test', (t) => {
t.plan(1);
t.assert.strictEqual(true, true);
});
context.assert.snapshot(value[, options])
Añadido en: v22.3.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.0 - Desarrollo temprano
value
<any> Un valor para serializar a una cadena. Si Node.js se inició con el flag--test-update-snapshots
, el valor serializado se escribe en el archivo de instantáneas. De lo contrario, el valor serializado se compara con el valor correspondiente en el archivo de instantáneas existente.options
<Object> Opciones de configuración opcionales. Se admiten las siguientes propiedades:serializers
<Array> Un arreglo de funciones sincrónicas utilizadas para serializarvalue
en una cadena.value
se pasa como el único argumento a la primera función de serialización. El valor de retorno de cada serializador se pasa como entrada al siguiente serializador. Una vez que se han ejecutado todos los serializadores, el valor resultante se convierte en una cadena. Predeterminado: Si no se proporcionan serializadores, se utilizan los serializadores predeterminados del ejecutor de pruebas.
Esta función implementa aserciones para pruebas de instantáneas.
test('prueba de instantánea con serialización predeterminada', (t) => {
t.assert.snapshot({ value1: 1, value2: 2 });
});
test('prueba de instantánea con serialización personalizada', (t) => {
t.assert.snapshot({ value3: 3, value4: 4 }, {
serializers: [(value) => JSON.stringify(value)],
});
});
context.diagnostic(message)
Agregado en: v18.0.0, v16.17.0
message
<string> Mensaje que se va a reportar.
Esta función se utiliza para escribir diagnósticos en la salida. Cualquier información de diagnóstico se incluye al final de los resultados de la prueba. Esta función no devuelve un valor.
test('prueba de nivel superior', (t) => {
t.diagnostic('Un mensaje de diagnóstico');
});
context.filePath
Agregado en: v22.6.0, v20.16.0
La ruta absoluta del archivo de prueba que creó la prueba actual. Si un archivo de prueba importa módulos adicionales que generan pruebas, las pruebas importadas devolverán la ruta del archivo de prueba raíz.
context.fullName
Agregado en: v22.3.0
El nombre de la prueba y cada uno de sus antepasados, separados por \>
.
context.name
Agregado en: v18.8.0, v16.18.0
El nombre de la prueba.
context.plan(count)
[Historial]
Versión | Cambios |
---|---|
v23.4.0 | Esta función ya no es experimental. |
v22.2.0, v20.15.0 | Agregado en: v22.2.0, v20.15.0 |
count
<number> El número de aserciones y subpruebas que se espera que se ejecuten.
Esta función se utiliza para establecer el número de aserciones y subpruebas que se espera que se ejecuten dentro de la prueba. Si el número de aserciones y subpruebas que se ejecutan no coincide con el recuento esperado, la prueba fallará.
test('prueba de nivel superior', (t) => {
t.plan(2);
t.assert.ok('alguna aserción relevante aquí');
t.test('subprueba', () => {});
});
Cuando se trabaja con código asíncrono, la función plan
se puede utilizar para garantizar que se ejecute el número correcto de aserciones:
test('planificación con flujos', (t, done) => {
function* generate() {
yield 'a';
yield 'b';
yield 'c';
}
const expected = ['a', 'b', 'c'];
t.plan(expected.length);
const stream = Readable.from(generate());
stream.on('data', (chunk) => {
t.assert.strictEqual(chunk, expected.shift());
});
stream.on('end', () => {
done();
});
});
context.runOnly(shouldRunOnlyTests)
Agregado en: v18.0.0, v16.17.0
shouldRunOnlyTests
<boolean> Indica si se deben ejecutar o no las pruebasonly
.
Si shouldRunOnlyTests
es verdadero, el contexto de la prueba solo ejecutará las pruebas que tengan la opción only
establecida. De lo contrario, se ejecutarán todas las pruebas. Si Node.js no se inició con la opción de línea de comandos --test-only
, esta función es una operación nula.
test('prueba de nivel superior', (t) => {
// El contexto de la prueba se puede configurar para ejecutar subpruebas con la opción 'only'.
t.runOnly(true);
return Promise.all([
t.test('esta subprueba ahora se omite'),
t.test('esta subprueba se ejecuta', { only: true }),
]);
});
context.signal
Agregado en: v18.7.0, v16.17.0
- Tipo: <AbortSignal>
Se puede utilizar para abortar las subtareas de la prueba cuando la prueba ha sido abortada.
test('prueba de nivel superior', async (t) => {
await fetch('some/uri', { signal: t.signal });
});
context.skip([message])
Agregado en: v18.0.0, v16.17.0
message
<string> Mensaje de omisión opcional.
Esta función hace que la salida de la prueba indique que la prueba se ha omitido. Si se proporciona message
, se incluye en la salida. Llamar a skip()
no finaliza la ejecución de la función de prueba. Esta función no devuelve un valor.
test('prueba de nivel superior', (t) => {
// Asegúrate de regresar aquí también si la prueba contiene lógica adicional.
t.skip('esto se omite');
});
context.todo([message])
Agregado en: v18.0.0, v16.17.0
message
<string> MensajeTODO
opcional.
Esta función agrega una directiva TODO
a la salida de la prueba. Si se proporciona message
, se incluye en la salida. Llamar a todo()
no finaliza la ejecución de la función de prueba. Esta función no devuelve un valor.
test('prueba de nivel superior', (t) => {
// Esta prueba está marcada como `TODO`
t.todo('esto es un todo');
});
context.test([name][, options][, fn])
[Historial]
Versión | Cambios |
---|---|
v18.8.0, v16.18.0 | Se añade la opción signal . |
v18.7.0, v16.17.0 | Se añade la opción timeout . |
v18.0.0, v16.17.0 | Añadido en: v18.0.0, v16.17.0 |
name
<string> El nombre del subtest, que se muestra al informar de los resultados de la prueba. Predeterminado: La propiedadname
defn
, o'\<anonymous\>'
sifn
no tiene un nombre.options
<Object> Opciones de configuración para el subtest. Se admiten las siguientes propiedades:concurrency
<number> | <boolean> | <null> Si se proporciona un número, esa cantidad de pruebas se ejecutaría en paralelo dentro del hilo de la aplicación. Si estrue
, ejecutaría todos los subtests en paralelo. Si esfalse
, sólo ejecutaría una prueba a la vez. Si no se especifica, los subtests heredan este valor de su padre. Predeterminado:null
.only
<boolean> Si es verdadero, y el contexto de la prueba está configurado para ejecutar pruebasonly
, entonces esta prueba se ejecutará. De lo contrario, la prueba se omite. Predeterminado:false
.signal
<AbortSignal> Permite abortar una prueba en curso.skip
<boolean> | <string> Si es verdadero, la prueba se omite. Si se proporciona una cadena, esa cadena se muestra en los resultados de la prueba como la razón para omitir la prueba. Predeterminado:false
.todo
<boolean> | <string> Si es verdadero, la prueba se marca comoTODO
. Si se proporciona una cadena, esa cadena se muestra en los resultados de la prueba como la razón por la que la prueba esTODO
. Predeterminado:false
.timeout
<number> Un número de milisegundos después de los cuales la prueba fallará. Si no se especifica, los subtests heredan este valor de su padre. Predeterminado:Infinity
.plan
<number> El número de aserciones y subtests que se espera que se ejecuten en la prueba. Si el número de aserciones ejecutadas en la prueba no coincide con el número especificado en el plan, la prueba fallará. Predeterminado:undefined
.
fn
<Function> | <AsyncFunction> La función bajo prueba. El primer argumento de esta función es un objetoTestContext
. Si la prueba utiliza callbacks, la función de callback se pasa como segundo argumento. Predeterminado: Una función no operativa.Returns: <Promise> Cumplida con
undefined
una vez que la prueba se completa.
Esta función se utiliza para crear subtests bajo la prueba actual. Esta función se comporta de la misma manera que la función test()
de nivel superior.
test('prueba de nivel superior', async (t) => {
await t.test(
'Este es un subtest',
{ only: false, skip: false, concurrency: 1, todo: false, plan: 1 },
(t) => {
t.assert.ok('alguna aserción relevante aquí');
},
);
});
Clase: SuiteContext
Añadido en: v18.7.0, v16.17.0
Una instancia de SuiteContext
se pasa a cada función de suite para interactuar con el ejecutor de pruebas. Sin embargo, el constructor SuiteContext
no se expone como parte de la API.
context.filePath
Añadido en: v22.6.0
La ruta absoluta del archivo de prueba que creó la suite actual. Si un archivo de prueba importa módulos adicionales que generan suites, las suites importadas devolverán la ruta del archivo de prueba raíz.
context.name
Añadido en: v18.8.0, v16.18.0
El nombre de la suite.
context.signal
Añadido en: v18.7.0, v16.17.0
- Tipo: <AbortSignal>
Se puede utilizar para abortar subtareas de prueba cuando la prueba ha sido abortada.