No meu projeto atual (um jogo, em C ++), decidi que usaria o Test Driven Development 100% durante o desenvolvimento.
Em termos de qualidade do código, isso tem sido ótimo. Meu código nunca foi tão bem projetado ou livre de erros. Não me arrependo ao visualizar o código que escrevi há um ano no início do projeto, e adquiri uma noção muito melhor de como estruturar as coisas, não apenas para ser mais facilmente testável, mas para ser mais simples de implementar e usar. .
No entanto ... já faz um ano desde que iniciei o projeto. É verdade que só posso trabalhar no meu tempo livre, mas o TDD ainda está me atrasando consideravelmente em comparação com o que estou acostumado. Eu li que a velocidade mais lenta de desenvolvimento melhora com o tempo, e eu definitivamente penso nos testes com muito mais facilidade do que costumava fazer, mas estou nisso há um ano e ainda estou trabalhando no ritmo de um caracol.
Cada vez que penso na próxima etapa que precisa de trabalho, tenho que parar toda vez e pensar em como escreveria um teste para isso, para permitir que eu escrevesse o código real. Às vezes, fico preso por horas, sabendo exatamente o código que quero escrever, mas sem saber como detalhá-lo o suficiente para cobri-lo completamente com testes. Outras vezes, pensarei rapidamente em uma dúzia de testes e passarei uma hora escrevendo testes para cobrir um pequeno pedaço de código real que, de outra forma, levaria alguns minutos para ser escrito.
Ou, depois de terminar o 50º teste para cobrir uma entidade específica no jogo e todos os aspectos de sua criação e uso, olho para a minha lista de tarefas e vejo a próxima entidade a ser codificada, e me encolho de horror ao pensar em escrever outros 50 testes semelhantes para implementá-lo.
Chegou ao ponto de que, olhando para o progresso do ano passado, estou pensando em abandonar o TDD por uma questão de "concluir o maldito projeto". No entanto, desistir da qualidade do código que acompanha ele não é algo que estou ansioso. Receio que, se eu parar de escrever testes, deixarei o hábito de tornar o código tão modular e testável.
Talvez eu esteja fazendo algo errado para ainda ser tão lento nisso? Existem alternativas que aceleram a produtividade sem perder completamente os benefícios? TAD? Menos cobertura de teste? Como outras pessoas sobrevivem ao TDD sem matar toda a produtividade e motivação?
fonte
Respostas:
Deixe-me começar agradecendo a você por compartilhar sua experiência e expressar suas preocupações ... o que devo dizer que não é incomum.
E isso me leva à consulta final: como posso melhorar? Minha (ou uma) resposta é ler, refletir e praticar.
Por exemplo, ultimamente, eu fico de olho
fonte
Você não precisa de 100% de cobertura de teste. Seja pragmático.
fonte
a = x + y
e, embora todas as linhas no código tenham sido executadas em testes, os testes foram testados apenas para o caso em que y = 0, portanto o bug (deveria ter sidoa = x - y
) nunca foi encontrado nos testes.Isso é realmente falso.
Sem o TDD, você passa algumas semanas escrevendo código que funciona principalmente e passa o próximo ano "testando" e corrigindo muitos (mas não todos) dos bugs.
Com o TDD, você passa um ano escrevendo código que realmente funciona. Depois, você faz o teste final de integração por algumas semanas.
O tempo decorrido provavelmente será o mesmo. O software TDD terá uma qualidade substancialmente melhor.
fonte
Isso me faz pensar em quanto você está seguindo a etapa "Refatorar" do TDD.
Quando todos os seus testes estiverem passando, é hora de refatorar o código e remover a duplicação. Embora as pessoas geralmente se lembrem disso, às vezes esquecem que também é hora de refatorar seus testes , remover a duplicação e simplificar as coisas.
Se você tiver duas entidades que se fundem em uma para permitir a reutilização de código, considere mesclar seus testes também. Você realmente só precisa testar diferenças incrementais no seu código. Se você não realiza manutenção regularmente em seus testes, eles podem se tornar rapidamente difíceis de manejar.
Alguns pontos filosóficos sobre TDD que podem ser úteis:
EDIT: No tópico da filosofia do teste de unidade, acho que pode ser interessante para você ler: O Caminho do Testivus
E um ponto mais prático, se não necessariamente muito útil,:
fonte
Pergunta muito interessante.
O que é importante notar é que o C ++ não é facilmente testável e os jogos, em geral, também são um candidato muito ruim para o TDD. Você não pode testar se o OpenGL / DirectX desenha triângulo vermelho com o driver X e amarelo com o driver Y facilmente. Se o vetor normal do mapa de resposta não for invertido após a transformação do shader. Nem você pode testar problemas de recorte em versões de driver com diferentes precisões e assim por diante. O comportamento indefinido do desenho devido a chamadas incorretas também pode ser testado apenas com a revisão precisa do código e o SDK em mãos. O som também é um candidato ruim. Multithreading, que novamente é bastante importante para jogos, é praticamente inútil para testes de unidade. Então é difícil.
Basicamente, os jogos são muito GUI, som e threads. A GUI, mesmo com componentes padrão para os quais você pode enviar WM_, é difícil de testar na unidade.
Portanto, o que você pode testar são classes de carregamento de modelos, classes de carregamento de texturas, bibliotecas de matrizes e algo assim, que não é muito código e, muitas vezes, não é muito reutilizável, se é apenas o seu primeiro projeto. Além disso, eles são compactados em formatos proprietários, portanto, não é bem provável que a entrada de terceiros possa diferir muito, a menos que você libere ferramentas de modificação, etc.
Por outro lado, eu não sou um guru ou evangelista da TDD, então leve tudo isso com um grão de sal.
Eu provavelmente escreveria alguns testes para os principais componentes principais (por exemplo, biblioteca de matrizes, biblioteca de imagens). Adicione
abort()
várias entradas inesperadas em todas as funções. E o mais importante, concentre-se em código resistente / resiliente que não se quebre facilmente.Com relação a um erro, o uso inteligente de C ++, RAII e um bom design ajudam bastante a evitá-lo.
Basicamente, você tem muito o que fazer apenas para cobrir o básico, se quiser lançar o jogo. Não tenho certeza se o TDD vai ajudar.
fonte
Concordo com as outras respostas, mas também quero acrescentar um ponto muito importante: custos de refatoração !!
Com testes de unidade bem escritos, você pode reescrever com segurança seu código. Primeiro, testes de unidade bem escritos fornecem excelente documentação sobre a intenção do seu código. Segundo, quaisquer efeitos colaterais infelizes da sua refatoração serão detectados no conjunto de testes existente. Assim, você garantiu que as suposições do seu código antigo também são verdadeiras para o seu novo código.
fonte
Isso é completamente diferente das minhas experiências. Você é incrivelmente inteligente e escreve código sem bugs (por exemplo, desligado por um erro) ou não percebe que seu código possui bugs que impedem o funcionamento do programa e, portanto, não estão realmente concluídos.
TDD é sobre ter a humildade de saber que você (e eu!) Cometemos erros.
Para mim, o tempo de criação de unittests é mais do que economizado no tempo de depuração reduzido para projetos que são feitos usando TDD desde o início.
Se você não cometer erros, talvez o TDD não seja tão importante para você quanto para mim!
fonte
Eu tenho apenas algumas observações:
Parece que você está tentando testar tudo . Você provavelmente não deveria, apenas os casos de alto risco e de borda de uma parte específica de código / método. Tenho certeza de que a regra 80/20 se aplica aqui: você gasta 80% escrevendo testes nos últimos 20% do seu código ou casos que não são cobertos.
Prioritizar. Entre no desenvolvimento ágil de software e faça uma lista do que você realmente precisa fazer para lançar em um mês. Então solte, assim mesmo. Isso fará você pensar sobre a prioridade dos recursos. Sim, seria legal se seu personagem pudesse dar um retorno, mas isso tem valor comercial ?
O TDD é bom, mas apenas se você não deseja obter 100% de cobertura de teste, e não o impede de produzir valor comercial real (ou seja, recursos, coisas que adicionam algo ao seu jogo).
fonte
Sim, escrever testes e código pode levar mais tempo do que escrever código - mas escrever código e testes de unidade associados (usando TDD) é muito mais previsível do que escrever código e depois depurá-lo.
A depuração é quase eliminada ao usar o TDD - o que torna todo o processo de desenvolvimento muito mais previsível e, no final - sem dúvida mais rápido.
Refatoração constante - é impossível fazer uma refatoração séria sem um conjunto abrangente de testes de unidade. A maneira mais eficiente de construir essa rede de segurança baseada em testes de unidade é durante o TDD. O código bem refatorado melhora significativamente a produtividade geral do designer / equipe que mantém o código.
fonte
Considere restringir o escopo do seu jogo e levá-lo aonde alguém possa jogá-lo ou você o libera. Manter seus padrões de teste sem ter que esperar muito tempo para lançar seu jogo pode ser um meio termo para mantê-lo motivado. Os comentários de seus usuários podem fornecer benefícios a longo prazo e seus testes permitem que você se sinta confortável com as adições e alterações.
fonte