Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Node Test Runner: testes nativos no Node.js

Atualizado em: 12 de outubro de 2026

Terminal Linux usado em desenvolvimento e administração de aplicações Node.js

Node Test Runner no Node.js é o executor de testes nativo acessado pelo módulo node:test e pelo comando node --test. Ele permite criar testes unitários e de integração sem instalar um framework externo.

O runner fornece testes assíncronos, hooks, subtests, mocks, filtragem, paralelismo e relatórios. A vantagem principal é reduzir dependências e usar uma ferramenta que acompanha o runtime.

Neste guia, você aprenderá estrutura de testes, assertions, hooks, concorrência, timeouts, mocks, cobertura, CI e boas práticas.

Primeiro teste

import test from 'node:test';
import assert from 'node:assert/strict';
import { somar } from '../src/math.js';

test('soma dois números', () => {
  assert.equal(somar(2, 3), 5);
});

Execute:

node --test

Organização de arquivos

src/
  math.js
test/
  math.test.js

Use nomes previsíveis e mantenha testes próximos do domínio ou em uma pasta dedicada conforme o tamanho do projeto.

Testes assíncronos

test('busca usuário', async () => {
  const user = await service.buscar('123');
  assert.equal(user.id, '123');
});

Retorne ou aguarde a Promise. Não finalize o teste antes da operação assíncrona.

Rejeições

await assert.rejects(
  () => service.buscar('inexistente'),
  { code: 'USER_NOT_FOUND' }
);

Teste códigos estáveis em vez de depender apenas de mensagens.

Suites com describe

import { describe, it } from 'node:test';

describe('calculadora', () => {
  it('soma', () => {
    assert.equal(somar(1, 2), 3);
  });
});

Hooks

import { before, after, beforeEach } from 'node:test';

before(async () => {
  await database.start();
});

after(async () => {
  await database.stop();
});

beforeEach(async () => {
  await database.reset();
});

Hooks devem ser rápidos e sempre liberar recursos.

Subtests

test('validação', async (t) => {
  await t.test('rejeita email vazio', () => {
    assert.throws(() => validarEmail(''));
  });

  await t.test('aceita email válido', () => {
    assert.doesNotThrow(() => validarEmail('a@b.com'));
  });
});

Timeouts

test('responde rápido', { timeout: 2000 }, async () => {
  await executarOperacao();
});

Timeout não substitui cancelamento real. Recursos externos devem receber AbortSignal ou possuir encerramento explícito.

Testes concorrentes

Concorrência acelera suítes, mas testes que compartilham banco, arquivos ou portas podem interferir entre si. Use dados e recursos isolados.

Filtrando testes

node --test --test-name-pattern="usuário"

Filtros ajudam no desenvolvimento, mas CI deve executar a suíte completa.

Only e skip

Testes podem ser pulados ou marcados para execução exclusiva. Configure revisão ou CI para impedir que um only acidental reduza a suíte publicada.

Testes parametrizados

for (const [input, expected] of [
  [1, 2],
  [2, 4],
  [5, 10]
]) {
  test(`dobra ${input}`, () => {
    assert.equal(dobrar(input), expected);
  });
}

Mocks

O contexto de teste oferece ferramentas de mock:

test('registra evento', (t) => {
  const logger = { info() {} };
  const spy = t.mock.method(logger, 'info');

  executar(logger);
  assert.equal(spy.mock.callCount(), 1);
});

Veja o artigo dedicado sobre Mocking no Node.js.

Injeção de dependência

Não tente substituir qualquer import global. Passe repositórios, relógios e clientes por parâmetro. Isso reduz acoplamento e simplifica testes.

Teste de servidor

Crie a aplicação sem abrir porta automaticamente. O teste pode iniciar em porta aleatória e encerrar no hook.

const server = app.listen(0);
await once(server, 'listening');
// chamadas HTTP
server.close();

Banco de dados

Testes unitários não precisam de banco real. Testes de integração devem usar instância isolada, migrações e limpeza determinística.

Cobertura

O runtime pode gerar cobertura ao executar a suíte. Use métricas como apoio, não como substituto de cenários relevantes.

CI

npm ci
node --test

Use lockfile conforme Lockfile no Node.js e divida suítes grandes com Test Sharding no Node.js.

Testes frágeis

Evite depender de tempo real, rede externa, ordem, locale ou caminhos globais. Injete relógio, use fixtures pequenas e controle o ambiente.

Erros comuns

  • esquecer await;
  • compartilhar estado entre testes;
  • abrir recursos sem fechar;
  • usar sleep para sincronização;
  • testar implementação interna;
  • executar rede externa;
  • deixar only no código;
  • usar cobertura como meta única.

Checklist

  • nomes descritivos;
  • assertions estritas;
  • recursos encerrados;
  • dados isolados;
  • timeouts razoáveis;
  • erros negativos testados;
  • execução local igual ao CI;
  • sem dependência de ordem;
  • suíte rápida.

Conclusão

Node Test Runner no Node.js oferece uma base completa para testar aplicações sem dependência adicional. Ele funciona especialmente bem em projetos que valorizam APIs nativas e configuração simples.

Estruture o código para receber dependências, isole recursos externos e mantenha a suíte determinística. A qualidade dos testes depende mais do desenho da aplicação do que da quantidade de ferramentas.

Consulte a documentação oficial do test runner do Node.js e a documentação do módulo assert.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita