Todo mundo já passou por isso: você entra em um projeto com mais de 200 testes, pipeline verde, cobertura alta e mesmo assim… bugs passam, deploy dá medo e ninguém confia nos testes.
Foi exatamente esse cenário que enfrentamos. E a solução não foi escrever mais testes. Foi fazer o oposto: apagar a maioria deles.
O problema: muitos testes, pouca confiança
O projeto tinha: 212 testes, 87% de cobertura e tempo de execução alto. Mas na prática: qualquer refactor quebrava tudo, além de ter snapshots gigantes, mocks irreais e testes acoplados à implementação
Exemplo real (antes)
import { render } from '@testing-library/react';
import UserCard from './UserCard';
test('renderiza corretamente', () => {
const { container } = render(
<UserCard user={{ id: 1, name: 'Rafa' }} />
);
expect(container).toMatchSnapshot();
});
Problemas:
- snapshot enorme
- difícil revisar
- não testa comportamento
👉 só garante que nada mudou (ou finge garantir)
A decisão radical: reduzir para o essencial
Antes de sair refatorando, definimos uma regra simples:
“Se o teste não pega bug real, ele não deveria existir.”
Simples. E doloroso.
Etapa 1: deletar snapshots sem valor
Removemos quase todos.
De mais ou menos 80 snapshots, sobraram 5.
O que entrou no lugar
import { render, screen } from '@testing-library/react';
test('exibe nome do usuário', () => {
render(<UserCard user={{ id: 1, name: 'Rafa' }} />);
expect(screen.getByText('Rafa')).toBeInTheDocument();
});
Agora:
- teste legível
- fácil manutenção
- valida algo real
Etapa 2: parar de testar implementação
Esse foi o maior ganho. 😀
Antes (acoplado)
test('usa classe correta', () => {
const { container } = render(<Button />);
expect(container.firstChild).toHaveClass('btn-primary');
});
Depois (comportamento)
import userEvent from '@testing-library/user-event';
test('dispara ação ao clicar', async () => {
const onClick = jest.fn();
render(<Button onClick={onClick}>Salvar</Button>);
await userEvent.click(screen.getByText('Salvar'));
expect(onClick).toHaveBeenCalled();
});
👉 o teste sobrevive a refactor
Etapa 3: eliminar mocks mentirosos
Tínhamos vários testes assim:
jest.mock('./api', () => ({
fetchUsers: () => Promise.resolve([{ id: 1, name: 'Fake' }]),
}));
Problema:
👉 testava um mundo que não existe
Solução com MSW (mock realista)
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const server = setupServer(
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.json([
{ id: 1, name: 'Rafa' },
{ id: 2, name: 'Dev' },
])
);
})
);
beforeAll(() => server.listen());
afterAll(() => server.close());
Agora:
- simula API real
- mantém consistência
- reduz surpresas
Etapa 4: focar em fluxos reais
Paramos de testar funções isoladas. E começamos a testar o sistema.
Exemplo (login real)
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Login from './Login';
test('usuário consegue logar', async () => {
render(<Login />);
await userEvent.type(screen.getByLabelText('Email'), 'teste@email.com');
await userEvent.type(screen.getByLabelText('Senha'), '123456');
await userEvent.click(screen.getByRole('button', { name: 'Entrar' }));
expect(await screen.findByText('Bem-vindo')).toBeInTheDocument();
});
👉 isso pega bug de verdade
Etapa 5: adicionar poucos testes E2E (mas certos)
Usamos Playwright.
Exemplo de fluxo crítico
import { test, expect } from '@playwright/test';
test('fluxo de checkout', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.click('text=Produtos');
await page.click('text=Adicionar ao carrinho');
await page.click('text=Finalizar compra');
await expect(page.locator('h1')).toHaveText('Pedido confirmado');
});
👉 apenas 5 testes E2E cobriram o essencial
Resultado final (de verdade)
Antes:
- 212 testes
- execução: 9 minutos
- baixa confiança
Depois:
- 34 testes
- execução: 2 minutos
- alta confiança
E o mais importante
- menos falsos positivos
- menos manutenção
- mais segurança para deploy
O que aprendemos (na prática)
1. Cobertura alta pode ser enganosa
2. Snapshot é muleta (na maioria dos casos)
3. Mock mal feito cria ilusão
4. Teste bom é o que pega bug real
A regra que ficou
Se o teste não responde:
👉 “isso quebraria em produção?”
Ele provavelmente não deveria existir.
Conclusão: menos teste, mais valor
A maior virada não foi técnica, foi mental. Paramos de medir quantidade e cobertura. E começamos a medir confiança e utilidade
No final do dia, Dev Sênior tem que escrever os testes certos. E isso impacta diretamente a velocidade, a segurança e a maturidade do seu time.




