Nas últimas semanas, estive pensando e pesquisando como preencher uma lacuna em nossa metodologia de testes. Em termos simplificados, os testes de unidade são muito pequenos e os testes de integração tradicionais são muito grandes.
Um cenário frequente surge onde A
e B
ambos usam o componente C
. No entanto A
e B
tem requisitos ligeiramente diferentes para, e faça suposições ligeiramente diferentes sobre C
. Se eu sou o desenvolvedor de A
como e onde testo minhas suposições C
?
Obviamente, o teste de unidade A
com suposições simuladas C
é bom para testes A
isolados, mas não testa as próprias suposições.
Outra possibilidade é adicionar testes de unidade para C
. No entanto, isso não é ideal porque, enquanto A
estiver em desenvolvimento, alterar os testes C
com as suposições em evolução A
será excessivamente desajeitado. De fato, A
o desenvolvedor pode nem ter acesso adequado aos testes de unidade de C
(por exemplo, uma biblioteca externa).
Para enquadrar isso com um exemplo mais concreto: Suponha que este seja um aplicativo de nó. A
e B
dependem C
de ler um arquivo (entre outras coisas) e armazenar o conteúdo do arquivo no objeto passado para C
. No início, todos os arquivos que C
manipulam são pequenos e podem ser lidos de forma síncrona sem bloqueio significativo. No entanto, o desenvolvedor B
percebe que seus arquivos estão ficando enormes e precisa mudar C
para uma leitura assíncrona. Isso resulta em um erro de sincronização esporádica A
, que ainda pressupõe a C
leitura de arquivos de forma síncrona.
Esse é o tipo de bug que é notoriamente difícil de rastrear nos testes de integração completos e pode não ser detectado nos testes de integração. Também não é detectado pelos A
testes de unidade, porque as A
suposições são zombadas. No entanto, poderia ser facilmente capturado por um "mini" teste de integração que exercita apenas A
e C
.
Eu encontrei apenas algumas referências a esse tipo de teste. Integração no Pequeno , Teste de Integração de Componentes , Teste de Integração de Unidade . Também se relaciona um pouco com a direção de teste do BDD, em vez de com o teste formal da unidade TDD.
Como preencher essa lacuna de teste? Especificamente - onde coloco esses testes? Como zombar das entradas A
e C
dos "mini" testes de integração? E quanto esforço deve ser feito para separar as preocupações dos testes entre esses testes e os testes de unidade? Ou existe uma maneira melhor de preencher a lacuna de teste?
Respostas:
Parece-me que você tem um problema fundamental com seus componentes.
C deve fazer o que C precisa fazer e ser testado, documentado e projetado para fazer exatamente isso. Quando você tem uma situação em que C é projetado para "fazer o que B quer", você tem um relacionamento abusivo, que fica muito claro quando A chega e quer que C faça algo ligeiramente diferente.
O que você não deve fazer é testar a unidade C no contexto de A, e especialmente A no contexto de C - você testa A independentemente e fornece os resultados de uma C zombada a A. Se a versão do mundo real de C não fornece os mesmos resultados, então você tem uma falha de design ou bug em C que será detectada quando você executar seus grandes testes de integração. O teste de unidade sempre foi assim - você não pode testar uma unidade testando outra unidade ao mesmo tempo. O teste de unidade simplesmente não foi projetado para fazer isso.
Os testes de integração não precisam ser "o programa inteiro", embora sejam frequentemente configurados dessa maneira. Eles podem ser um equipamento de teste que executa A e C juntos sem executar o restante do programa (ou o mínimo possível). Neste ponto, não posso aconselhar mais, pois depende do que esses componentes fazem e como eles interagem com o restante do seu programa, mas geralmente é o caso de você poder escrever uma plataforma de teste que ofereça cobertura de teste para ambos os componentes. Se vale a pena o esforço para fazer isso ou se é mais eficiente testar a integração de todo o programa como um (mesmo que você execute um subconjunto dos testes de integração) é algo que apenas você pode responder. A maioria dos testes de integração é composta por várias seções, portanto, esperamos que você consiga executar apenas aqueles relevantes para esses 2 componentes (e, se não,
fonte