Introdução aos Frameworks de Teste em JavaScript
Testes automatizados são a base de software confiável e manutenível. Em JavaScript, você tem três ferramentas principais: Jest (robusto e completo), Vitest (moderno e rápido), e Testing Library (focado em comportamento do usuário). Cada uma resolve problemas específicos, e dominá-las é essencial para qualquer desenvolvedor profissional.
A escolha entre elas depende do seu contexto. Jest é ideal para projetos estabelecidos; Vitest excele em aplicações Vite modernas; Testing Library complementa ambos quando você precisa testar interfaces de usuário. Neste artigo, você aprenderá configuração, padrões práticos e como usá-las em conjunto.
Jest: A Base Sólida
Configuração e Setup
Jest é o framework de testes mais usado em JavaScript. Sua configuração é mínima graças aos padrões inteligentes. Instale com npm install --save-dev jest e crie um arquivo jest.config.js:
module.exports = {
testEnvironment: 'node',
collectCoverageFrom: ['src/**/*.js'],
coveragePathIgnorePatterns: ['/node_modules/'],
testMatch: ['**/__tests__/**/*.test.js']
};
Escrevendo Testes Básicos
Vamos testar uma função simples de cálculo. Crie src/calculator.js:
function soma(a, b) {
return a + b;
}
function multiplicacao(a, b) {
return a * b;
}
module.exports = { soma, multiplicacao };
Agora src/__tests__/calculator.test.js:
const { soma, multiplicacao } = require('../calculator');
describe('Calculator', () => {
it('deve somar dois números corretamente', () => {
expect(soma(2, 3)).toBe(5);
});
it('deve multiplicar dois números corretamente', () => {
expect(multiplicacao(4, 5)).toBe(20);
});
it('deve retornar 0 para soma com valores negativos', () => {
expect(soma(-5, 5)).toBe(0);
});
});
Execute com npm test. Jest fornece assertions claras (toBe, toEqual, toMatch), setup/teardown com beforeEach e afterEach, e relatórios de cobertura automaticamente. Para testes mais avançados, use mocks: jest.fn() para funções e jest.mock() para módulos inteiros.
Vitest: Performance e Modernidade
Por Que Vitest?
Vitest é construído sobre Vite e oferece reload instantâneo (HMR) e execução paralela nativa. É perfeito se você já usa Vite. A API é compatível com Jest, facilitando a migração.
Primeiros Passos
Instale: npm install --save-dev vitest. Crie vitest.config.js:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'node',
coverage: {
provider: 'v8'
}
}
});
Teste o mesmo calculator com Vitest em src/__tests__/calculator.vitest.js:
import { describe, it, expect } from 'vitest';
import { soma, multiplicacao } from '../calculator';
describe('Calculator com Vitest', () => {
it('soma dois números', () => {
expect(soma(10, 20)).toBe(30);
});
it('trata erros de entrada', () => {
expect(() => soma(null, 5)).toBeDefined();
});
});
Execute com npm run test -- vitest. A diferença prática: Vitest reconstrói testes modificados em milissegundos, não segundos. Para projetos grandes, isso muda a experiência de desenvolvimento significativamente.
Testing Library: Testando Como Usuários
Filosofia de Teste
Testing Library não testa implementação, testa comportamento. Você evita selecionar por className ou data-testid desnecessários, focando em como usuários realmente interagem: clicam em botões, preenchem campos, leem texto.
Testando Componentes React
Instale: npm install --save-dev @testing-library/react @testing-library/jest-dom. Crie um componente simples src/components/LoginForm.jsx:
import { useState } from 'react';
export function LoginForm({ onSubmit }) {
const [email, setEmail] = useState('');
return (
<form onSubmit={(e) => {
e.preventDefault();
onSubmit(email);
}}>
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">Entrar</button>
</form>
);
}
Teste com src/__tests__/LoginForm.test.jsx:
import { render, screen, fireEvent } from '@testing-library/react';
import { LoginForm } from '../components/LoginForm';
describe('LoginForm', () => {
it('chama onSubmit quando formulário é enviado', () => {
const handleSubmit = jest.fn();
render(<LoginForm onSubmit={handleSubmit} />);
const input = screen.getByLabelText('Email');
const button = screen.getByRole('button', { name: /entrar/i });
fireEvent.change(input, { target: { value: 'test@example.com' } });
fireEvent.click(button);
expect(handleSubmit).toHaveBeenCalledWith('test@example.com');
});
it('exibe label corretamente', () => {
render(<LoginForm onSubmit={() => {}} />);
expect(screen.getByLabelText('Email')).toBeInTheDocument();
});
});
Use getByRole e getByLabelText (acessíveis a usuários) em vez de getByTestId. Isso garante que sua aplicação é usável por todos e força boas práticas de acessibilidade.
Integrando as Três Ferramentas
Na prática profissional, você usa todas juntas. Jest para lógica de negócio pura, Vitest para performance em desenvolvimento, Testing Library para UI. Um padrão comum:
// src/__tests__/integration.test.js
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { App } from '../App';
describe('Fluxo completo de usuário', () => {
it('usuário faz login e acessa dashboard', async () => {
render(<App />);
const user = userEvent.setup();
const emailInput = screen.getByLabelText('Email');
await user.type(emailInput, 'user@test.com');
await user.click(screen.getByRole('button', { name: /entrar/i }));
await waitFor(() => {
expect(screen.getByText(/bem-vindo/i)).toBeInTheDocument();
});
});
});
Use userEvent (simulação mais realista que fireEvent) e waitFor para operações assíncronas. Adicione coverage: jest --coverage gera relatórios HTML detalhados.
Conclusão
Dominar testes em JavaScript exige entender quando usar cada ferramenta. Primeiro aprendizado: Jest fornece a base sólida com API simples e integração perfeita com qualquer projeto. Segundo: Vitest moderniza a experiência com HMR e performance, ideal para workflows de desenvolvimento intensivo. Terceiro: Testing Library muda seu mindset, forçando código mais acessível e testável focando em comportamento, não implementação. A combinação desses conhecimentos transforma você de quem escreve testes em quem escreve código testável desde o início.