Uma feature de checkout precisa de três testes E2E, não de trinta: um para o happy path, um para falha de pagamento, um para item fora de estoque. Os outros casos extremos são mais baratos e estáveis como testes unitários e de API.
O modelo original
Mike Cohn introduziu a pirâmide de testes em 2009. A versão original tinha três camadas:
/\
/ \
/ E2E \ ← poucos, lentos, caros
/--------\
/ Integração\ ← alguns
/--------------\
/ Testes Unit. \ ← muitos, rápidos, baratos
/------------------\A forma importa: muitos na base, menos no topo. A pirâmide.
Por que a forma importa
Se você inverter a pirâmide, com muitos testes E2E e poucos testes unitários, você obtém:
- Uma suite lenta (testes E2E levam de 10 a 60 vezes mais do que testes unitários)
- Testes flaky (mais partes móveis = mais modos de falha)
- Informações de debug ruins (uma falha E2E diz que algo está errado; uma falha de teste unitário diz exatamente o quê)
- Manutenção cara (mudanças de UI quebram testes E2E; APIs mudam com menos frequência)
O anti-padrão clássico é o cone de sorvete: camada minúscula de testes unitários, nenhuma integração, e uma suite E2E massiva que leva 45 minutos e falha aleatoriamente.
A interpretação moderna
A pirâmide original é anterior a microsserviços, serverless e frameworks como Playwright que tornam os testes E2E significativamente mais confiáveis. A versão moderna reconhece isso:
/\
/ \
/ E2E \ ← smoke tests, caminhos críticos
/--------\
/ API/Svc \ ← testes de integração, contract tests
/--------------\
/ Component/Unit \ ← lógica de negócio, utilitários
/--------------------\As proporções específicas variam por time e tipo de produto. Uma API CRUD pode ter poucos testes E2E e cobertura pesada de API. Um dashboard React com UI complexa pode ter mais testes de componentes e menos testes unitários.
O princípio permanece: dependa dos testes mais baratos, rápidos e estáveis. Reserve o E2E para os cenários que só podem ser verificados pelo full stack.
Aplicando a pirâmide a um projeto Playwright
O que pertence aos testes E2E:- Jornadas críticas do usuário (login → checkout → confirmação)
- Integração entre serviços (frontend + backend + banco de dados juntos)
- Comportamentos específicos do browser (upload de arquivo, múltiplas abas, redirecionamento OAuth)
- Smoke tests para deploys de produção
- Mensagens de erro de validação (teste-as em testes unitários da lógica de validação)
- Cada caso extremo de um algoritmo complexo (teste unitário)
- Respostas de API em isolamento (teste de API)
- As 15 permutações de um formulário (use particionamento de equivalência, escolha 3 a 4 casos representativos para E2E)
Um exemplo concreto
Você está testando uma feature de realização de pedido. Os requisitos:
1. Usuário adiciona item ao carrinho
2. Usuário vai para o checkout
3. Usuário preenche informações de entrega
4. Usuário paga
5. Confirmação do pedido exibida
6. Email enviado ao usuário
Testes unitários cobrem:- Lógica de cálculo de preço (descontos, impostos, custos de frete)
- Renderização do template de email
- Função de validação de endereço
- Arredondamento do valor do pagamento
- POST /orders cria registro no banco de dados
- POST /orders com pagamento inválido retorna 422
- Transições de status do pedido (pendente → confirmado → enviado)
- Serviço de email chamado com parâmetros corretos
- Happy path: pedido completo do carrinho à confirmação (um teste)
- Falha de pagamento: cartão recusado, erro exibido, pedido não criado (um teste)
- Item esgotado: item indisponível, usuário redirecionado com mensagem (um teste)
Só isso. Três testes E2E para uma feature de checkout inteira. Os testes unitários e de API cobrem os casos extremos. O E2E cobre os fluxos que mais importam para os usuários.
O testing trophy (modelo alternativo)
Kent C. Dodds propôs o testing trophy em 2018, que ajusta a pirâmide para frontends JavaScript:
/\
/ \ ← E2E (poucos)
/----\
/ Integr \ ← integração (a maioria)
/----------\
/ Unitário \ ← unitário (alguns)
/--------------\
/ Estático \ ← tipos, linting (sempre)
/------------------\A diferença principal: testes de integração no topo do meio. Para apps React, Vue ou Next.js, "testes de integração" significa renderizar componentes com suas dependências reais. Chamadas de API vão para um servidor de teste real ou para uma versão mockada na camada de rede. Essa é a filosofia do React Testing Library: teste como os usuários interagem com o componente, não os detalhes de implementação.
Os dois modelos são válidos. A pirâmide se encaixa bem em sistemas backend. O trophy se encaixa em aplicações com frontend pesado. Qualquer um deles é melhor do que o cone de sorvete.
A regra prática
Quando você está prestes a escrever um teste E2E, pergunte: o que esse teste está realmente verificando que não poderia ser verificado em um nível inferior?
Se a resposta for "que o frontend e o backend estão conectados e os dados fluem corretamente pelo full stack": escreva o teste E2E.
Se a resposta for "que a validação do formulário mostra um erro para um campo de email vazio": isso é terreno de teste unitário. Escreva um teste para a função de validação e um teste de componente para o formulário. O teste E2E seria apenas ruído.
→ Veja também: Testes de Fumaça vs Testes de Regressão: Qual é a Diferença? | Teste de Componentes com Playwright: Testando Componentes React/Vue em Isolamento | Boas Práticas de Automação de Testes que Realmente Importam