TL; DR
Escrever testes bons e úteis é difícil e tem um alto custo em C ++. Os desenvolvedores experientes podem compartilhar sua lógica sobre o que e quando testar?
Longa história
Eu costumava fazer desenvolvimento orientado a testes, toda a minha equipe, mas não funcionou bem para nós. Temos muitos testes, mas eles nunca parecem cobrir os casos em que temos erros e regressões reais - o que geralmente ocorre quando as unidades estão interagindo, e não por seu comportamento isolado.
Geralmente, é tão difícil de testar no nível da unidade que paramos de fazer TDD (exceto para componentes onde realmente acelera o desenvolvimento) e, em vez disso, investimos mais tempo aumentando a cobertura do teste de integração. Enquanto os pequenos testes de unidade nunca detectaram bugs reais e eram basicamente apenas despesas gerais de manutenção, os testes de integração realmente valeram o esforço.
Agora, herdei um novo projeto e estou pensando em como testá-lo. Como é um aplicativo C ++ / OpenGL nativo, os testes de integração não são realmente uma opção. Mas o teste de unidade em C ++ é um pouco mais difícil do que em Java (você precisa fazer coisas explicitamentevirtual
), e o programa não é muito orientado a objetos, então não posso zombar / remover algumas coisas.
Eu não quero desmembrar e otimizar a coisa toda, apenas para escrever alguns testes em prol de escrever testes. Então, eu estou lhe perguntando: para que devo escrever testes? por exemplo:
- Funções / classes que espero mudar com frequência?
- Funções / classes que são mais difíceis de testar manualmente?
- Funções / classes que já são fáceis de testar?
Comecei a investigar algumas bases de código C ++ respeitosas para ver como eles fazem os testes. No momento, estou analisando o código-fonte do Chromium, mas acho difícil extrair a lógica de teste do código. Se alguém tiver um bom exemplo ou publicação de como usuários populares de C ++ (membros do comitê, autores de livros, Google, Facebook, Microsoft, ...) abordam isso, isso seria mais útil.
Atualizar
Eu procurei neste site e na Web desde que escrevi isso. Encontrou algumas coisas boas:
- Quando é apropriado não realizar o teste de unidade?
- /programming/109432/what-not-to-test-when-it-comes-to-unit-testing
- http://junit.sourceforge.net/doc/faq/faq.htm#best
Infelizmente, todos esses são bastante centrados em Java / C #. Escrever muitos testes em Java / C # não é um grande problema; portanto, o benefício geralmente supera os custos.
Mas, como escrevi acima, é mais difícil em C ++. Especialmente se sua base de código não é tão OO, você precisa estragar tudo para obter uma boa cobertura de teste de unidade. Por exemplo: O aplicativo que herdei tem umGraphics
espaço para nome que é uma camada fina acima do OpenGL. Para testar qualquer uma das entidades - que todas usam suas funções diretamente - eu teria que transformar isso em uma interface e uma classe e injetar em todas as entidades. Esse é apenas um exemplo.
Portanto, ao responder a essa pergunta, lembre-se de que preciso fazer um grande investimento para escrever testes.
fonte
Respostas:
Bem, o teste de unidade é apenas uma parte. Os testes de integração ajudam você com o problema da sua equipe. Os testes de integração podem ser escritos para todos os tipos de aplicativos, também para aplicativos nativos e OpenGL. Você deve verificar "Growing Object Oriented Software Guided by Tests" de Steve Freemann e Nat Pryce (por exemplo, http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Signature/dp/0321503627 ). Ele o leva passo a passo pelo desenvolvimento de um aplicativo com GUI e comunicação de rede.
Teste de software que não foi testado é outra história. Verifique Michael Feathers "Trabalhando efetivamente com o código herdado" (http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052).
fonte
É uma pena que o TDD "não tenha funcionado bem para você". Eu acho que é a chave para entender para onde ir. Revise e entenda como o TDD não funcionou, o que você poderia ter feito melhor, por que houve dificuldade.
Portanto, é claro que seus testes de unidade não detectaram os bugs que você encontrou. Esse é o ponto. :-) Você não encontrou esses bugs porque os impediu de acontecer em primeiro lugar, pensando em como as interfaces deveriam funcionar e como garantir que elas fossem testadas corretamente.
Para responder, você questiona, como concluiu, que o código de teste de unidade que não foi projetado para ser testado é difícil. Para o código existente, pode ser mais eficaz usar um ambiente de teste funcional ou de integração do que um ambiente de teste de unidade. Teste o sistema em geral, concentrando-se em áreas específicas.
É claro que o novo desenvolvimento se beneficiará do TDD. À medida que novos recursos são adicionados, a refatoração para TDD pode ajudar a testar o novo desenvolvimento, além de permitir o desenvolvimento de um novo teste de unidade para as funções herdadas.
fonte
Eu não fiz TDD em C ++, então não posso comentar sobre isso, mas você deve testar o comportamento esperado do seu código. Embora a implementação possa mudar, o comportamento deve (normalmente?) Permanecer o mesmo. No mundo centralizado em Java \ C #, isso significaria que você só testaria os métodos públicos, escrevendo testes para o comportamento esperado e fazendo isso antes da implementação (o que geralmente é melhor dizer do que fazer :)).
fonte