Por que uma pirâmide?
Nem todos os testes custam o mesmo nem dão a mesma confiança. A pirâmide de testes (Mike Cohn) é uma heurística para repartir o esforço: larga na base, estreita no topo.
/\ E2E ← poucos: lentos, frágeis, alta confiança
/ \
/----\ Integração ← alguns: várias peças juntas
/ \
/--------\ Unitários ← muitos: rápidos, baratos, isolados
As três camadas
- Unitários (base, maioria): testam uma unidade isolada (uma função, uma classe) sem tocar em rede, disco nem banco de dados. Executam em milissegundos, então você pode ter milhares e rodá-los a cada salvamento. Quando falham, apontam com precisão o que quebrou.
- Integração (meio): comprovam que várias peças colaboram bem: um endpoint com sua camada de dados, um componente com sua store. Mais lentos que os unitários, mas detectam erros que os unitários não veem (contratos entre módulos).
- E2E (topo, minoria): exercitam toda a aplicação como um usuário real, do navegador até o banco de dados. Dão a maior confiança ("isto funciona de verdade") mas são lentos e frágeis.
O eixo custo / velocidade / confiança
Conforme você sobe na pirâmide, cada teste cobre mais sistema (mais confiança de que o produto funciona) mas em troca é mais lento, mais caro de escrever e mais propenso a falhar por motivos alheios ao bug (timing, rede, dados). Por isso você quer muitos testes baratos embaixo e poucos caros em cima: máxima confiança por minuto de execução.
Antipadrão: o cone de sorvete (muitos E2E, poucos unitários). A suíte demora horas, falha de forma intermitente e ninguém confia nela.
Exemplos
Um teste unitário: rápido e isolado
function precoComIcms(liquido, icms) {
return Math.round(liquido * (1 + icms) * 100) / 100;
}
// O "teste" comprova uma única unidade, sem rede nem BD:
console.log(precoComIcms(100, 0.21) === 121 ? "OK" : "FALHA");