Preciso de teste de unidade se já tenho teste de integração?

47

Se eu já tenho um teste de integração para o meu programa e todos foram aprovados, sinto que ele funcionará. Quais são os motivos para escrever / adicionar testes de unidade? Como já tenho que escrever testes de integração, gostaria de escrever apenas testes de unidade para peças que não são cobertas por testes de integração.

O que eu sei os benefícios do teste de unidade sobre o teste de integração são

  • Pequeno e, portanto, rápido de executar (mas adicionar uma nova unidade para testar algo já foi testado pelo teste de integração significa que meu traje de teste total fica maior e mais longo para executar)
  • Localize o bug com mais facilidade porque ele só testa uma coisa (mas posso iniciar o teste de unidade de gravação para verificar cada parte individual quando meu teste de integração falhou)
  • Encontre um bug que pode não ser detectado no teste de integração. por exemplo, mascaramento / correção de erros. (mas se minha integração testar todas as aprovações, o que significa que meu programa funcionará mesmo que exista algum bug oculto. Portanto, encontre / corrija esses bugs não são realmente de alta prioridade, a menos que comecem a interromper futuros testes de integração ou causem problemas de desempenho)

E sempre queremos escrever menos código, mas os testes de unidade de gravação precisam de muito mais código (principalmente a configuração de objetos simulados). A diferença entre alguns dos meus testes de unidade e testes de integração é que, nos testes de unidade, eu uso objetos simulados, e nos testes de integração, eu uso objetos reais. Que têm muita duplicação e eu não gosto de código duplicado, mesmo em testes, porque isso adiciona uma sobrecarga para alterar o comportamento do código (a ferramenta refatorar não pode fazer todo o trabalho o tempo todo).

Bryan Chen
fonte
Por curiosidade, quanta cobertura seus testes de integração têm? Além disso, se você tiver alguma lógica complexa, seus testes de integração cobrem todas ou apenas parte dela e quais partes são importantes para os negócios ou aleatórias?
Civan
Esta questão parece ambígua. Digamos que eu tenho um método de controlador Rails que chama um interator ( github.com/collectiveidea/interactor ). Decidi escrever testes de integração para o meu método de controlador (porque sem eles não posso confiar que meu ponto de extremidade da API funcione). Existem pelo menos duas perguntas aqui: (1) devo também escrever testes de unidade para meus métodos de controlador (por exemplo, devo escrever testes de unidade que testam o mesmo comportamento que meus testes de integração) e (2) devo também escrever testes de unidade para o meu interator? Eu responderia a essas duas perguntas de maneira diferente em determinados contextos de negócios.
Daniel

Respostas:

33

Você apresentou bons argumentos a favor e contra o teste de unidade. Então você deve se perguntar: " Vejo valor nos argumentos positivos que superam os custos nos negativos? " Certamente:

  • Pequeno e rápido é um aspecto interessante dos testes de unidade, embora de maneira alguma seja o mais importante.
  • O erro de localização [s] é mais valioso. Muitos estudos de desenvolvimento profissional de software mostraram que o custo de um bug aumenta acentuadamente à medida que envelhece e diminui o pipeline de entrega de software.
  • Encontrar bugs mascarados é valioso. Quando você sabe que um componente específico tem todos os seus comportamentos verificados, você pode usá-lo de maneiras que não foram usadas anteriormente, com confiança. Se a única verificação for através do teste de integração, você saberá apenas que seus usos atuais se comportam corretamente.
  • A zombaria é cara nos casos do mundo real, e a manutenção da zombaria é duplamente. De fato, ao zombar de objetos ou interfaces "interessantes", você pode até precisar de testes para verificar se seus objetos simulados modelam corretamente seus objetos reais!

No meu livro, os profissionais superam os contras.

Ross Patterson
fonte
2
Zombar não é mais barato nos casos do mundo real? Você está apenas configurando as expectativas de quais mensagens o mock recebe e especificando o que ele retornará.
Dogweather
10
@Dogweather Mocks funciona bem quando criado pela primeira vez. À medida que o tempo passa e o objeto real é alterado, as zombarias precisam mudar com ele. 10 anos e 6.000 testes de unidade no caminho, é muito difícil saber que seus testes "bem-sucedidos" são realmente bem-sucedidos.
Ross Patterson
1
Como um aparte, que "10 anos e 6.000 testes de unidade" são números da experiência pessoal, não exageros.
Ross Patterson
3
Comecei a escrever testes de desenvolvedor automatizados (unidade e integração, mas principalmente os últimos) em 2004 ou 2005 e desenvolvi uma biblioteca avançada de simulação para Java. Muitas vezes vi vários testes de integração sendo interrompidos pelo mesmo motivo (como uma alteração no banco de dados ou uma alteração na rede) e às vezes escrevo testes de integração de "nível inferior" para componentes reutilizáveis, mas, ainda assim, prefiro apenas ter testes de integração. Testes de unidade isolados com zombaria, na maioria das vezes, simplesmente não valem a pena; Aplico a zombaria apenas como uma ajuda para os testes de integração.
Rogério
Seu último ponto parece contradizer o argumento que você está fazendo. Neste ponto, você está argumentando contra a criação de zombarias desnecessárias, que é um argumento contra a gravação de testes de unidade para peças que já são cobertas por testes de integração. O argumento do seu argumento, no entanto, é a favor de escrever testes de unidade para peças que já estão cobertas por testes de integração. Você poderia esclarecer sua intenção aqui @RossPatterson?
Daniel
8

