Testes Unitários, de Integração e E2E: entenda as diferenças
Entenda as diferenças entre testes unitários, de integração e E2E e aprenda a escolher o nível certo para cada risco do software.

Um teste pode validar uma função em milissegundos e ainda assim não perceber que a aplicação não consegue conversar com o banco.
Outro pode abrir o sistema inteiro no navegador, mas ser lento e difícil de diagnosticar quando falha. Por isso, qualidade não depende de escolher um único tipo de teste.
Testes unitários, de integração e E2E verificam o software em escopos diferentes. Os unitários isolam pequenas regras; os de integração confirmam a colaboração entre componentes reais; e os end-to-end percorrem um fluxo completo pela perspectiva do usuário ou cliente.
Neste guia, você entenderá as diferenças, custos, exemplos e critérios para combinar os três níveis sem criar uma suíte lenta, frágil ou incapaz de encontrar os riscos importantes.
O que são testes de software?
Testes de software são verificações executáveis sobre comportamentos esperados.
Eles fornecem evidência de que determinados cenários funcionam, ajudam a detectar regressões e tornam mudanças mais seguras. Porém, nenhum conjunto finito prova que um sistema não possui defeitos.
Uma boa estratégia prioriza risco. Regras financeiras, permissões, contratos de API e jornadas críticas merecem atenção diferente de detalhes visuais pouco relevantes.
A suíte também precisa ser rápida o suficiente para ser usada e clara o suficiente para explicar uma falha.
O que é teste unitário?
Teste unitário verifica uma pequena unidade de comportamento de forma isolada e rápida. A unidade pode ser uma função, classe ou conjunto coeso, dependendo do desenho.
O ponto importante é controlar dependências externas e obter um resultado determinístico.
Um teste para cálculo de desconto pode fornecer itens e perfil do cliente, executar a regra e comparar o total.
Ele não precisa iniciar servidor, acessar rede ou gravar em banco. Isso torna a execução rápida e facilita identificar qual regra foi quebrada.
- Vantagens: velocidade, diagnóstico preciso e ampla cobertura de regras.
- Limites: não prova que banco, fila, framework e serviços colaboram corretamente.
- Uso ideal: cálculos, validações, transformações e decisões de domínio.
Para um exemplo específico no ecossistema Java, consulte o guia de testes unitários com JUnit e Mockito. A documentação oficial do JUnit apresenta a plataforma e seus recursos atuais.
O que é teste de integração?
Teste de integração verifica se partes do sistema colaboram corretamente. Pode validar repositório e banco real, aplicação e fila, serialização HTTP ou vários módulos juntos.
Seu escopo varia; por isso, a equipe deve nomear claramente qual fronteira está sendo testada.
Uma API de pedidos pode iniciar a aplicação, usar um banco temporário, enviar uma requisição e confirmar o registro persistido.
Esse teste encontra problemas de mapeamento, transação, consulta e configuração que um teste unitário não alcança.
- Vantagens: confiança nas conexões e contratos reais.
- Limites: preparação mais cara, execução mais lenta e diagnóstico mais amplo.
- Uso ideal: banco, mensageria, HTTP, serialização e integração entre módulos.

O que é teste E2E?
Teste end-to-end, ou E2E, percorre um fluxo completo em um sistema próximo do real. Em uma aplicação web, pode abrir o navegador, autenticar, adicionar um produto ao carrinho, finalizar o pedido e verificar a confirmação.
Esse nível atravessa várias camadas e oferece confiança na jornada, mas custa mais para executar e manter.
Mudanças de interface, latência, dados compartilhados e serviços indisponíveis podem provocar falhas sem que a regra principal esteja errada.
A documentação do Playwright Test mostra recursos para testes ponta a ponta em navegadores, incluindo isolamento, paralelismo e rastreamento para diagnóstico.

