Executador de teste
[Histórico]
Versão | Alterações |
---|---|
v20.0.0 | O executor de teste agora está estável. |
v18.0.0, v16.17.0 | Adicionado em: v18.0.0, v16.17.0 |
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
Código-fonte: lib/test.js
O módulo node:test
facilita a criação de testes JavaScript. Para acessá-lo:
import test from 'node:test'
const test = require('node:test')
Este módulo está disponível apenas sob o esquema node:
.
Testes criados via o módulo test
consistem em uma única função que é processada de uma das três maneiras:
O exemplo a seguir ilustra como os testes são escritos usando o módulo test
.
test('teste síncrono aprovado', t => {
// Este teste é aprovado porque não lança uma exceção.
assert.strictEqual(1, 1)
})
test('teste síncrono reprovado', t => {
// Este teste falha porque lança uma exceção.
assert.strictEqual(1, 2)
})
test('teste assíncrono aprovado', async t => {
// Este teste é aprovado porque a Promise retornada pela função assíncrona
// é resolvida e não rejeitada.
assert.strictEqual(1, 1)
})
test('teste assíncrono reprovado', async t => {
// Este teste falha porque a Promise retornada pela função assíncrona
// é rejeitada.
assert.strictEqual(1, 2)
})
test('teste reprovado usando Promises', t => {
// Promises também podem ser usadas diretamente.
return new Promise((resolve, reject) => {
setImmediate(() => {
reject(new Error('isso fará com que o teste falhe'))
})
})
})
test('teste com callback aprovado', (t, done) => {
// done() é a função de callback. Quando o setImmediate() é executado, ele invoca
// done() sem argumentos.
setImmediate(done)
})
test('teste com callback reprovado', (t, done) => {
// Quando o setImmediate() é executado, done() é invocado com um objeto Error e
// o teste falha.
setImmediate(() => {
done(new Error('falha no callback'))
})
})
Se algum teste falhar, o código de saída do processo será definido como 1
.
Subtestes
O método test()
do contexto de teste permite a criação de subtestes. Ele permite que você estruture seus testes de forma hierárquica, onde você pode criar testes aninhados dentro de um teste maior. Este método se comporta de forma idêntica à função test()
de nível superior. O exemplo a seguir demonstra a criação de um teste de nível superior com dois subtestes.
test('teste de nível superior', async t => {
await t.test('subteste 1', t => {
assert.strictEqual(1, 1)
})
await t.test('subteste 2', t => {
assert.strictEqual(2, 2)
})
})
Neste exemplo, await
é usado para garantir que ambos os subtestes tenham sido concluídos. Isso é necessário porque os testes não esperam que seus subtestes sejam concluídos, ao contrário dos testes criados dentro de suítes. Quaisquer subtestes que ainda estiverem pendentes quando o pai terminar são cancelados e tratados como falhas. Qualquer falha de subteste faz com que o teste pai falhe.
Ignorando testes
Testes individuais podem ser ignorados passando a opção skip
para o teste, ou chamando o método skip()
do contexto do teste, como mostrado no exemplo a seguir.
// A opção skip é usada, mas nenhuma mensagem é fornecida.
test('opção skip', { skip: true }, t => {
// Este código nunca é executado.
})
// A opção skip é usada, e uma mensagem é fornecida.
test('opção skip com mensagem', { skip: 'isto está ignorado' }, t => {
// Este código nunca é executado.
})
test('método skip()', t => {
// Certifique-se de retornar aqui também se o teste contiver lógica adicional.
t.skip()
})
test('método skip() com mensagem', t => {
// Certifique-se de retornar aqui também se o teste contiver lógica adicional.
t.skip('isto está ignorado')
})
Testes TODO
Testes individuais podem ser marcados como instáveis ou incompletos passando a opção todo
para o teste, ou chamando o método todo()
do contexto do teste, como mostrado no exemplo a seguir. Esses testes representam uma implementação pendente ou um bug que precisa ser corrigido. Os testes TODO são executados, mas não são tratados como falhas de teste e, portanto, não afetam o código de saída do processo. Se um teste for marcado como TODO e ignorado, a opção TODO será ignorada.
// A opção todo é usada, mas nenhuma mensagem é fornecida.
test('opção todo', { todo: true }, t => {
// Este código é executado, mas não tratado como uma falha.
throw new Error('isto não falha no teste')
})
// A opção todo é usada, e uma mensagem é fornecida.
test('opção todo com mensagem', { todo: 'este é um teste todo' }, t => {
// Este código é executado.
})
test('método todo()', t => {
t.todo()
})
test('método todo() com mensagem', t => {
t.todo('este é um teste todo e não é tratado como uma falha')
throw new Error('isto não falha no teste')
})
Aliases describe()
e it()
Suítes e testes também podem ser escritos usando as funções describe()
e it()
. describe()
é um alias para suite()
, e it()
é um alias para test()
.
describe('Uma coisa', () => {
it('deve funcionar', () => {
assert.strictEqual(1, 1)
})
it('deve estar ok', () => {
assert.strictEqual(2, 2)
})
describe('uma coisa aninhada', () => {
it('deve funcionar', () => {
assert.strictEqual(3, 3)
})
})
})
describe()
e it()
são importados do módulo node:test
.
import { describe, it } from 'node:test'
const { describe, it } = require('node:test')
Testes only
Se o Node.js for iniciado com a opção de linha de comando --test-only
, ou o isolamento de teste estiver desabilitado, é possível pular todos os testes, exceto um subconjunto selecionado, passando a opção only
para os testes que devem ser executados. Quando um teste com a opção only
está definido, todos os subtestes também são executados. Se uma suíte tiver a opção only
definida, todos os testes dentro da suíte serão executados, a menos que tenha descendentes com a opção only
definida, caso em que apenas esses testes serão executados.
Ao usar subtestes dentro de um test()
/it()
, é necessário marcar todos os testes ancestrais com a opção only
para executar apenas um subconjunto selecionado de testes.
O método runOnly()
do contexto do teste pode ser usado para implementar o mesmo comportamento no nível do subteste. Testes que não são executados são omitidos da saída do executor de testes.
// Assume-se que o Node.js é executado com a opção de linha de comando --test-only.
// A opção 'only' da suíte está definida, então esses testes são executados.
test('este teste é executado', { only: true }, async t => {
// Dentro deste teste, todos os subtestes são executados por padrão.
await t.test('subteste em execução')
// O contexto do teste pode ser atualizado para executar subtestes com a opção 'only'.
t.runOnly(true)
await t.test('este subteste agora é ignorado')
await t.test('este subteste é executado', { only: true })
// Mude o contexto de volta para executar todos os testes.
t.runOnly(false)
await t.test('este subteste agora é executado')
// Explicitamente não execute esses testes.
await t.test('subteste ignorado 3', { only: false })
await t.test('subteste ignorado 4', { skip: true })
})
// A opção 'only' não está definida, então este teste é ignorado.
test('este teste não é executado', () => {
// Este código não é executado.
throw new Error('falha')
})
describe('uma suíte', () => {
// A opção 'only' está definida, então este teste é executado.
it('este teste é executado', { only: true }, () => {
// Este código é executado.
})
it('este teste não é executado', () => {
// Este código não é executado.
throw new Error('falha')
})
})
describe.only('uma suíte', () => {
// A opção 'only' está definida, então este teste é executado.
it('este teste é executado', () => {
// Este código é executado.
})
it('este teste é executado', () => {
// Este código é executado.
})
})
Filtrando testes por nome
A opção de linha de comando --test-name-pattern
pode ser usada para executar apenas testes cujo nome corresponda ao padrão fornecido, e a opção --test-skip-pattern
pode ser usada para pular testes cujo nome corresponda ao padrão fornecido. Os padrões de nome de teste são interpretados como expressões regulares JavaScript. As opções --test-name-pattern
e --test-skip-pattern
podem ser especificadas várias vezes para executar testes aninhados. Para cada teste executado, quaisquer ganchos de teste correspondentes, como beforeEach()
, também são executados. Testes que não são executados são omitidos da saída do executor de testes.
Dado o seguinte arquivo de teste, iniciar o Node.js com a opção --test-name-pattern="test [1-3]"
faria com que o executor de testes executasse test 1
, test 2
e test 3
. Se test 1
não correspondesse ao padrão de nome do teste, seus subtestes não seriam executados, apesar de corresponderem ao padrão. O mesmo conjunto de testes também poderia ser executado passando --test-name-pattern
várias vezes (por exemplo, --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')
})
Os padrões de nome de teste também podem ser especificados usando literais de expressão regular. Isso permite que flags de expressão regular sejam usadas. No exemplo anterior, iniciar o Node.js com --test-name-pattern="/test [4-5]/i"
(ou --test-skip-pattern="/test [4-5]/i"
) corresponderia a Test 4
e Test 5
porque o padrão não diferencia maiúsculas de minúsculas.
Para corresponder a um único teste com um padrão, você pode prefixá-lo com todos os nomes de seus testes ancestrais separados por espaço, para garantir que ele seja único. Por exemplo, dado o seguinte arquivo de teste:
describe('test 1', t => {
it('some test')
})
describe('test 2', t => {
it('some test')
})
Iniciar o Node.js com --test-name-pattern="test 1 some test"
corresponderia apenas a some test
em test 1
.
Os padrões de nome de teste não alteram o conjunto de arquivos que o executor de testes executa.
Se ambas as opções --test-name-pattern
e --test-skip-pattern
forem fornecidas, os testes devem satisfazer ambos os requisitos para serem executados.
Atividade assíncrona estranha
Assim que uma função de teste termina de executar, os resultados são relatados o mais rápido possível, mantendo a ordem dos testes. No entanto, é possível que a função de teste gere atividade assíncrona que sobreviva ao próprio teste. O executor de testes lida com esse tipo de atividade, mas não atrasa a geração de relatórios dos resultados dos testes para acomodá-la.
No exemplo a seguir, um teste é concluído com duas operações setImmediate()
ainda pendentes. A primeira setImmediate()
tenta criar um novo subteste. Como o teste pai já terminou e gerou seus resultados, o novo subteste é imediatamente marcado como falha e relatado posteriormente para o <TestsStream>.
A segunda setImmediate()
cria um evento uncaughtException
. Os eventos uncaughtException
e unhandledRejection
originários de um teste concluído são marcados como falha pelo módulo test
e relatados como avisos de diagnóstico no nível superior pelo <TestsStream>.
test('um teste que cria atividade assíncrona', t => {
setImmediate(() => {
t.test('subteste criado tarde demais', t => {
throw new Error('error1')
})
})
setImmediate(() => {
throw new Error('error2')
})
// O teste termina após esta linha.
})
Modo de observação
Adicionado em: v19.2.0, v18.13.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1 - Experimental
O executor de testes Node.js suporta a execução no modo de observação passando a flag --watch
:
node --test --watch
No modo de observação, o executor de testes monitorará as alterações nos arquivos de teste e suas dependências. Quando uma alteração é detectada, o executor de testes reexecutará os testes afetados pela alteração. O executor de testes continuará a executar até que o processo seja encerrado.
Executando testes a partir da linha de comando
O executor de testes Node.js pode ser invocado a partir da linha de comando passando a flag --test
:
node --test
Por padrão, o Node.js executará todos os arquivos que correspondem a estes padrões:
**/*.test.{cjs,mjs,js}
**/*-test.{cjs,mjs,js}
**/*_test.{cjs,mjs,js}
**/test-*.{cjs,mjs,js}
**/test.{cjs,mjs,js}
**/test/**/*.{cjs,mjs,js}
Quando --experimental-strip-types
é fornecido, os seguintes padrões adicionais são correspondidos:
**/*.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, um ou mais padrões glob podem ser fornecidos como argumento(s) final(is) para o comando Node.js, como mostrado abaixo. Os padrões glob seguem o comportamento de glob(7)
. Os padrões glob devem estar entre aspas duplas na linha de comando para evitar a expansão do shell, o que pode reduzir a portabilidade entre sistemas.
node --test "**/*.test.js" "**/*.spec.js"
Os arquivos correspondentes são executados como arquivos de teste. Mais informações sobre a execução do arquivo de teste podem ser encontradas na seção modelo de execução do executor de testes.
Modelo de execução do testador
Quando o isolamento de teste em nível de processo está habilitado, cada arquivo de teste correspondente é executado em um processo filho separado. O número máximo de processos filhos em execução a qualquer momento é controlado pela flag --test-concurrency
. Se o processo filho terminar com um código de saída 0, o teste é considerado aprovado. Caso contrário, o teste é considerado uma falha. Os arquivos de teste devem ser executáveis pelo Node.js, mas não precisam usar o módulo node:test
internamente.
Cada arquivo de teste é executado como se fosse um script regular. Ou seja, se o próprio arquivo de teste usar node:test
para definir testes, todos esses testes serão executados em uma única thread de aplicativo, independentemente do valor da opção concurrency
de test()
.
Quando o isolamento de teste em nível de processo está desabilitado, cada arquivo de teste correspondente é importado para o processo do testador. Depois que todos os arquivos de teste forem carregados, os testes de nível superior são executados com uma concorrência de um. Como todos os arquivos de teste são executados no mesmo contexto, é possível que os testes interajam uns com os outros de maneiras que não são possíveis quando o isolamento está habilitado. Por exemplo, se um teste depender de um estado global, é possível que esse estado seja modificado por um teste originário de outro arquivo.
Coletando cobertura de código
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1 - Experimental
Quando o Node.js é iniciado com a flag de linha de comando --experimental-test-coverage
, a cobertura de código é coletada e as estatísticas são relatadas assim que todos os testes forem concluídos. Se a variável de ambiente NODE_V8_COVERAGE
for usada para especificar um diretório de cobertura de código, os arquivos de cobertura V8 gerados serão gravados nesse diretório. Os módulos principais do Node.js e os arquivos dentro dos diretórios node_modules/
são, por padrão, não incluídos no relatório de cobertura. No entanto, eles podem ser incluídos explicitamente por meio da flag --test-coverage-include
. Por padrão, todos os arquivos de teste correspondentes são excluídos do relatório de cobertura. As exclusões podem ser substituídas usando a flag --test-coverage-exclude
. Se a cobertura estiver habilitada, o relatório de cobertura é enviado a quaisquer relatórios de teste por meio do evento 'test:coverage'
.
A cobertura pode ser desabilitada em uma série de linhas usando a seguinte sintaxe de comentário:
/* node:coverage disable */
if (anAlwaysFalseCondition) {
// O código neste ramo nunca será executado, mas as linhas são ignoradas para
// fins de cobertura. Todas as linhas após o comentário 'disable' são ignoradas
// até que um comentário 'enable' correspondente seja encontrado.
console.log('isso nunca será executado')
}
/* node:coverage enable */
A cobertura também pode ser desabilitada para um número especificado de linhas. Após o número especificado de linhas, a cobertura será automaticamente reabilitada. Se o número de linhas não for fornecido explicitamente, uma única linha será ignorada.
/* node:coverage ignore next */
if (anAlwaysFalseCondition) {
console.log('isso nunca será executado')
}
/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
console.log('isso nunca será executado')
}
Relatórios de cobertura
Os relatores tap
e spec
imprimirão um resumo das estatísticas de cobertura. Existe também um relator lcov
que gerará um arquivo lcov
, que pode ser usado como um relatório de cobertura detalhado.
node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info
- Este relator não relata resultados de teste.
- Idealmente, este relator deve ser usado junto com outro relator.
Simulação (Mocking)
O módulo node:test
suporta simulação durante os testes através de um objeto mock
de nível superior. O exemplo a seguir cria um espião em uma função que adiciona dois números. O espião é então usado para afirmar que a função foi chamada conforme o esperado.
import assert from 'node:assert'
import { mock, test } from 'node:test'
test('espião em uma função', () => {
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)
// Redefine as simulações rastreadas globalmente.
mock.reset()
})
'use strict'
const assert = require('node:assert')
const { mock, test } = require('node:test')
test('espião em uma função', () => {
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)
// Redefine as simulações rastreadas globalmente.
mock.reset()
})
A mesma funcionalidade de simulação também é exposta no objeto TestContext
de cada teste. O exemplo a seguir cria um espião em um método de objeto usando a API exposta no TestContext
. O benefício da simulação via contexto de teste é que o executor de teste restaurará automaticamente toda a funcionalidade simulada assim que o teste terminar.
test('espião em um 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
Simular temporizadores é uma técnica comumente usada em testes de software para simular e controlar o comportamento de temporizadores, como setInterval
e setTimeout
, sem realmente esperar pelos intervalos de tempo especificados.
Consulte a classe MockTimers
para uma lista completa de métodos e recursos.
Isso permite que os desenvolvedores escrevam testes mais confiáveis e previsíveis para funcionalidades dependentes do tempo.
O exemplo abaixo mostra como simular setTimeout
. Usando .enable({ apis: ['setTimeout'] });
, ele simulará as funções setTimeout
nos módulos node:timers e node:timers/promises, bem como do contexto global do Node.js.
Observação: Funções de desestruturação como import { setTimeout } from 'node:timers'
não são atualmente suportadas por esta API.
import assert from 'node:assert'
import { mock, test } from 'node:test'
test('simula setTimeout para ser executado sincronicamente sem precisar realmente esperar por ele', () => {
const fn = mock.fn()
// Opcionalmente escolha o que simular
mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(fn, 9999)
assert.strictEqual(fn.mock.callCount(), 0)
// Avançar no tempo
mock.timers.tick(9999)
assert.strictEqual(fn.mock.callCount(), 1)
// Redefinir as simulações rastreadas globalmente.
mock.timers.reset()
// Se você chamar reset mock instance, ele também redefinirá a instância de timers
mock.reset()
})
const assert = require('node:assert')
const { mock, test } = require('node:test')
test('simula setTimeout para ser executado sincronicamente sem precisar realmente esperar por ele', () => {
const fn = mock.fn()
// Opcionalmente escolha o que simular
mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(fn, 9999)
assert.strictEqual(fn.mock.callCount(), 0)
// Avançar no tempo
mock.timers.tick(9999)
assert.strictEqual(fn.mock.callCount(), 1)
// Redefinir as simulações rastreadas globalmente.
mock.timers.reset()
// Se você chamar reset mock instance, ele também redefinirá a instância de timers
mock.reset()
})
A mesma funcionalidade de simulação também é exposta na propriedade mock no objeto TestContext
de cada teste. O benefício de simular via contexto de teste é que o executor de teste restaurará automaticamente todas as funcionalidades de temporizadores simulados assim que o teste terminar.
import assert from 'node:assert'
import { test } from 'node:test'
test('simula setTimeout para ser executado sincronicamente sem precisar realmente esperar por ele', context => {
const fn = context.mock.fn()
// Opcionalmente escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(fn, 9999)
assert.strictEqual(fn.mock.callCount(), 0)
// Avançar no tempo
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 ser executado sincronicamente sem precisar realmente esperar por ele', context => {
const fn = context.mock.fn()
// Opcionalmente escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(fn, 9999)
assert.strictEqual(fn.mock.callCount(), 0)
// Avançar no tempo
context.mock.timers.tick(9999)
assert.strictEqual(fn.mock.callCount(), 1)
})
Datas
A API de timers simulados também permite a simulação do objeto Date
. Este é um recurso útil para testar funcionalidades dependentes do tempo ou para simular funções de calendário internas, como Date.now()
.
A implementação de datas também faz parte da classe MockTimers
. Consulte-a para obter uma lista completa de métodos e recursos.
Nota: Datas e timers são dependentes quando simulados juntos. Isso significa que, se você tiver ambos os Date
e setTimeout
simulados, o avanço do tempo também avançará a data simulada, pois eles simulam um único relógio interno.
O exemplo abaixo mostra como simular o objeto Date
e obter o valor atual de Date.now()
.
import assert from 'node:assert'
import { test } from 'node:test'
test('simula o objeto Date', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['Date'] })
// Se não especificado, a data inicial será baseada em 0 na época Unix
assert.strictEqual(Date.now(), 0)
// O avanço no tempo também avançará a data
context.mock.timers.tick(9999)
assert.strictEqual(Date.now(), 9999)
})
const assert = require('node:assert')
const { test } = require('node:test')
test('simula o objeto Date', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['Date'] })
// Se não especificado, a data inicial será baseada em 0 na época Unix
assert.strictEqual(Date.now(), 0)
// O avanço no tempo também avançará a data
context.mock.timers.tick(9999)
assert.strictEqual(Date.now(), 9999)
})
Se não houver nenhuma época inicial definida, a data inicial será baseada em 0 na época Unix. Esta é 1º de janeiro de 1970, 00:00:00 UTC. Você pode definir uma data inicial passando uma propriedade now
para o método .enable()
. Esse valor será usado como a data inicial para o objeto Date
simulado. Pode ser um inteiro positivo ou outro objeto Date.
import assert from 'node:assert'
import { test } from 'node:test'
test('simula o objeto Date com tempo inicial', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['Date'], now: 100 })
assert.strictEqual(Date.now(), 100)
// O avanço no tempo também avançará a data
context.mock.timers.tick(200)
assert.strictEqual(Date.now(), 300)
})
const assert = require('node:assert')
const { test } = require('node:test')
test('simula o objeto Date com tempo inicial', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['Date'], now: 100 })
assert.strictEqual(Date.now(), 100)
// O avanço no tempo também avançará a data
context.mock.timers.tick(200)
assert.strictEqual(Date.now(), 300)
})
Você pode usar o método .setTime()
para mover manualmente a data simulada para outro horário. Este método só aceita um inteiro positivo.
Nota: Este método executará todos os timers simulados que estão no passado a partir do novo horário.
No exemplo abaixo, estamos definindo um novo horário para a data simulada.
import assert from 'node:assert'
import { test } from 'node:test'
test('define o horário de um objeto de data', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['Date'], now: 100 })
assert.strictEqual(Date.now(), 100)
// O avanço no tempo também avançará a data
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('define o horário de um objeto de data', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['Date'], now: 100 })
assert.strictEqual(Date.now(), 100)
// O avanço no tempo também avançará a data
context.mock.timers.setTime(1000)
context.mock.timers.tick(200)
assert.strictEqual(Date.now(), 1200)
})
Se você tiver algum timer definido para ser executado no passado, ele será executado como se o método .tick()
tivesse sido chamado. Isso é útil se você quiser testar a funcionalidade dependente do tempo que já está no passado.
import assert from 'node:assert'
import { test } from 'node:test'
test('executa timers conforme setTime passa ticks', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
const fn = context.mock.fn()
setTimeout(fn, 1000)
context.mock.timers.setTime(800)
// O timer não é executado, pois o tempo ainda não foi atingido
assert.strictEqual(fn.mock.callCount(), 0)
assert.strictEqual(Date.now(), 800)
context.mock.timers.setTime(1200)
// O timer é executado, pois o tempo agora foi atingido
assert.strictEqual(fn.mock.callCount(), 1)
assert.strictEqual(Date.now(), 1200)
})
const assert = require('node:assert')
const { test } = require('node:test')
test('executa timers conforme setTime passa ticks', context => {
// Opcionalmente, escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
const fn = context.mock.fn()
setTimeout(fn, 1000)
context.mock.timers.setTime(800)
// O timer não é executado, pois o tempo ainda não foi atingido
assert.strictEqual(fn.mock.callCount(), 0)
assert.strictEqual(Date.now(), 800)
context.mock.timers.setTime(1200)
// O timer é executado, pois o tempo agora foi atingido
assert.strictEqual(fn.mock.callCount(), 1)
assert.strictEqual(Date.now(), 1200)
})
Usando .runAll()
executará todos os timers que estão atualmente na fila. Isso também avançará a data simulada para o horário do último timer que foi executado, como se o tempo tivesse passado.
import assert from 'node:assert'
import { test } from 'node:test'
test('executa timers conforme setTime passa ticks', context => {
// Opcionalmente, escolha o que 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 os timers são executados, pois o tempo agora foi atingido
assert.strictEqual(fn.mock.callCount(), 3)
assert.strictEqual(Date.now(), 3000)
})
const assert = require('node:assert')
const { test } = require('node:test')
test('executa timers conforme setTime passa ticks', context => {
// Opcionalmente, escolha o que 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 os timers são executados, pois o tempo agora foi atingido
assert.strictEqual(fn.mock.callCount(), 3)
assert.strictEqual(Date.now(), 3000)
})
Testes de instantâneo
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
Testes de instantâneo permitem que valores arbitrários sejam serializados em valores de string e comparados com um conjunto de valores conhecidos como bons. Os valores conhecidos como bons são conhecidos como instantâneos e são armazenados em um arquivo de instantâneo. Os arquivos de instantâneo são gerenciados pelo executor de teste, mas são projetados para serem legíveis por humanos para auxiliar na depuração. A melhor prática é que os arquivos de instantâneo sejam enviados para o controle de origem junto com seus arquivos de teste.
Os arquivos de instantâneo são gerados iniciando o Node.js com a flag de linha de comando --test-update-snapshots
. Um arquivo de instantâneo separado é gerado para cada arquivo de teste. Por padrão, o arquivo de instantâneo tem o mesmo nome do arquivo de teste com uma extensão de arquivo .snapshot
. Esse comportamento pode ser configurado usando a função snapshot.setResolveSnapshotPath()
. Cada asserção de instantâneo corresponde a uma exportação no arquivo de instantâneo.
Um exemplo de teste de instantâneo é mostrado abaixo. Na primeira vez que este teste for executado, ele falhará porque o arquivo de instantâneo correspondente não existe.
// test.js
suite('suíte de testes de instantâneo', () => {
test('teste de instantâneo', t => {
t.assert.snapshot({ value1: 1, value2: 2 })
t.assert.snapshot(5)
})
})
Gere o arquivo de instantâneo executando o arquivo de teste com --test-update-snapshots
. O teste deve passar e um arquivo chamado test.js.snapshot
será criado no mesmo diretório que o arquivo de teste. O conteúdo do arquivo de instantâneo é mostrado abaixo. Cada instantâneo é identificado pelo nome completo do teste e um contador para diferenciar entre instantâneos no mesmo teste.
exports[`suíte de testes de instantâneo > teste de instantâneo 1`] = `
{
"value1": 1,
"value2": 2
}
`
exports[`suíte de testes de instantâneo > teste de instantâneo 2`] = `
5
`
Depois que o arquivo de instantâneo for criado, execute os testes novamente sem a flag --test-update-snapshots
. Os testes devem passar agora.
Relatórios de teste
[Histórico]
Versão | Alterações |
---|---|
v19.9.0, v18.17.0 | Os relatores agora são expostos em node:test/reporters . |
v19.6.0, v18.15.0 | Adicionado em: v19.6.0, v18.15.0 |
O módulo node:test
suporta a passagem de flags --test-reporter
para o executor de teste usar um relator específico.
Os seguintes relatores integrados são suportados:
spec
O relatorspec
produz os resultados do teste em um formato legível por humanos. Este é o relator padrão.tap
O relatortap
produz os resultados do teste no formato TAP.dot
O relatordot
produz os resultados do teste em um formato compacto, onde cada teste aprovado é representado por um.
, e cada teste falho é representado por umX
.junit
O relator junit produz os resultados do teste em um formato XML jUnitlcov
O relatorlcov
produz a cobertura de teste quando usado com a flag--experimental-test-coverage
.
A saída exata desses relatores está sujeita a alterações entre as versões do Node.js e não deve ser considerada programaticamente. Se o acesso programático à saída do executor de teste for necessário, use os eventos emitidos pelo <TestsStream>.
Os relatores estão disponíveis via 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')
Relatórios personalizados
--test-reporter
pode ser usado para especificar um caminho para um relator personalizado. Um relator personalizado é um módulo que exporta um valor aceito por stream.compose. Os relatores devem transformar eventos emitidos por um <TestsStream>
Exemplo de um relator personalizado usando <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
Exemplo de um relator personalizado usando uma função geradora:
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
}
}
}
}
O valor fornecido para --test-reporter
deve ser uma string como a usada em um import()
em código JavaScript, ou um valor fornecido para --import
.
Vários repórteres
A flag --test-reporter
pode ser especificada múltiplas vezes para relatar os resultados dos testes em vários formatos. Nesta situação, é necessário especificar um destino para cada repórter usando --test-reporter-destination
. O destino pode ser stdout
, stderr
ou um caminho de arquivo. Repórteres e destinos são emparelhados de acordo com a ordem em que foram especificados.
No exemplo a seguir, o repórter spec
terá saída para stdout
, e o repórter dot
terá saída para file.txt
:
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txt
Quando um único repórter é especificado, o destino será stdout
por padrão, a menos que um destino seja explicitamente fornecido.
run([options])
[Histórico]
Versão | Alterações |
---|---|
v23.0.0 | Adicionada a opção cwd . |
v23.0.0 | Adicionadas opções de cobertura. |
v22.8.0 | Adicionada a opção isolation . |
v22.6.0 | Adicionada a opção globPatterns . |
v22.0.0, v20.14.0 | Adicionada a opção forceExit . |
v20.1.0, v18.17.0 | Adicionada a opção testNamePatterns . |
v18.9.0, v16.19.0 | Adicionada em: v18.9.0, v16.19.0 |
options
<Object> Opções de configuração para execução de testes. As seguintes propriedades são suportadas:concurrency
<number> | <boolean> Se um número for fornecido, então tantos processos de teste serão executados em paralelo, onde cada processo corresponde a um arquivo de teste. Setrue
, ele executaráos.availableParallelism() - 1
arquivos de teste em paralelo. Sefalse
, ele executará apenas um arquivo de teste por vez. Padrão:false
.cwd
: <string> Especifica o diretório de trabalho atual a ser usado pelo executor de testes. Serve como o caminho base para resolver arquivos de acordo com o modelo de execução do executor de testes. Padrão:process.cwd()
.files
: <Array> Um array contendo a lista de arquivos a serem executados. Padrão: arquivos correspondentes do modelo de execução do executor de testes.forceExit
: <boolean> Configura o executor de testes para encerrar o processo assim que todos os testes conhecidos terminarem de executar, mesmo que o loop de eventos permaneça ativo. Padrão:false
.globPatterns
: <Array> Um array contendo a lista de padrões glob para corresponder aos arquivos de teste. Esta opção não pode ser usada em conjunto comfiles
. Padrão: arquivos correspondentes do modelo de execução do executor de testes.inspectPort
<number> | <Function> Define a porta do inspetor do processo filho de teste. Isso pode ser um número ou uma função que não aceita argumentos e retorna um número. Se um valor nulo for fornecido, cada processo recebe sua própria porta, incrementada a partir daprocess.debugPort
principal. Esta opção é ignorada se a opçãoisolation
estiver definida como'none'
, pois nenhum processo filho é gerado. Padrão:undefined
.isolation
<string> Configura o tipo de isolamento de teste. Se definido como'process'
, cada arquivo de teste é executado em um processo filho separado. Se definido como'none'
, todos os arquivos de teste são executados no processo atual. Padrão:'process'
.only
: <boolean> Se verdadeiro, o contexto do teste só executará testes que tenham a opçãoonly
definida.setup
<Function> Uma função que aceita a instânciaTestsStream
e pode ser usada para configurar ouvintes antes da execução de qualquer teste. Padrão:undefined
.execArgv
<Array> Um array de flags de CLI para passar ao executávelnode
ao gerar os subprocessos. Esta opção não tem efeito quandoisolation
é'none'
. Padrão:[]
argv
<Array> Um array de flags de CLI para passar a cada arquivo de teste ao gerar os subprocessos. Esta opção não tem efeito quandoisolation
é'none'
. Padrão:[]
.signal
<AbortSignal> Permite abortar uma execução de teste em andamento.testNamePatterns
<string> | <RegExp> | <Array> Uma String, RegExp ou um array RegExp, que pode ser usado para executar apenas testes cujo nome corresponda ao padrão fornecido. Os padrões de nome de teste são interpretados como expressões regulares JavaScript. Para cada teste que é executado, quaisquer ganchos de teste correspondentes, comobeforeEach()
, também são executados. Padrão:undefined
.testSkipPatterns
<string> | <RegExp> | <Array> Uma String, RegExp ou um array RegExp, que pode ser usado para excluir a execução de testes cujo nome corresponda ao padrão fornecido. Os padrões de nome de teste são interpretados como expressões regulares JavaScript. Para cada teste que é executado, quaisquer ganchos de teste correspondentes, comobeforeEach()
, também são executados. Padrão:undefined
.timeout
<number> Um número de milissegundos após o qual a execução do teste falhará. Se não especificado, os subtestes herdam esse valor de seu pai. Padrão:Infinity
.watch
<boolean> Se deve executar no modo de observação ou não. Padrão:false
.shard
<Object> Executando testes em um shard específico. Padrão:undefined
.index
<number> é um inteiro positivo entre 1 e\<total\>
que especifica o índice do shard a ser executado. Esta opção é obrigatória.total
<number> é um inteiro positivo que especifica o número total de shards para dividir os arquivos de teste. Esta opção é obrigatória.coverage
<boolean> habilita a coleta de cobertura de código. Padrão:false
.coverageExcludeGlobs
<string> | <Array> Exclui arquivos específicos da cobertura de código usando um padrão glob, que pode corresponder a caminhos de arquivos absolutos e relativos. Esta propriedade só é aplicável quandocoverage
foi definido comotrue
. Se amboscoverageExcludeGlobs
ecoverageIncludeGlobs
forem fornecidos, os arquivos devem atender a ambos os critérios para serem incluídos no relatório de cobertura. Padrão:undefined
.coverageIncludeGlobs
<string> | <Array> Inclui arquivos específicos na cobertura de código usando um padrão glob, que pode corresponder a caminhos de arquivos absolutos e relativos. Esta propriedade só é aplicável quandocoverage
foi definido comotrue
. Se amboscoverageExcludeGlobs
ecoverageIncludeGlobs
forem fornecidos, os arquivos devem atender a ambos os critérios para serem incluídos no relatório de cobertura. Padrão:undefined
.lineCoverage
<number> Requer uma porcentagem mínima de linhas cobertas. Se a cobertura de código não atingir o limite especificado, o processo sairá com o código1
. Padrão:0
.branchCoverage
<number> Requer uma porcentagem mínima de branches cobertos. Se a cobertura de código não atingir o limite especificado, o processo sairá com o código1
. Padrão:0
.functionCoverage
<number> Requer uma porcentagem mínima de funções cobertas. Se a cobertura de código não atingir o limite especificado, o processo sairá com o código1
. Padrão:0
.
Retorna: <TestsStream>
Nota: shard
é usado para paralelizar horizontalmente a execução de testes em máquinas ou processos, ideal para execuções em larga escala em ambientes variados. É incompatível com o modo watch
, adaptado para iteração rápida de código, reexecutando automaticamente os testes em alterações de arquivo.
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])
Adicionado em: v22.0.0, v20.13.0
name
<string> O nome da suíte, que é exibido ao relatar os resultados do teste. Padrão: A propriedadename
defn
, ou'\<anonymous\>'
sefn
não tiver um nome.options
<Object> Opções de configuração opcionais para a suíte. Isso suporta as mesmas opções quetest([name][, options][, fn])
.fn
<Function> | <AsyncFunction> A função da suíte declarando testes e suítes aninhados. O primeiro argumento para esta função é um objetoSuiteContext
. Padrão: Uma função sem operação.- Retorna: <Promise> Imediatamente cumprido com
undefined
.
A função suite()
é importada do módulo node:test
.
suite.skip([name][, options][, fn])
Adicionado em: v22.0.0, v20.13.0
Atalho para pular uma suíte. Isso é o mesmo que suite([name], { skip: true }[, fn])
.
suite.todo([name][, options][, fn])
Adicionado em: v22.0.0, v20.13.0
Atalho para marcar uma suíte como TODO
. Isso é o mesmo que suite([name], { todo: true }[, fn])
.
suite.only([name][, options][, fn])
Adicionado em: v22.0.0, v20.13.0
Atalho para marcar uma suíte como only
. Isso é o mesmo que suite([name], { only: true }[, fn])
.
test([name][, options][, fn])
[Histórico]
Versão | Alterações |
---|---|
v20.2.0, v18.17.0 | Adicionados os atalhos skip , todo e only . |
v18.8.0, v16.18.0 | Adicionada uma opção signal . |
v18.7.0, v16.17.0 | Adicionada uma opção timeout . |
v18.0.0, v16.17.0 | Adicionada em: v18.0.0, v16.17.0 |
name
<string> O nome do teste, que é exibido ao relatar os resultados do teste. Padrão: A propriedadename
defn
, ou'\<anonymous\>'
sefn
não tiver um nome.options
<Object> Opções de configuração para o teste. As seguintes propriedades são suportadas:concurrency
<number> | <boolean> Se um número for fornecido, então tantos testes serão executados em paralelo dentro da thread do aplicativo. Setrue
, todos os testes assíncronos agendados são executados simultaneamente na thread. Sefalse
, apenas um teste é executado por vez. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:false
.only
<boolean> Se verdadeiro, e o contexto do teste estiver configurado para executar testesonly
, então este teste será executado. Caso contrário, o teste é pulado. Padrão:false
.signal
<AbortSignal> Permite abortar um teste em andamento.skip
<boolean> | <string> Se verdadeiro, o teste é pulado. Se uma string for fornecida, essa string é exibida nos resultados do teste como o motivo para pular o teste. Padrão:false
.todo
<boolean> | <string> Se verdadeiro, o teste é marcado comoTODO
. Se uma string for fornecida, essa string é exibida nos resultados do teste como o motivo pelo qual o teste éTODO
. Padrão:false
.timeout
<number> Um número de milissegundos após o qual o teste falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.plan
<number> O número de asserções e subtestes esperados para serem executados no teste. Se o número de asserções executadas no teste não corresponder ao número especificado no plano, o teste falhará. Padrão:undefined
.
fn
<Function> | <AsyncFunction> A função em teste. O primeiro argumento para esta função é um objetoTestContext
. Se o teste usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função sem operação.Retorna: <Promise> Cumprido com
undefined
assim que o teste for concluído, ou imediatamente se o teste for executado dentro de uma suíte.
A função test()
é o valor importado do módulo test
. Cada invocação desta função resulta na notificação do teste para o <TestsStream>.
O objeto TestContext
passado para o argumento fn
pode ser usado para executar ações relacionadas ao teste atual. Exemplos incluem pular o teste, adicionar informações de diagnóstico adicionais ou criar subtestes.
test()
retorna uma Promise
que é cumprida assim que o teste é concluído. Se test()
for chamado dentro de uma suíte, ele é cumprido imediatamente. O valor de retorno geralmente pode ser descartado para testes de nível superior. No entanto, o valor de retorno dos subtestes deve ser usado para evitar que o teste pai termine primeiro e cancele o subteste, como mostrado no exemplo a seguir.
test('teste de nível superior', async t => {
// O setTimeout() no subteste a seguir faria com que ele sobrevivesse ao seu
// teste pai se 'await' for removido na próxima linha. Assim que o teste pai
// for concluído, ele cancelará quaisquer subtestes pendentes.
await t.test('subteste de execução mais longa', async t => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000)
})
})
})
A opção timeout
pode ser usada para falhar o teste se levar mais de timeout
milissegundos para ser concluído. No entanto, não é um mecanismo confiável para cancelar testes porque um teste em execução pode bloquear a thread do aplicativo e, portanto, impedir o cancelamento agendado.
test.skip([name][, options][, fn])
Forma abreviada para pular um teste, igual a test([name], { skip: true }[, fn])
.
test.todo([name][, options][, fn])
Forma abreviada para marcar um teste como TODO
, igual a test([name], { todo: true }[, fn])
.
test.only([name][, options][, fn])
Forma abreviada para marcar um teste como only
, igual a test([name], { only: true }[, fn])
.
describe([name][, options][, fn])
Alias para suite()
.
A função describe()
é importada do módulo node:test
.
describe.skip([name][, options][, fn])
Forma abreviada para pular uma suíte. Isto é o mesmo que describe([name], { skip: true }[, fn])
.
describe.todo([name][, options][, fn])
Forma abreviada para marcar uma suíte como TODO
. Isto é o mesmo que describe([name], { todo: true }[, fn])
.
describe.only([name][, options][, fn])
Adicionado em: v19.8.0, v18.15.0
Forma abreviada para marcar uma suíte como only
. Isto é o mesmo que describe([name], { only: true }[, fn])
.
it([name][, options][, fn])
[Histórico]
Versão | Alterações |
---|---|
v19.8.0, v18.16.0 | Chamar it() agora é equivalente a chamar test() . |
v18.6.0, v16.17.0 | Adicionada em: v18.6.0, v16.17.0 |
Alias para test()
.
A função it()
é importada do módulo node:test
.
it.skip([name][, options][, fn])
Forma abreviada para pular um teste, igual a it([name], { skip: true }[, fn])
.
it.todo([name][, options][, fn])
Forma abreviada para marcar um teste como TODO
, igual a it([name], { todo: true }[, fn])
.
it.only([name][, options][, fn])
Adicionado em: v19.8.0, v18.15.0
Forma abreviada para marcar um teste como only
, igual a it([name], { only: true }[, fn])
.
before([fn][, options])
Adicionado em: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> A função de hook. Se o hook usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o hook. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um hook em andamento.timeout
<number> Um número de milissegundos após o qual o hook falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função cria um hook que é executado antes da execução de uma suíte.
describe('tests', async () => {
before(() => console.log('about to run some test'))
it('is a subtest', () => {
assert.ok('some relevant assertion here')
})
})
after([fn][, options])
Adicionado em: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> A função de hook. Se o hook usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o hook. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um hook em andamento.timeout
<number> Um número de milissegundos após o qual o hook falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função cria um hook que é executado após a execução de uma suíte.
describe('tests', async () => {
after(() => console.log('finished running tests'))
it('is a subtest', () => {
assert.ok('some relevant assertion here')
})
})
Nota: O hook after
é garantido para ser executado, mesmo que os testes dentro da suíte falhem.
beforeEach([fn][, options])
Adicionado em: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> A função de gancho. Se o gancho usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o gancho. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um gancho em progresso.timeout
<number> Um número de milissegundos após o qual o gancho falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função cria um gancho que é executado antes de cada teste na suíte atual.
describe('tests', async () => {
beforeEach(() => console.log('sobre a executar um teste'))
it('is a subtest', () => {
assert.ok('alguma asserção relevante aqui')
})
})
afterEach([fn][, options])
Adicionado em: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> A função de gancho. Se o gancho usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o gancho. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um gancho em progresso.timeout
<number> Um número de milissegundos após o qual o gancho falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função cria um gancho que é executado após cada teste na suíte atual. O gancho afterEach()
é executado mesmo que o teste falhe.
describe('tests', async () => {
afterEach(() => console.log('terminou de executar um teste'))
it('is a subtest', () => {
assert.ok('alguma asserção relevante aqui')
})
})
snapshot
Adicionado em: v22.3.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
Um objeto cujos métodos são usados para configurar as configurações padrão de snapshot no processo atual. É possível aplicar a mesma configuração a todos os arquivos colocando o código de configuração comum em um módulo pré-carregado com --require
ou --import
.
snapshot.setDefaultSnapshotSerializers(serializers)
Adicionado em: v22.3.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
serializers
<Array> Uma matriz de funções síncronas usadas como serializadores padrão para testes de snapshot.
Esta função é usada para personalizar o mecanismo de serialização padrão usado pelo executor de testes. Por padrão, o executor de testes realiza a serialização chamando JSON.stringify(value, null, 2)
no valor fornecido. JSON.stringify()
tem limitações em relação a estruturas circulares e tipos de dados suportados. Se um mecanismo de serialização mais robusto for necessário, esta função deve ser usada.
snapshot.setResolveSnapshotPath(fn)
Adicionado em: v22.3.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
fn
<Function> Uma função usada para calcular a localização do arquivo de snapshot. A função recebe o caminho do arquivo de teste como seu único argumento. Se o teste não estiver associado a um arquivo (por exemplo, no REPL), a entrada é indefinida.fn()
deve retornar uma string especificando a localização do arquivo de snapshot.
Esta função é usada para personalizar a localização do arquivo de snapshot usado para testes de snapshot. Por padrão, o nome do arquivo de snapshot é o mesmo que o nome do arquivo de entrada com uma extensão de arquivo .snapshot
.
Classe: MockFunctionContext
Adicionado em: v19.1.0, v18.13.0
A classe MockFunctionContext
é usada para inspecionar ou manipular o comportamento de mocks criados via APIs MockTracker
.
ctx.calls
Adicionado em: v19.1.0, v18.13.0
Um getter que retorna uma cópia do array interno usado para rastrear chamadas para o mock. Cada entrada no array é um objeto com as seguintes propriedades.
arguments
<Array> Um array dos argumentos passados para a função mock.error
<any> Se a função mock lançou uma exceção, esta propriedade contém o valor lançado. Padrão:undefined
.result
<any> O valor retornado pela função mock.stack
<Error> Um objetoError
cujo stack pode ser usado para determinar o local da chamada da invocação da função mock.target
<Function> | <undefined> Se a função mock é um construtor, este campo contém a classe sendo construída. Caso contrário, seráundefined
.this
<any> O valorthis
da função mock.
ctx.callCount()
Adicionado em: v19.1.0, v18.13.0
- Retorna: <integer> O número de vezes que este mock foi invocado.
Esta função retorna o número de vezes que este mock foi invocado. Esta função é mais eficiente do que verificar ctx.calls.length
porque ctx.calls
é um getter que cria uma cópia do array interno de rastreamento de chamadas.
ctx.mockImplementation(implementation)
Adicionado em: v19.1.0, v18.13.0
implementation
<Function> | <AsyncFunction> A função a ser usada como nova implementação da simulação.
Esta função é usada para alterar o comportamento de uma simulação existente.
O exemplo a seguir cria uma função de simulação usando t.mock.fn()
, chama a função de simulação e, em seguida, altera a implementação da simulação para uma função diferente.
test('altera um comportamento de simulação', 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])
Adicionado em: v19.1.0, v18.13.0
implementation
<Function> | <AsyncFunction> A função a ser usada como implementação da simulação para o número de invocação especificado poronCall
.onCall
<integer> O número da invocação que usaráimplementation
. Se a invocação especificada já ocorreu, uma exceção é lançada. Padrão: O número da próxima invocação.
Esta função é usada para alterar o comportamento de uma simulação existente para uma única invocação. Assim que a invocação onCall
tiver ocorrido, a simulação retornará ao comportamento que teria usado se mockImplementationOnce()
não tivesse sido chamado.
O exemplo a seguir cria uma função de simulação usando t.mock.fn()
, chama a função de simulação, altera a implementação da simulação para uma função diferente para a próxima invocação e, em seguida, retorna ao seu comportamento anterior.
test('altera um comportamento de simulação uma 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()
Adicionado em: v19.3.0, v18.13.0
Reinicia o histórico de chamadas da função mock.
ctx.restore()
Adicionado em: v19.1.0, v18.13.0
Reinicia a implementação da função mock para o seu comportamento original. O mock ainda pode ser usado após a chamada desta função.
Classe: MockModuleContext
Adicionado em: v22.3.0, v20.18.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
A classe MockModuleContext
é usada para manipular o comportamento de mocks de módulos criados via APIs MockTracker
.
ctx.restore()
Adicionado em: v22.3.0, v20.18.0
Reinicia a implementação do módulo mock.
Classe: MockTracker
Adicionado em: v19.1.0, v18.13.0
A classe MockTracker
é usada para gerenciar a funcionalidade de mocking. O módulo do executor de teste fornece uma exportação de nível superior mock
, que é uma instância MockTracker
. Cada teste também fornece sua própria instância MockTracker
via propriedade mock
do contexto do teste.
mock.fn([original[, implementation]][, options])
Adicionado em: v19.1.0, v18.13.0
original
<Function> | <AsyncFunction> Uma função opcional para criar um mock. Padrão: Uma função sem operação.implementation
<Function> | <AsyncFunction> Uma função opcional usada como implementação mock paraoriginal
. Isso é útil para criar mocks que exibem um comportamento para um número especificado de chamadas e depois restauram o comportamento deoriginal
. Padrão: A função especificada pororiginal
.options
<Object> Opções de configuração opcionais para a função mock. As seguintes propriedades são suportadas:times
<integer> O número de vezes que o mock usará o comportamento deimplementation
. Assim que a função mock for chamadatimes
vezes, ela restaurará automaticamente o comportamento deoriginal
. Este valor deve ser um inteiro maior que zero. Padrão:Infinity
.
Retorna: <Proxy> A função mockada. A função mockada contém uma propriedade
mock
especial, que é uma instância deMockFunctionContext
, e pode ser usada para inspecionar e alterar o comportamento da função mockada.
Esta função é usada para criar uma função mock.
O exemplo a seguir cria uma função mock que incrementa um contador em um a cada invocação. A opção times
é usada para modificar o comportamento do mock de forma que as duas primeiras invocações adicionem dois ao contador em vez de um.
test('mocks a counting function', 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])
Adicionado em: v19.3.0, v18.13.0
Esta função é um atalho sintático para MockTracker.method
com options.getter
definido como true
.
mock.method(object, methodName[, implementation][, options])
Adicionado em: v19.1.0, v18.13.0
object
<Object> O objeto cujo método está sendo simulado.methodName
<string> | <symbol> O identificador do método emobject
a ser simulado. Seobject[methodName]
não for uma função, um erro será lançado.implementation
<Function> | <AsyncFunction> Uma função opcional usada como implementação simulada paraobject[methodName]
. Padrão: O método original especificado porobject[methodName]
.options
<Object> Opções de configuração opcionais para o método simulado. As seguintes propriedades são suportadas:getter
<boolean> Setrue
,object[methodName]
é tratado como um getter. Esta opção não pode ser usada com a opçãosetter
. Padrão: false.setter
<boolean> Setrue
,object[methodName]
é tratado como um setter. Esta opção não pode ser usada com a opçãogetter
. Padrão: false.times
<integer> O número de vezes que a simulação usará o comportamento deimplementation
. Uma vez que o método simulado tenha sido chamadotimes
vezes, ele restaurará automaticamente o comportamento original. Este valor deve ser um inteiro maior que zero. Padrão:Infinity
.
Retorna: <Proxy> O método simulado. O método simulado contém uma propriedade especial
mock
, que é uma instância deMockFunctionContext
, e pode ser usada para inspecionar e alterar o comportamento do método simulado.
Esta função é usada para criar uma simulação em um método de objeto existente. O exemplo a seguir demonstra como uma simulação é criada em um método de objeto existente.
test('espiona em um 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])
Adicionado em: v22.3.0, v20.18.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
specifier
<string> | <URL> Uma string identificando o módulo a ser simulado.options
<Object> Opções de configuração opcionais para o módulo simulado. As seguintes propriedades são suportadas:cache
<boolean> Sefalse
, cada chamada pararequire()
ouimport()
gera um novo módulo simulado. Setrue
, chamadas subsequentes retornarão o mesmo mock de módulo, e o módulo simulado é inserido no cache CommonJS. Padrão: false.defaultExport
<any> Um valor opcional usado como exportação padrão do módulo simulado. Se este valor não for fornecido, os mocks ESM não incluem uma exportação padrão. Se o mock for um módulo CommonJS ou embutido, esta configuração é usada como o valor demodule.exports
. Se este valor não for fornecido, os mocks CJS e embutidos usam um objeto vazio como o valor demodule.exports
.namedExports
<Object> Um objeto opcional cujas chaves e valores são usados para criar as exportações nomeadas do módulo simulado. Se o mock for um módulo CommonJS ou embutido, esses valores são copiados paramodule.exports
. Portanto, se um mock for criado com exportações nomeadas e uma exportação padrão não-objeto, o mock lançará uma exceção quando usado como um módulo CJS ou embutido.
Retorna: <MockModuleContext> Um objeto que pode ser usado para manipular o mock.
Esta função é usada para simular as exportações de módulos ECMAScript, módulos CommonJS e módulos embutidos do Node.js. Quaisquer referências ao módulo original antes da simulação não são afetadas. Para habilitar a simulação de módulos, o Node.js deve ser iniciado com a flag de linha de comando --experimental-test-module-mocks
.
O exemplo a seguir demonstra como um mock é criado para um módulo.
test('simula um módulo embutido em ambos os sistemas de módulos', async t => {
// Cria um mock de 'node:readline' com uma exportação nomeada chamada 'fn', que
// não existe no módulo 'node:readline' original.
const mock = t.mock.module('node:readline', {
namedExports: {
fn() {
return 42
},
},
})
let esmImpl = await import('node:readline')
let cjsImpl = require('node:readline')
// cursorTo() é uma exportação do módulo 'node:readline' original.
assert.strictEqual(esmImpl.cursorTo, undefined)
assert.strictEqual(cjsImpl.cursorTo, undefined)
assert.strictEqual(esmImpl.fn(), 42)
assert.strictEqual(cjsImpl.fn(), 42)
mock.restore()
// O mock é restaurado, então o módulo embutido original é retornado.
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()
Adicionado em: v19.1.0, v18.13.0
Esta função restaura o comportamento padrão de todas as mocks que foram previamente criadas por este MockTracker
e desassocia as mocks da instância MockTracker
. Uma vez desassociadas, as mocks ainda podem ser usadas, mas a instância MockTracker
não pode mais ser usada para redefinir seu comportamento ou interagir com elas de outra forma.
Após a conclusão de cada teste, esta função é chamada no MockTracker
do contexto do teste. Se o MockTracker
global for usado extensivamente, recomenda-se chamar esta função manualmente.
mock.restoreAll()
Adicionado em: v19.1.0, v18.13.0
Esta função restaura o comportamento padrão de todas as mocks que foram previamente criadas por este MockTracker
. Ao contrário de mock.reset()
, mock.restoreAll()
não desassocia as mocks da instância MockTracker
.
mock.setter(object, methodName[, implementation][, options])
Adicionado em: v19.3.0, v18.13.0
Esta função é açúcar sintático para MockTracker.method
com options.setter
definido como true
.
Classe: MockTimers
[Histórico]
Versão | Alterações |
---|---|
v23.1.0 | Os Mock Timers agora estão estáveis. |
v20.4.0, v18.19.0 | Adicionados em: v20.4.0, v18.19.0 |
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
Mockar timers é uma técnica comumente usada em testes de software para simular e controlar o comportamento de timers, como setInterval
e setTimeout
, sem realmente esperar pelos intervalos de tempo especificados.
MockTimers também é capaz de mockar o objeto Date
.
O MockTracker
fornece uma exportação timers
de nível superior que é uma instância MockTimers
.
timers.enable([enableOptions])
[Histórico]
Versão | Alterações |
---|---|
v21.2.0, v20.11.0 | Parâmetros atualizados para serem um objeto de opção com APIs disponíveis e a época inicial padrão. |
v20.4.0, v18.19.0 | Adicionados em: v20.4.0, v18.19.0 |
Habilita a simulação de timers para os timers especificados.
enableOptions
<Object> Opções de configuração opcionais para habilitar a simulação de timers. As seguintes propriedades são suportadas:apis
<Array> Um array opcional contendo os timers a serem simulados. Os valores de timer atualmente suportados são'setInterval'
,'setTimeout'
,'setImmediate'
e'Date'
. Padrão:['setInterval', 'setTimeout', 'setImmediate', 'Date']
. Se nenhum array for fornecido, todas as APIs relacionadas ao tempo ('setInterval'
,'clearInterval'
,'setTimeout'
,'clearTimeout'
,'setImmediate'
,'clearImmediate'
e'Date'
) serão simuladas por padrão.now
<number> | <Date> Um número ou objeto Date opcional representando o tempo inicial (em milissegundos) a ser usado como o valor paraDate.now()
. Padrão:0
.
Observação: Quando você habilita a simulação para um timer específico, sua função clear
associada também será simulada implicitamente.
Observação: Simular Date
afetará o comportamento dos timers simulados, pois eles usam o mesmo relógio interno.
Exemplo de uso sem definir o tempo inicial:
import { mock } from 'node:test'
mock.timers.enable({ apis: ['setInterval'] })
const { mock } = require('node:test')
mock.timers.enable({ apis: ['setInterval'] })
O exemplo acima habilita a simulação para o timer setInterval
e simula implicitamente a função clearInterval
. Somente as funções setInterval
e clearInterval
de node:timers, node:timers/promises e globalThis
serão simuladas.
Exemplo de uso com tempo inicial definido
import { mock } from 'node:test'
mock.timers.enable({ apis: ['Date'], now: 1000 })
const { mock } = require('node:test')
mock.timers.enable({ apis: ['Date'], now: 1000 })
Exemplo de uso com objeto Date inicial definido como tempo
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, se você chamar mock.timers.enable()
sem nenhum parâmetro:
Todos os timers ('setInterval'
, 'clearInterval'
, 'setTimeout'
, 'clearTimeout'
, 'setImmediate'
e 'clearImmediate'
) serão simulados. As funções setInterval
, clearInterval
, setTimeout
, clearTimeout
, setImmediate
e clearImmediate
de node:timers
, node:timers/promises
e globalThis
serão simuladas. Assim como o objeto global Date
.
timers.reset()
Adicionado em: v20.4.0, v18.19.0
Esta função restaura o comportamento padrão de todos os mocks que foram previamente criados por esta instância MockTimers
e desassocia os mocks da instância MockTracker
.
Nota: Após cada teste ser concluído, esta função é chamada no MockTracker
do contexto do teste.
import { mock } from 'node:test'
mock.timers.reset()
const { mock } = require('node:test')
mock.timers.reset()
timers[Symbol.dispose]()
Chama timers.reset()
.
timers.tick([milliseconds])
Adicionado em: v20.4.0, v18.19.0
Avança o tempo para todos os timers mockados.
milliseconds
<number> A quantidade de tempo, em milissegundos, para avançar os timers. Padrão:1
.
Nota: Isto diverge de como setTimeout
em Node.js se comporta e aceita apenas números positivos. Em Node.js, setTimeout
com números negativos é suportado apenas por razões de compatibilidade web.
O exemplo a seguir simula uma função setTimeout
e, usando .tick
, avança no tempo, acionando todos os timers pendentes.
import assert from 'node:assert'
import { test } from 'node:test'
test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
const fn = context.mock.fn()
context.mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(fn, 9999)
assert.strictEqual(fn.mock.callCount(), 0)
// Avançar no tempo
context.mock.timers.tick(9999)
assert.strictEqual(fn.mock.callCount(), 1)
})
const assert = require('node:assert')
const { test } = require('node:test')
test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
const fn = context.mock.fn()
context.mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(fn, 9999)
assert.strictEqual(fn.mock.callCount(), 0)
// Avançar no tempo
context.mock.timers.tick(9999)
assert.strictEqual(fn.mock.callCount(), 1)
})
Alternativamente, a função .tick
pode ser chamada várias vezes
import assert from 'node:assert'
import { test } from 'node:test'
test('mocks setTimeout to be executed synchronously without having to actually wait for it', 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('mocks setTimeout to be executed synchronously without having to actually wait for it', 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)
})
Avançar o tempo usando .tick
também avançará o tempo para qualquer objeto Date
criado após o mock ter sido ativado (se Date
também foi definido para ser mockado).
import assert from 'node:assert'
import { test } from 'node:test'
test('mocks setTimeout to be executed synchronously without having to actually wait for it', 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)
// Avançar no tempo
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('mocks setTimeout to be executed synchronously without having to actually wait for it', 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)
// Avançar no tempo
context.mock.timers.tick(9999)
assert.strictEqual(fn.mock.callCount(), 1)
assert.strictEqual(Date.now(), 9999)
})
Usando funções clear
Como mencionado, todas as funções clear de timers (clearTimeout
, clearInterval
e clearImmediate
) são implicitamente simuladas. Veja este exemplo usando setTimeout
:
import assert from 'node:assert'
import { test } from 'node:test'
test('simula setTimeout para ser executado sincronicamente sem precisar realmente esperar por ele', context => {
const fn = context.mock.fn()
// Opcionalmente escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout'] })
const id = setTimeout(fn, 9999)
// Implicitamente simulado também
clearTimeout(id)
context.mock.timers.tick(9999)
// Como esse setTimeout foi limpo, a função simulada nunca será chamada
assert.strictEqual(fn.mock.callCount(), 0)
})
const assert = require('node:assert')
const { test } = require('node:test')
test('simula setTimeout para ser executado sincronicamente sem precisar realmente esperar por ele', context => {
const fn = context.mock.fn()
// Opcionalmente escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout'] })
const id = setTimeout(fn, 9999)
// Implicitamente simulado também
clearTimeout(id)
context.mock.timers.tick(9999)
// Como esse setTimeout foi limpo, a função simulada nunca será chamada
assert.strictEqual(fn.mock.callCount(), 0)
})
Trabalhando com módulos de timers do Node.js
Assim que você habilitar a simulação de timers, os módulos node:timers, node:timers/promises e os timers do contexto global do Node.js são habilitados:
Nota: Funções de desestruturação como import { setTimeout } from 'node:timers'
atualmente não são suportadas por 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 ser executado sincronicamente sem precisar realmente esperar por ele', async context => {
const globalTimeoutObjectSpy = context.mock.fn()
const nodeTimerSpy = context.mock.fn()
const nodeTimerPromiseSpy = context.mock.fn()
// Opcionalmente escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(globalTimeoutObjectSpy, 9999)
nodeTimers.setTimeout(nodeTimerSpy, 9999)
const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy)
// Avançar no tempo
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 ser executado sincronicamente sem precisar realmente esperar por ele', async context => {
const globalTimeoutObjectSpy = context.mock.fn()
const nodeTimerSpy = context.mock.fn()
const nodeTimerPromiseSpy = context.mock.fn()
// Opcionalmente escolha o que simular
context.mock.timers.enable({ apis: ['setTimeout'] })
setTimeout(globalTimeoutObjectSpy, 9999)
nodeTimers.setTimeout(nodeTimerSpy, 9999)
const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy)
// Avançar no tempo
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)
})
No Node.js, setInterval
de node:timers/promises é um AsyncGenerator
e também é suportado por esta API:
import assert from 'node:assert'
import { test } from 'node:test'
import nodeTimersPromises from 'node:timers/promises'
test('deve marcar cinco vezes testando um 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('deve marcar cinco vezes testando um 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()
Adicionado em: v20.4.0, v18.19.0
Ativa todos os temporizadores simulados pendentes imediatamente. Se o objeto Date
também for simulado, ele também avançará o objeto Date
para o tempo do temporizador mais distante.
O exemplo abaixo aciona todos os temporizadores pendentes imediatamente, fazendo com que eles sejam executados sem nenhum atraso.
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: A função runAll()
é especificamente projetada para acionar temporizadores no contexto da simulação de temporizadores. Não tem nenhum efeito nos relógios do sistema em tempo real ou temporizadores reais fora do ambiente de simulação.
timers.setTime(milliseconds)
Adicionado em: v21.2.0, v20.11.0
Define o timestamp Unix atual que será usado como referência para quaisquer objetos Date
simulados.
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)
})
Datas e Temporizadores trabalhando juntos
Objetos de data e temporizador são dependentes um do outro. Se você usar setTime()
para passar o horário atual para o objeto Date
simulado, os temporizadores definidos com setTimeout
e setInterval
não serão afetados.
No entanto, o método tick
irá avançar o objeto Date
simulado.
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)
assert.deepStrictEqual(results, [])
context.mock.timers.setTime(12000)
assert.deepStrictEqual(results, [])
// The date is advanced but the timers don't tick
assert.strictEqual(Date.now(), 12000)
})
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)
assert.deepStrictEqual(results, [])
context.mock.timers.setTime(12000)
assert.deepStrictEqual(results, [])
// The date is advanced but the timers don't tick
assert.strictEqual(Date.now(), 12000)
})
Classe: TestsStream
[Histórico]
Versão | Alterações |
---|---|
v20.0.0, v19.9.0, v18.17.0 | adicionou tipo para eventos test:pass e test:fail quando o teste é uma suíte. |
v18.9.0, v16.19.0 | Adicionado em: v18.9.0, v16.19.0 |
- Extende <Readable>
Uma chamada bem-sucedida ao método run()
retornará um novo objeto <TestsStream>, transmitindo uma série de eventos que representam a execução dos testes. TestsStream
emitirá eventos, na ordem da definição dos testes.
Alguns eventos são garantidos para serem emitidos na mesma ordem em que os testes são definidos, enquanto outros são emitidos na ordem em que os testes são executados.
Evento: 'test:coverage'
data
<Objeto>summary
<Objeto> Um objeto contendo o relatório de cobertura.files
<Array> Um array de relatórios de cobertura para arquivos individuais. Cada relatório é um objeto com o seguinte esquema:path
<string> O caminho absoluto do arquivo.totalLineCount
<number> O número total de linhas.totalBranchCount
<number> O número total de branches.totalFunctionCount
<number> O número total de funções.coveredLineCount
<number> O número de linhas cobertas.coveredBranchCount
<number> O número de branches cobertos.coveredFunctionCount
<number> O número de funções cobertas.coveredLinePercent
<number> A porcentagem de linhas cobertas.coveredBranchPercent
<number> A porcentagem de branches cobertos.coveredFunctionPercent
<number> A porcentagem de funções cobertas.functions
<Array> Um array de funções representando a cobertura da função.name
<string> O nome da função.line
<number> O número da linha onde a função é definida.count
<number> O número de vezes que a função foi chamada.branches
<Array> Um array de branches representando a cobertura de branches.line
<number> O número da linha onde o branch é definido.count
<number> O número de vezes que o branch foi tomado.lines
<Array> Um array de linhas representando os números das linhas e o número de vezes que elas foram cobertas.line
<number> O número da linha.count
<number> O número de vezes que a linha foi coberta.thresholds
<Objeto> Um objeto contendo se a cobertura para cada tipo de cobertura atingiu ou não o limite.function
<number> O limite de cobertura da função.branch
<number> O limite de cobertura do branch.line
<number> O limite de cobertura da linha.totals
<Objeto> Um objeto contendo um resumo da cobertura para todos os arquivos.totalLineCount
<number> O número total de linhas.totalBranchCount
<number> O número total de branches.totalFunctionCount
<number> O número total de funções.coveredLineCount
<number> O número de linhas cobertas.coveredBranchCount
<number> O número de branches cobertos.coveredFunctionCount
<number> O número de funções cobertas.coveredLinePercent
<number> A porcentagem de linhas cobertas.coveredBranchPercent
<number> A porcentagem de branches cobertos.coveredFunctionPercent
<number> A porcentagem de funções cobertas.workingDirectory
<string> O diretório de trabalho quando a cobertura de código começou. Isso é útil para exibir nomes de caminhos relativos caso os testes alterem o diretório de trabalho do processo Node.js.nesting
<number> O nível de aninhamento do teste.
Emitido quando a cobertura de código está habilitada e todos os testes foram concluídos.
Evento: 'test:complete'
data
<Objeto>column
<número> | <indefinido> O número da coluna onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.details
<Objeto> Metadados de execução adicionais.passed
<booleano> Se o teste passou ou não.duration_ms
<número> A duração do teste em milissegundos.error
<Erro> | <indefinido> Um erro encapsulando o erro lançado pelo teste se ele não passou.cause
<Erro> O erro real lançado pelo teste.type
<string> | <indefinido> O tipo do teste, usado para indicar se este é uma suíte.file
<string> | <indefinido> O caminho do arquivo de teste,indefinido
se o teste foi executado através do REPL.line
<número> | <indefinido> O número da linha onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.name
<string> O nome do teste.nesting
<número> O nível de aninhamento do teste.testNumber
<número> O número ordinal do teste.todo
<string> | <booleano> | <indefinido> Presente secontext.todo
for chamado.skip
<string> | <booleano> | <indefinido> Presente secontext.skip
for chamado.
Emitido quando um teste completa sua execução. Este evento não é emitido na mesma ordem em que os testes são definidos. Os eventos correspondentes ordenados por declaração são 'test:pass'
e 'test:fail'
.
Evento: 'test:dequeue'
data
<Object>column
<number> | <undefined> O número da coluna onde o teste está definido, ouundefined
se o teste foi executado através do REPL.file
<string> | <undefined> O caminho do arquivo de teste,undefined
se o teste foi executado através do REPL.line
<number> | <undefined> O número da linha onde o teste está definido, ouundefined
se o teste foi executado através do REPL.name
<string> O nome do teste.nesting
<number> O nível de aninhamento do teste.
Emitido quando um teste é retirado da fila, imediatamente antes de ser executado. Não é garantido que este evento seja emitido na mesma ordem em que os testes são definidos. O evento correspondente ordenado por declaração é 'test:start'
.
Evento: 'test:diagnostic'
data
<Object>column
<number> | <undefined> O número da coluna onde o teste está definido, ouundefined
se o teste foi executado através do REPL.file
<string> | <undefined> O caminho do arquivo de teste,undefined
se o teste foi executado através do REPL.line
<number> | <undefined> O número da linha onde o teste está definido, ouundefined
se o teste foi executado através do REPL.message
<string> A mensagem de diagnóstico.nesting
<number> O nível de aninhamento do teste.
Emitido quando context.diagnostic
é chamado. Este evento é garantido que seja emitido na mesma ordem em que os testes são definidos.
Evento: 'test:enqueue'
data
<Object>column
<number> | <undefined> O número da coluna onde o teste está definido, ouundefined
se o teste foi executado através do REPL.file
<string> | <undefined> O caminho do arquivo de teste,undefined
se o teste foi executado através do REPL.line
<number> | <undefined> O número da linha onde o teste está definido, ouundefined
se o teste foi executado através do REPL.name
<string> O nome do teste.nesting
<number> O nível de aninhamento do teste.
Emitido quando um teste é colocado na fila para execução.
Evento: 'test:fail'
data
<Object>column
<number> | <undefined> O número da coluna onde o teste está definido, ouundefined
se o teste foi executado através do REPL.details
<Object> Metadados de execução adicionais.duration_ms
<number> A duração do teste em milissegundos.error
<Error> Um erro envolvendo o erro lançado pelo teste.cause
<Error> O erro real lançado pelo teste.type
<string> | <undefined> O tipo do teste, usado para indicar se este é uma suíte.file
<string> | <undefined> O caminho do arquivo de teste,undefined
se o teste foi executado através do REPL.line
<number> | <undefined> O número da linha onde o teste está definido, ouundefined
se o teste foi executado através do REPL.name
<string> O nome do teste.nesting
<number> O nível de aninhamento do teste.testNumber
<number> O número ordinal do teste.todo
<string> | <boolean> | <undefined> Presente secontext.todo
for chamadoskip
<string> | <boolean> | <undefined> Presente secontext.skip
for chamado
Emitido quando um teste falha. Este evento é garantido para ser emitido na mesma ordem que os testes são definidos. O evento correspondente ordenado pela execução é 'test:complete'
.
Evento: 'test:pass'
data
<Objeto>column
<número> | <indefinido> O número da coluna onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.details
<Objeto> Metadados de execução adicionais.duration_ms
<número> A duração do teste em milissegundos.type
<string> | <indefinido> O tipo do teste, usado para indicar se este é uma suíte.file
<string> | <indefinido> O caminho do arquivo de teste,indefinido
se o teste foi executado através do REPL.line
<número> | <indefinido> O número da linha onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.name
<string> O nome do teste.nesting
<número> O nível de aninhamento do teste.testNumber
<número> O número ordinal do teste.todo
<string> | <booleano> | <indefinido> Presente secontext.todo
for chamadoskip
<string> | <booleano> | <indefinido> Presente secontext.skip
for chamado
Emitido quando um teste é aprovado. Este evento é garantido para ser emitido na mesma ordem em que os testes são definidos. O evento correspondente ordenado pela execução é 'test:complete'
.
Evento: 'test:plan'
data
<Objeto>column
<número> | <indefinido> O número da coluna onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.file
<string> | <indefinido> O caminho do arquivo de teste,indefinido
se o teste foi executado através do REPL.line
<número> | <indefinido> O número da linha onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.nesting
<número> O nível de aninhamento do teste.count
<número> O número de subtestes que foram executados.
Emitido quando todos os subtestes são concluídos para um determinado teste. Este evento é garantido para ser emitido na mesma ordem em que os testes são definidos.
Evento: 'test:start'
data
<Objeto>column
<número> | <indefinido> O número da coluna onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.file
<string> | <indefinido> O caminho do arquivo de teste,indefinido
se o teste foi executado através do REPL.line
<número> | <indefinido> O número da linha onde o teste é definido, ouindefinido
se o teste foi executado através do REPL.name
<string> O nome do teste.nesting
<número> O nível de aninhamento do teste.
Emitido quando um teste inicia o reporte de seu próprio status e o status de seus subtestes. Este evento é garantido para ser emitido na mesma ordem em que os testes são definidos. O evento correspondente ordenado por execução é 'test:dequeue'
.
Evento: 'test:stderr'
data
<Objeto>
Emitido quando um teste em execução escreve para stderr
. Este evento só é emitido se a flag --test
for passada. Não é garantido que este evento seja emitido na mesma ordem em que os testes são definidos.
Evento: 'test:stdout'
data
<Objeto>
Emitido quando um teste em execução escreve para stdout
. Este evento só é emitido se a flag --test
for passada. Não é garantido que este evento seja emitido na mesma ordem em que os testes são definidos.
Evento: 'test:summary'
data
<Objeto>counts
<Objeto> Um objeto contendo as contagens de vários resultados de teste.cancelled
<number> O número total de testes cancelados.failed
<number> O número total de testes falhos.passed
<number> O número total de testes aprovados.skipped
<number> O número total de testes ignorados.suites
<number> O número total de suítes executadas.tests
<number> O número total de testes executados, excluindo suítes.todo
<number> O número total de testes TODO.topLevel
<number> O número total de testes e suítes de nível superior.duration_ms
<number> A duração da execução do teste em milissegundos.file
<string> | <undefined> O caminho do arquivo de teste que gerou o resumo. Se o resumo corresponder a vários arquivos, este valor seráundefined
.success
<boolean> Indica se a execução do teste é considerada bem-sucedida ou não. Se alguma condição de erro ocorrer, como um teste falho ou um limite de cobertura não atendido, este valor será definido comofalse
.
Emitido quando uma execução de teste é concluída. Este evento contém métricas relativas à execução de teste concluída e é útil para determinar se uma execução de teste foi aprovada ou reprovada. Se o isolamento de teste em nível de processo for usado, um evento 'test:summary'
é gerado para cada arquivo de teste, além de um resumo cumulativo final.
Evento: 'test:watch:drained'
Emitido quando não há mais testes na fila de execução no modo de observação.
Classe: TestContext
[Histórico]
Versão | Alterações |
---|---|
v20.1.0, v18.17.0 | A função before foi adicionada ao TestContext. |
v18.0.0, v16.17.0 | Adicionada em: v18.0.0, v16.17.0 |
Uma instância de TestContext
é passada para cada função de teste para interagir com o executor de teste. No entanto, o construtor TestContext
não é exposto como parte da API.
context.before([fn][, options])
Adicionado em: v20.1.0, v18.17.0
fn
<Function> | <AsyncFunction> A função de gancho. O primeiro argumento desta função é um objetoTestContext
. Se o gancho usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o gancho. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um gancho em andamento.timeout
<number> Um número de milissegundos após o qual o gancho falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função é usada para criar um gancho que é executado antes do subteste do teste atual.
context.beforeEach([fn][, options])
Adicionado em: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> A função de gancho. O primeiro argumento desta função é um objetoTestContext
. Se o gancho usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o gancho. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um gancho em andamento.timeout
<number> Um número de milissegundos após o qual o gancho falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função é usada para criar um gancho que é executado antes de cada subteste do teste atual.
test('teste de nível superior', async t => {
t.beforeEach(t => t.diagnostic(`prestes a executar ${t.name}`))
await t.test('Este é um subteste', t => {
assert.ok('alguma afirmação relevante aqui')
})
})
context.after([fn][, options])
Adicionado em: v19.3.0, v18.13.0
fn
<Function> | <AsyncFunction> A função de gancho. O primeiro argumento para esta função é um objetoTestContext
. Se o gancho usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o gancho. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um gancho em progresso.timeout
<number> Um número de milissegundos após o qual o gancho falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função é usada para criar um gancho que é executado após o término do teste atual.
test('teste de nível superior', async t => {
t.after(t => t.diagnostic(`terminou de executar ${t.name}`))
assert.ok('alguma asserção relevante aqui')
})
context.afterEach([fn][, options])
Adicionado em: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> A função de gancho. O primeiro argumento para esta função é um objetoTestContext
. Se o gancho usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função no-op.options
<Object> Opções de configuração para o gancho. As seguintes propriedades são suportadas:signal
<AbortSignal> Permite abortar um gancho em progresso.timeout
<number> Um número de milissegundos após o qual o gancho falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.
Esta função é usada para criar um gancho que é executado após cada subteste do teste atual.
test('teste de nível superior', async t => {
t.afterEach(t => t.diagnostic(`terminou de executar ${t.name}`))
await t.test('Este é um subteste', t => {
assert.ok('alguma asserção relevante aqui')
})
})
context.assert
Adicionado em: v22.2.0, v20.15.0
Um objeto contendo métodos de asserção vinculados a context
. As funções de nível superior do módulo node:assert
são expostas aqui para a finalidade de criar planos de teste.
test('test', t => {
t.plan(1)
t.assert.strictEqual(true, true)
})
context.assert.snapshot(value[, options])
Adicionado em: v22.3.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.0 - Desenvolvimento inicial
value
<any> Um valor para serializar em uma string. Se o Node.js foi iniciado com a flag--test-update-snapshots
, o valor serializado é escrito no arquivo de snapshot. Caso contrário, o valor serializado é comparado ao valor correspondente no arquivo de snapshot existente.options
<Object> Opções de configuração opcionais. As seguintes propriedades são suportadas:serializers
<Array> Uma matriz de funções síncronas usadas para serializarvalue
em uma string.value
é passado como o único argumento para a primeira função serializadora. O valor retornado de cada serializador é passado como entrada para o próximo serializador. Depois que todos os serializadores foram executados, o valor resultante é convertido em uma string. Padrão: Se nenhum serializador for fornecido, os serializadores padrão do testador são usados.
Esta função implementa asserções para testes de snapshot.
test('snapshot test with default serialization', t => {
t.assert.snapshot({ value1: 1, value2: 2 })
})
test('snapshot test with custom serialization', t => {
t.assert.snapshot(
{ value3: 3, value4: 4 },
{
serializers: [value => JSON.stringify(value)],
}
)
})
context.diagnostic(message)
Adicionado em: v18.0.0, v16.17.0
message
<string> Mensagem a ser relatada.
Esta função é usada para escrever diagnósticos na saída. Qualquer informação de diagnóstico é incluída no final dos resultados do teste. Esta função não retorna nenhum valor.
test('top level test', t => {
t.diagnostic('Uma mensagem de diagnóstico')
})
context.filePath
Adicionado em: v22.6.0, v20.16.0
O caminho absoluto do arquivo de teste que criou o teste atual. Se um arquivo de teste importar módulos adicionais que geram testes, os testes importados retornarão o caminho do arquivo de teste raiz.
context.fullName
Adicionado em: v22.3.0
O nome do teste e de cada um de seus ancestrais, separados por \>
.
context.name
Adicionado em: v18.8.0, v16.18.0
O nome do teste.
context.plan(count)
[Histórico]
Versão | Alterações |
---|---|
v23.4.0 | Esta função não é mais experimental. |
v22.2.0, v20.15.0 | Adicionada em: v22.2.0, v20.15.0 |
count
<number> O número de asserções e subtestes que se espera que sejam executados.
Esta função é usada para definir o número de asserções e subtestes que se espera que sejam executados dentro do teste. Se o número de asserções e subtestes executados não corresponder à contagem esperada, o teste falhará.
test('top level test', t => {
t.plan(2)
t.assert.ok('alguma asserção relevante aqui')
t.test('subteste', () => {})
})
Ao trabalhar com código assíncrono, a função plan
pode ser usada para garantir que o número correto de asserções seja executado:
test('planejamento com streams', (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)
Adicionado em: v18.0.0, v16.17.0
shouldRunOnlyTests
<boolean> Se deve ou não executar testesonly
.
Se shouldRunOnlyTests
for verdadeiro, o contexto do teste só executará os testes que tiverem a opção only
definida. Caso contrário, todos os testes serão executados. Se o Node.js não foi iniciado com a opção de linha de comando --test-only
, esta função é uma operação sem efeito.
test('teste de nível superior', t => {
// O contexto do teste pode ser definido para executar subtestes com a opção 'only'.
t.runOnly(true)
return Promise.all([t.test('este subteste agora está ignorado'), t.test('este subteste é executado', { only: true })])
})
context.signal
Adicionado em: v18.7.0, v16.17.0
- Tipo: <AbortSignal>
Pode ser usado para interromper subtarefas de teste quando o teste foi interrompido.
test('teste de nível superior', async t => {
await fetch('some/uri', { signal: t.signal })
})
context.skip([message])
Adicionado em: v18.0.0, v16.17.0
message
<string> Mensagem de ignorância opcional.
Esta função faz com que a saída do teste indique o teste como ignorado. Se message
for fornecido, ele será incluído na saída. Chamar skip()
não encerra a execução da função de teste. Esta função não retorna nenhum valor.
test('teste de nível superior', t => {
// Certifique-se de retornar aqui também se o teste contiver lógica adicional.
t.skip('isto está ignorado')
})
context.todo([message])
Adicionado em: v18.0.0, v16.17.0
message
<string> MensagemTODO
opcional.
Esta função adiciona uma diretiva TODO
à saída do teste. Se message
for fornecido, ele será incluído na saída. Chamar todo()
não encerra a execução da função de teste. Esta função não retorna nenhum valor.
test('teste de nível superior', t => {
// Este teste está marcado como `TODO`
t.todo('isto é um TODO')
})
context.test([name][, options][, fn])
[Histórico]
Versão | Alterações |
---|---|
v18.8.0, v16.18.0 | Adiciona uma opção signal . |
v18.7.0, v16.17.0 | Adiciona uma opção timeout . |
v18.0.0, v16.17.0 | Adicionado em: v18.0.0, v16.17.0 |
name
<string> O nome do subteste, que é exibido ao relatar os resultados do teste. Padrão: A propriedadename
defn
, ou'\<anônimo\>'
sefn
não tiver um nome.options
<Object> Opções de configuração para o subteste. As seguintes propriedades são suportadas:concurrency
<number> | <boolean> | <null> Se um número for fornecido, então tantos testes serão executados em paralelo dentro da thread do aplicativo. Setrue
, ele executará todos os subtestes em paralelo. Sefalse
, ele executará apenas um teste por vez. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:null
.only
<boolean> Se verdadeiro, e o contexto do teste estiver configurado para executar testesonly
, então este teste será executado. Caso contrário, o teste será ignorado. Padrão:false
.signal
<AbortSignal> Permite interromper um teste em andamento.skip
<boolean> | <string> Se verdadeiro, o teste é ignorado. Se uma string for fornecida, essa string será exibida nos resultados do teste como o motivo para ignorar o teste. Padrão:false
.todo
<boolean> | <string> Se verdadeiro, o teste é marcado comoTODO
. Se uma string for fornecida, essa string será exibida nos resultados do teste como o motivo pelo qual o teste éTODO
. Padrão:false
.timeout
<number> Um número de milissegundos após o qual o teste falhará. Se não especificado, os subtestes herdam este valor de seu pai. Padrão:Infinity
.plan
<number> O número de asserções e subtestes esperados para serem executados no teste. Se o número de asserções executadas no teste não corresponder ao número especificado no plano, o teste falhará. Padrão:undefined
.
fn
<Function> | <AsyncFunction> A função em teste. O primeiro argumento desta função é um objetoTestContext
. Se o teste usar callbacks, a função de callback é passada como o segundo argumento. Padrão: Uma função sem operação.Retorna: <Promise> Resolvido com
undefined
assim que o teste for concluído.
Esta função é usada para criar subtestes no teste atual. Esta função se comporta da mesma maneira que a função de nível superior test()
.
test('teste de nível superior', async t => {
await t.test('Este é um subteste', { only: false, skip: false, concurrency: 1, todo: false, plan: 1 }, t => {
t.assert.ok('alguma asserção relevante aqui')
})
})
Classe: SuiteContext
Adicionado em: v18.7.0, v16.17.0
Uma instância de SuiteContext
é passada para cada função de suíte para interagir com o executor de testes. No entanto, o construtor SuiteContext
não é exposto como parte da API.
context.filePath
Adicionado em: v22.6.0
O caminho absoluto do arquivo de teste que criou a suíte atual. Se um arquivo de teste importar módulos adicionais que geram suítes, as suítes importadas retornarão o caminho do arquivo de teste raiz.
context.name
Adicionado em: v18.8.0, v16.18.0
O nome da suíte.
context.signal
Adicionado em: v18.7.0, v16.17.0
- Tipo: <AbortSignal>
Pode ser usado para interromper subtarefas de teste quando o teste foi abortado.