Não vejo muito valor em reimplementar uma integração-testcase existente como unittest.

Os testes de integração costumam ser muito mais fáceis de escrever para aplicativos herdados não tdd, porque geralmente as funcionalidades a serem testadas são fortemente acopladas, de modo que as unidades de teste isoladas (= sem teste) podem ser difíceis / caras / impossíveis.

> Then what are the reasons to write/add unit tests?

Na minha opinião, o desenvolvimento orientado a testes é mais eficaz se você escrever os testes de unidade antes do código real. Dessa forma, o código que realiza os testes se torna claramente separado com um mínimo de referências externas fáceis de serem testadas.

Se o código já existir sem os testes de unidade, geralmente é muito trabalhoso escrever os testes de unidade posteriormente, porque o código não foi escrito para facilitar o teste.

Se você fizer TDD, o código será automaticamente testado facilmente.

k3b
fonte
2
Se eu tenho um aplicativo legado sem unit-tests, e quero incluir unit-testsem algumas partes, você acha melhor escrever primeiro integration testso código legado. Uma vez escrito, você pode desacoplar o acoplamento rígido e criar funções com interfaces que podem ser testadas? Desde que você já integration-testtenha escrito, poderá verificar em cada etapa da refatoração, se a nova versão do código ainda funciona como desejado?
alpha_989 24/02
2
@ alpha_989, isso é muito IMHO e estou aberto a ouvir outras idéias, mas eu preferiria Testes de Integração do que Testes de Unidade para Código Legado. Nos dois casos, você deve ter certeza de que os métodos estão funcionando corretamente antes de adicionar qualquer tipo de teste, mas o Teste de Integração garante que as expectativas gerais dos métodos estejam funcionando em oposição aos elementos de código individuais.
Britt Wescott
5

Os testes de integração devem apenas verificar se vários componentes estão funcionando juntos conforme o esperado. A precisão ou não da lógica dos componentes individuais deve ser verificada por testes de unidade.
A maioria dos métodos possui vários caminhos de execução possíveis; pense nas variáveis ​​de entrada if-then-else, com valores inesperados ou simplesmente errados etc. Geralmente, os desenvolvedores tendem a pensar apenas no caminho feliz: o caminho normal que não dá errado. Mas, no que diz respeito a esses outros caminhos, você tem duas opções: você pode permitir que o usuário final explore esses caminhos por meio das ações que eles executam na interface do usuário e espero que não travem seu aplicativo, ou você pode escrever testes de unidade que afirmam o comportamento desses outros caminhos e tome as medidas necessárias.

Stefan Billiet
fonte
4

Algumas das razões pelas quais você apontou na sua pergunta são realmente importantes e, por si só, poderiam muito bem defender o teste de unidade, mas o YMMV. Por exemplo, com que frequência você executa seu conjunto de testes integrado? Minha experiência com testes integrados é que mais cedo ou mais tarde eles ficarão tão lentos que você não os executará toda vez que fizer uma alteração e o tempo entre a inserção e a detecção de um bug aumentará.

Além disso, um grande erro que você pode estar cometendo é confiar que

Find bug that may not be caught in integration test. e.g. masking/offsetting bugs.

não é importante. Você espera que seus usuários encontrem os bugs para você? Confiar em coberturas obtidas a partir de testes integrados é perigoso, na minha opinião, você pode obter muito facilmente uma alta% de cobertura, mas, na realidade, está testando muito pouco.

Eu acho que a referência canônica contra testes integrados são os posts do JBrains:

http://www.jbrains.ca/permalink/integrated-tests-are-a-scam-part-1

caso você ainda não os tenha lido.

Por fim, na IMO, o feedback que você pode obter dos testes de unidade para seu projeto é inestimável. Julgar um projeto pelo instinto e confiar em testes integrados também pode ser um erro.

José Ricardo
fonte
Eu realmente não entendo esse artigo. Portanto, existem muitos caminhos de código e os testes de integração não podem cobrir todos eles ... então? O mesmo se aplica aos testes de unidade, a menos que suas unidades sejam tão triviais que sejam inúteis.
Casey
É mais como um argumento contra a fixação de cobertura de código em mais de um que você deveria escrever uma tonelada de testes de unidade e evitar testes de integração.
Casey
1

Se você espera ter que modificar ou refatorar seu código, é essencial ter testes de unidade. Os testes de unidade existem não apenas para demonstrar erros no momento em que o código é gravado, mas para mostrar quando novos erros aparecem quando mais código é gravado.

Sim, é muito melhor escrever seus testes de integração e unidade primeiro, mas há muito valor em tê-los, mesmo que sejam escritos posteriormente.

Matthew Flynn
fonte
3
Não acho que você tenha defendido. Os testes de integração também revelariam bugs no código e, de fato, são capazes de detectar bugs que os testes de unidade não apresentam.
Casey