Diferenças entre testes unitários, integração e E2E
| Critério | Unitário | Integração | E2E |
|---|---|---|---|
| Escopo | Unidade pequena | Componentes colaborando | Fluxo completo |
| Dependências | Isoladas ou controladas | Algumas reais | Maioria real ou equivalente |
| Velocidade | Alta | Média | Menor |
| Diagnóstico | Preciso | Moderado | Mais difícil |
| Confiança principal | Regra local | Integração e contrato | Jornada |
Essas categorias não possuem fronteiras universais. Um teste com banco em memória pode ser chamado de unitário em uma equipe e de integração em outra. Mais importante que o rótulo é declarar escopo, dependências e risco coberto.
A pirâmide de testes
A pirâmide sugere muitos testes rápidos na base, uma quantidade menor de integrações e poucos E2E no topo. O Google Testing Blog explica essa estratégia e alerta para suítes concentradas em testes ponta a ponta.
A proporção não deve ser uma meta rígida. Uma biblioteca matemática pode ter enorme base unitária; uma camada de integração pode exigir mais testes de contrato; uma interface crítica pode justificar fluxos E2E adicionais. A forma ideal acompanha a arquitetura e os riscos.
Mocks, stubs e dependências reais
Um stub devolve respostas controladas. Um mock também pode verificar interações esperadas. Esses dublês tornam testes rápidos, mas uma simulação incorreta pode concordar com o código enquanto a API real mudou.
Use dublês nas bordas quando o objetivo é exercitar uma decisão local. Use dependências reais ou ambientes equivalentes quando o risco está no protocolo, consulta, serialização ou configuração.
Quanto mais importante o contrato externo, mais valioso é um teste de integração.
O acoplamento também influencia a facilidade de teste. O guia sobre dependências de software mostra como ligações rígidas ampliam falhas e dificultam substituições controladas.
Como testar uma API em cada nível
Considere o endpoint de criação de pedido. No nível unitário, teste cálculo, validação e transições de estado com dependências controladas.
No nível de integração, envie uma requisição à aplicação, use banco real temporário e confirme status, corpo e persistência.
No E2E, percorra apenas jornadas críticas: o usuário entra na loja, escolhe itens, paga em ambiente controlado e vê a confirmação. O objetivo não é repetir todas as combinações da regra; essas combinações pertencem à camada rápida.
Ao testar uma API REST ou GraphQL, inclua também contratos de esquema, autenticação, erros e compatibilidade, escolhendo o nível mais barato capaz de encontrar cada risco.
Como escolher o tipo de teste
- Se o risco é uma regra isolada, comece com teste unitário.
- Se está na conversa entre componentes, use integração.
- Se envolve uma jornada completa indispensável, adicione E2E.
- Se o defeito já escapou, crie o teste no nível mais baixo que consegue reproduzi-lo com fidelidade.
- Se o teste é lento demais para cada commit, organize estágios sem retirar o feedback rápido.
Evite duplicação sem propósito. Testar a mesma matriz de cem casos nos três níveis aumenta custo sem triplicar confiança.
Deixe combinações detalhadas perto da regra e reserve camadas amplas para conexões e cenários representativos.
Testes no pipeline de CI/CD
Testes unitários devem fornecer retorno imediato. Integrações podem executar em seguida com serviços temporários.
E2E críticos podem bloquear a promoção para um ambiente, enquanto uma suíte mais ampla roda em horários específicos.
O artigo de CI/CD para iniciantes explica como testes se encaixam entre integração, entrega e implantação. O pipeline precisa preservar relatórios, logs e artefatos que permitam diagnosticar uma falha.
Testes instáveis e falsos resultados
Um teste flaky passa e falha sem mudança relevante no código. Tempo, concorrência, rede, ordem de execução e dados compartilhados são causas comuns. Ignorar ou repetir indefinidamente a execução destrói a confiança da equipe.
Use dados independentes, espere condições observáveis em vez de pausas fixas, controle relógio e aleatoriedade, elimine dependência de ordem e registre evidências.
O estudo do Google sobre testes flaky discute como testes maiores tendem a apresentar mais instabilidade.
Boas práticas
- Teste comportamento observável, não detalhes privados.
- Dê nomes que expressem cenário e resultado.
- Mantenha cada teste independente e repetível.
- Crie dados mínimos e explícitos.
- Não compartilhe estado mutável entre execuções.
- Faça a falha apontar claramente o problema.
- Remova ou corrija testes que deixaram de proteger comportamento válido.
Erros comuns
Buscar somente cobertura percentual é um erro. Um teste pode executar linhas sem verificar resultados relevantes. Cobertura ajuda a localizar áreas não exercitadas, mas não mede a qualidade das asserções.
Outro erro é depender apenas de E2E. A suíte fica lenta e toda falha pode ter muitas causas. O extremo oposto também é perigoso: milhares de unitários com integrações simuladas não percebem contratos quebrados.
A ausência de testes em áreas sensíveis pode ocultar riscos de segurança. O conteúdo sobre vulnerabilidades causadas pela falta de testes complementa essa perspectiva.
Perguntas frequentes
Qual tipo de teste deve ser criado primeiro?
Comece pelo risco e pelo nível mais barato que consegue verificá-lo. Regras isoladas normalmente favorecem unitários; conexões reais exigem integração.
Teste com banco é sempre de integração?
Na maioria das classificações, sim, porque envolve uma dependência externa e verifica sua colaboração com o código.
Teste E2E substitui teste manual?
Não completamente. Exploração humana ainda encontra problemas inesperados de usabilidade, contexto e comportamento que roteiros automatizados não procuram.
Quantos testes um projeto deve ter?
Não existe número universal. A quantidade deve cobrir riscos relevantes e permanecer sustentável em tempo de execução e manutenção.
Todo teste unitário precisa de mock?
Não. Funções puras e objetos simples podem ser testados diretamente. Mocks são úteis somente quando uma interação precisa ser controlada ou observada.
O que fazer com um teste flaky?
Investigue e corrija rapidamente. Se necessário, coloque-o temporariamente em quarentena com responsável e prazo, sem esconder a falha no pipeline principal.
Conclusão
Testes unitários protegem regras com velocidade; testes de integração validam conexões reais; e testes E2E confirmam jornadas completas.
Nenhum nível substitui os demais porque cada um enxerga uma classe diferente de risco.
Uma suíte saudável concentra combinações na camada rápida, verifica contratos nas fronteiras e reserva E2E para fluxos que justificam seu custo.
Mais importante que seguir uma proporção fixa é obter feedback confiável, diagnóstico claro e segurança para mudar o software.