Escreva a regra como comportamento observável
Considere a função “um cliente confirma um pedido”. Um teste pode enviar uma requisição e verificar status, estado persistido e evento produzido. Outro pode exercitar o mesmo resultado por uma tela no navegador. Ambos podem ser funcionais se validam a regra observável, mas têm escopos, custos e dependências diferentes.
Comece pelo requisito, incluindo resultados esperados e casos de erro. Evite testar um detalhe interno que não altera o comportamento para consumidor ou usuário; teste integração quando a questão for se componentes concretos cooperam.
Escolha a fronteira com o menor custo adequado
- Função ou domínio: rápido e preciso para cálculos e regras isoladas.
- API ou aplicação: útil para contratos HTTP e fluxos com o pipeline real, sem navegador.
- Integração: valida uma fronteira concreta, como aplicação e banco de dados.
- Ponta a ponta: valida uma jornada representativa passando pela interface e serviços conectados.
Use a fronteira mais estreita que responde à pergunta. Não é necessário reproduzir um fluxo completo pelo browser se um teste de API verifica a mesma regra com menos fragilidade. Por outro lado, nenhum teste de unidade comprova que a navegação principal realmente funciona.
Teste estados inválidos e transições importantes
Além do caminho feliz, cubra entradas inválidas, acesso negado, conflitos, ausência de dados e falhas recuperáveis que tenham significado para o usuário. Para um pedido, pode ser importante verificar que ele não é confirmado duas vezes, que a tentativa sem itens é rejeitada e que uma falha de persistência não retorna resposta de sucesso.
Não crie uma matriz combinatória sem prioridade. Selecione partições e limites representativos com base no risco e nas regras de negócio. Uma falha deve indicar claramente qual contrato deixou de ser atendido.
Teste resultados, não efeitos incidentais
Verifique o resultado público — resposta, estado, mensagem ou efeito que integra o contrato. Evite asserções sobre chamadas internas e ordem de métodos que podem mudar em uma refatoração sem mudar a função. Use dados controlados, relógios determinísticos quando necessários e dependências reais somente quando o teste pretende validar sua integração.
Teste o comportamento acessível da interface com seletores estáveis baseados no papel, nome ou atributos de teste planejados, não em classes CSS voláteis. Isso reduz manutenção causada por mudanças puramente visuais.
Testes funcionais e BDD
BDD pode ajudar a equipe a descobrir exemplos funcionais em linguagem de domínio antes de automatizá-los. Gherkin é um formato opcional para esses exemplos, não sinônimo de teste funcional. Leia BDD e cenários para entender colaboração e automação sem confundir documentação com cobertura.
Quando automatizar pela interface
Automatize poucas jornadas críticas no navegador, como entrar, concluir uma ação principal e verificar o resultado visível. Navegação e layout mudam com frequência; muitas verificações de detalhe na camada E2E deixam a suíte lenta e instável. Para interface web, veja Cypress e testes E2E; para a API, consulte testes de integração ASP.NET Core.