← Conceitos de Testes

A Estratégia da Pirâmide de Testes

Published on 2026-08-06·v1.0

Objective

A pirâmide de testes é uma estratégia sobre quantos testes de cada tipo escrever. Os testes de software formam uma hierarquia: unitário na base, depois integração, depois sistema, depois aceitação no topo, e o formato de pirâmide prescreve suas proporções: muitos testes unitários rápidos e baratos na base, e progressivamente menos testes lentos e caros em direção ao topo. O objetivo é capturar a maioria dos defeitos no nível mais barato, ainda verificando, com um punhado de testes de nível mais alto, que o sistema inteiro funciona. Cada nível mapeia para uma ferramenta: JUnit 5 + Mockito para unidades, JUnit 5 (frequentemente com Spring) para integração, Selenium para sistema/UI, Cucumber para aceitação.

Use Cases

  • Decidir a mistura de testes para um projeto: escrever a maioria no nível unitário e só alguns testes de ponta a ponta, em vez do inverso.
  • Diagnosticar uma suíte de testes lenta e instável (geralmente uma pirâmide invertida, testes demais de UI/E2E, poucos demais no nível unitário).
  • Escolher o nível certo para uma dada verificação: regra de negócio → unidade; interação de componente → integração; jornada de usuário → aceitação.
  • Estruturar os testes de uma base de código nova para que o loop de feedback rápido (unidades) continue rápido e a suíte lenta (E2E) continue pequena.
  • Decidir o que testar no nível unitário: lógica de negócio, entradas ruins, limites, invariantes e regressões.

Deep Dive

Os quatro níveis, de baixo para cima

Do mais barato/numeroso ao mais caro/escasso (os próprios níveis são definidos no conceito "Princípios de Teste de Software"):

plaintext
▲ Aceitação : satisfaz o usuário final? (cenários Cucumber) ▲▲ Sistema : sistema inteiro vs. spec, sem conhecimento de código (Selenium/UI) ▲▲▲ Integração : unidades verificadas, combinadas e testadas juntas (JUnit 5 + Spring) ▲▲▲▲ Unidade : cada classe/método isoladamente (JUnit 5 + Mockito)

Testes de nível baixo são detalhados e rápidos; testes de nível alto são abstratos, mais próximos do usuário, e mais lentos. A pirâmide diz: empurre o teste para baixo: prefira um teste unitário a um de integração, e um de integração a um de ponta a ponta, sempre que um nível puder dar a mesma confiança.

O que testar (a checklist do nível unitário)

Na base, o livro enumera o que merece um teste. Um único value object mostra vários de uma vez:

java
@Test void rejectsNegativeSeatCount() { // bad input value assertThrows(RuntimeException.class, () -> new Flight("AA1", -5)); } @Test void acceptsBoundaryValues() { // boundary conditions assertEquals(0, new Flight("AA1", 0).getPassengers().size()); // min: empty flight } @Test void identifierCannotChangeToInvalid() { // invariant Passenger p = new Passenger("900-45-6789", "Mike", "US"); assertThrows(RuntimeException.class, () -> p.setIdentifier("bad")); }

A checklist: lógica de negócio, valores de entrada ruins, condições de limite (mín/máx/vazio/cheio), condições inesperadas, invariantes (valores que não devem mudar), e regressões (um teste por bug corrigido para que não volte).

Mapeando ferramentas aos níveis

A pirâmide é construída com as ferramentas do livro todo, cada uma no seu nível:

plaintext
Unidade JUnit 5 + Mockito : isola uma classe, mocka seus colaboradores Integração JUnit 5 (+ Spring) : carrega colaboradores reais juntos (@SpringBootTest, DB) Sistema Selenium WebDriver : controla a UI rodando de ponta a ponta Aceitação Cucumber (Gherkin) : verifica cenários de negócio na linguagem das partes interessadas

Uma suíte saudável roda a base larga de unidades a cada mudança (segundos), e o topo estreito (Selenium/Cucumber) com menos frequência (minutos); o formato mantém o feedback rápido de fato rápido.

Trade-offs

  • Inverter a pirâmide (o "cone de sorvete") arruína o feedback: muitos testes lentos de UI/E2E sobre uma base fina de unidades dá uma suíte lenta, frágil e instável, porque toda mudança pequena reexecuta testes caros e dependentes de ambiente:
plaintext
▼▼▼▼ many E2E/UI ← slow, flaky, expensive ▼▼ some integration ▼ few unit ← anti-pattern: push tests DOWN instead
  • Testes unitários são rápidos, mas cegos para integração: uma classe pode passar em todo teste unitário e ainda falhar quando conectada aos seus colaboradores reais (SQL errado, bean mal configurado), que é exatamente o que os (menos numerosos) testes de integração existem para capturar.
  • Testes de ponta a ponta dão mais confiança e mais dor: eles exercitam o sistema real como um usuário faria, mas são lentos, precisam de um ambiente completo, e falham por razões que não são de código (tempo, rede, dados de teste), então você quer poucos deles, mirando jornadas críticas.
  • As proporções são heurísticas, não leis: "quantos" depende do sistema (uma aplicação carregada de UI precisa de mais testes de sistema do que uma biblioteca pura); a pirâmide é um viés a favor de testes baratos, não uma proporção fixa a impor mecanicamente.

Documentation Links