Eu não sou novo em codificação. Eu tenho codificado (sério) há mais de 15 anos. Eu sempre tive alguns testes para o meu código. No entanto, nos últimos meses, tenho aprendido design / desenvolvimento orientado a testes (TDD) usando Ruby on Rails . Até agora, não estou vendo o benefício.
Vejo algum benefício em escrever testes para algumas coisas, mas muito poucas. E embora eu goste da ideia de escrever o teste primeiro, acho que passo substancialmente mais tempo tentando depurar meus testes para que eles digam o que eu realmente quero dizer do que depurando o código real. Isso provavelmente ocorre porque o código de teste geralmente é substancialmente mais complicado do que o código que ele testa. Espero que isso seja apenas inexperiência com as ferramentas disponíveis ( neste caso, o RSpec ).
Devo dizer que, neste ponto, o nível de frustração misturado com a decepcionante falta de desempenho está além do inaceitável. Até agora, o único valor que estou vendo do TDD é uma biblioteca crescente de arquivos RSpec que servem como modelos para outros projetos / arquivos. O que não é muito mais útil, talvez menos útil, do que os arquivos de código do projeto.
Ao ler a literatura disponível, percebo que o TDD parece ser um tempo enorme, mas vale a pena no final. Só estou pensando, existem exemplos do mundo real? Essa frustração massiva é recompensada no mundo real?
Eu realmente espero não ter perdido esta pergunta em outro lugar aqui. Eu procurei, mas todas as perguntas / respostas têm vários anos neste momento. Foi uma ocasião rara quando eu encontrei um desenvolvedor que dizia algo ruim sobre o TDD, e é por isso que gastei tanto tempo nisso quanto eu. No entanto, notei que ninguém parece apontar para exemplos específicos do mundo real. Eu li uma resposta que dizia que o cara que depurava o código em 2011 agradeceria por ter um conjunto completo de testes de unidade (acho que esse comentário foi feito em 2008).
Então, eu só estou pensando, depois de todos esses anos, finalmente temos alguns exemplos mostrando que o retorno é real? Alguém realmente herdou ou voltou ao código que foi projetado / desenvolvido com o TDD e que possui um conjunto completo de testes de unidade e realmente sentiu uma recompensa? Ou você achou que estava gastando tanto tempo tentando descobrir o que o teste estava testando (e por que era importante) que acabou de jogar toda a bagunça e cavar o código?
fonte
Respostas:
Este artigo demonstra que o TDD adiciona 15 a 35% do tempo de desenvolvimento em troca de uma redução de 40 a 90% na densidade de defeitos em projetos semelhantes.
O artigo refere o artigo completo (pdf) - Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat e Laurie Williams. "Realizando a melhoria da qualidade através do desenvolvimento orientado a testes: resultados e experiências de quatro equipes industriais". ESE 2008 .
O artigo completo também resume brevemente os estudos empíricos relevantes sobre TDD e seus resultados de alto nível (seção 3 Trabalhos relacionados ), incluindo George e Williams 2003, Müller e Hagner (2002), Erdogmus et al. (2005), Müller e Tichy (2001), Janzen e Seiedian (2006).
fonte
Trabalho com TDD há três anos e minha experiência é exatamente o oposto. Eu gasto menos tempo escrevendo testes de unidade que teria depurado o código, se não tivesse escrito os testes de unidade.
Não só faço TDD, também trabalho de fora para dentro, ou seja, primeiro implemento o TDD da camada superior / GUI. A implementação da camada superior define os requisitos para a próxima camada do sistema, que eu desenvolvo usando TDD, etc., até que todo o código necessário para o recurso tenha sido implementado. Freqüentemente, experimento que, depois de implementar um recurso como este, e testar o recurso no sistema real, ele funciona pela primeira vez. Não o tempo todo, mas frequentemente.
E, considerando que demora muito mais tempo para testar um recurso no sistema do que para executar alguns testes de unidade, economizo uma quantidade enorme de tempo. Na verdade, é mais rápido implementar um recurso usando TDD do que não implementar o recurso sem escrever testes de unidade.
Mas escrever testes de unidade é uma habilidade que precisa ser aprendida e dominada, como qualquer outra habilidade de programação. Quando comecei a TDD, tinha 12 anos de experiência profissional em programação e era um programador muito talentoso. Eu pensei que escrever grandes suítes de teste para o código do sistema seria uma coisa simples. Mas à medida que a quantidade de código de teste crescia, e diferentes partes do sistema eram alteradas, e os testes existentes tinham que ser modificados, aprendi que estruturar e escrever testes de unidade é em si uma habilidade que precisa ser aprendida e dominada. Além disso, nem todo código é igualmente testável. O código do sistema deve ser muito pouco acoplado para poder ser testado com eficiência. Na verdade, aprender TDD me ajudou a tornar o código do sistema mais frouxamente acoplado.
Mas minha eficiência atual no trabalho de TDD vem de uma combinação de ambos como dominar como escrever testes de unidade, mas também dominar a tecnologia na qual o sistema é implementado (C # neste caso).
Fazer TDD enquanto aprende uma nova tecnologia pode ser difícil, por exemplo, embora eu tenha feito um pouco de programação no iPhone, não estou escrevendo uma quantidade significativa de testes de unidade, porque não domino a linguagem, o objetivo c, nem domino a biblioteca. Portanto, não tenho idéia de como estruturar meus testes de unidade, muito menos de como estruturar o código do sistema, como torná-lo testável.
No projeto em que trabalho nos últimos dois anos, embora exista um requisito de que o código seja coberto suficientemente por testes de unidade, sou o único na equipe que está escrevendo os primeiros testes. Mas o grande conjunto de testes me dá confiança para refatorar o sistema e acredito que o sistema funcionará corretamente se o conjunto de testes for aprovado.
Infelizmente, porém, porque muitos dos testes são escritos após o código do sistema, alguns deles são defeituosos, ou seja, eles realmente não testam o que eles deveriam testar. Este imho não pode ser evitado. Toda vez que você escreve um pedaço de código, há uma probabilidade de o código não funcionar como você pretendia, ou seja, há um erro. O mesmo vale para o código de teste. Portanto, há uma probabilidade de que você escreva um teste que passe, mesmo que o código que ele deveria estar testando não esteja funcionando conforme o esperado.
Escrevendo o teste primeiro, verificando não apenas se há uma falha no teste, mas se o teste falha exatamente com a mensagem de erro que você espera antes de implementar o código do sistema reduz seriamente o risco de um bug no código do teste de unidade.
Então, para resumir, na minha experiência, depois de dominar a arte do TDD, você não economizará apenas tempo a longo prazo, mas sim na frente. Mas leva tempo, mesmo para um programador experiente, dominar a arte do TDD. E leva ainda mais tempo para uma equipe de desenvolvedores de habilidades variadas dominar a arte do TDD.
fonte
Somos comerciantes de nível 1, o que significa que processamos mais de seis milhões de transações de pagamento por ano.
Nosso sistema de gateway de pagamento possui milhares de testes de unidade e integração. Esses testes nos dão confiança em nossa capacidade de processar pagamentos. Você quer ter certeza de que os freios do seu carro funcionam, não é? Queremos ter certeza de que não perdemos nossos negócios porque não podemos processar pagamentos.
A cobertura do código oferece essa confiança. Claro que não basta por si só, mas é um começo muito bom.
A maior parte do nosso sistema de gateway de pagamento foi escrita usando TDD. Alguns aspectos foram bastante difíceis de testar, por isso decidimos cortar custos sacrificando alguma cobertura de código. Voltaremos e resolveremos esses problemas eventualmente.
Pessoalmente, acho difícil escrever qualquer lógica antes de escrever testes. Dito isto, demorei um pouco para começar a pensar no modo TDD.
Referência do Visa PCI: http://usa.visa.com/merchants/risk_management/cisp_merchants.html
fonte
Embora os testes possam ser frequentemente considerados apenas uma maneira de fazer muito por algumas pessoas, acho que realmente vale a pena em alguns casos.
Desenvolvo um Killer Sudoku Solver para a escola há cerca de 3 meses. Ele usa muitas "estratégias" para remover possibilidades e soluções. O fato é que, um erro em uma possibilidade pode ser fatal e resultar em um problema para resolver o sudoku, porque quando alguma possibilidade é removida, você não tenta mais, e se era a solução, o programa não pode resolver a grade mais.
Mas é realmente difícil testar manualmente, quero dizer, há uma grade, posso ver quais estratégias estão fazendo o que em um exemplo do mundo real, mas não consigo verificar todas as vezes que uma estratégia se aplica porque isso representa muitos dados.
E as estratégias aplicadas a uma determinada grade são bastante "aleatórias", ou seja, você não usará todas em uma grade específica.
Então, escrevi testes em cada estratégia, verificando o resultado em todas as células, usando apenas situações simples (por exemplo, apenas duas células já removeram possibilidades) e me salvou horas por dia quando, infelizmente, eu tinha uma grade que não podia ser resolvida. Porque eu já sabia onde estava o problema.
fonte
A vantagem do TDD é que você descobre como chamar seu código antes de escrever o código real.
Em outras palavras, o TDD ajuda a projetar sua API.
Na minha experiência, isso resulta em melhores APIs, que por sua vez fornecem um código melhor.
Edição: Como eu escrevi, isso foi "na minha experiência", ou seja, ao escrever "projetos do mundo real", mas infelizmente isso é com uma base de código fonte fechada que não posso deixar o mundo ver. Pude entender pelos comentários que isso é o que realmente é pedido, e não apenas uma confirmação da mera existência de tais projetos.
Também descobri - novamente na minha experiência pessoal - que o benefício real aparece quando você entra no modo de manutenção porque os requisitos tendem a mudar. As APIs mais limpas tornaram muito mais fácil expressar os requisitos novos ou alterados no código de teste, e todos os testes tornam muito fácil ver para um futuro mantenedor como o código deve ser chamado e o que pode ser esperado de volta.
Os casos de teste estão executando versões da especificação e permitem ver muito, muito facilmente como chamar sua API. Essa talvez seja a forma mais útil de documentação "HOW" que eu vi até agora (compare com a documentação "WHY", como JavaDoc), pois você tem certeza de que está correta (caso contrário, o teste falharia).
Ultimamente, tive que manter um cliente ftp com script, com um conjunto muito grande de opções que influenciam o funcionamento do aplicativo. O TDD foi introduzido recentemente para novas funcionalidades e o grande conjunto de testes nos permite fazer hotfixes, ao mesmo tempo em que confiamos que a funcionalidade usada ainda funcione conforme o esperado. Em outras palavras, essa transição foi recompensada muito rapidamente.
fonte
A importância de uma abordagem específica para o teste depende de quão crítica é a missão do sistema em desenvolvimento e de quanto outro sistema crítico depende dela. Um script simples de livro de visitas para o seu site dificilmente pode ser considerado de missão crítica, mas se o site em que ele é executado pode potencialmente ser comprometido por um bug que permitia entrada não filtrada no banco de dados e esse site oferece algum serviço vital, então de repente se torna muito mais É importante que o script do livro de visitas seja completamente testado. O mesmo vale também para o código da estrutura / biblioteca. Se você desenvolver uma estrutura com um bug, todos os aplicativos que usam esse recurso da estrutura também terão esse mesmo bug.
O desenvolvimento orientado a testes oferece uma camada extra de segurança quando se trata de testes. Se você escrever os testes ao lado ou mesmo depois do código que deseja testar, haverá um risco real de que os testes sejam errados. Se você escrever todos os testes primeiro, então como o código funciona internamente não poderá influenciar para o que você escreve os testes e, portanto, há menos possibilidade de você escrever inadvertidamente testes que pensam que uma saída incorreta específica está correta.
O desenvolvimento orientado a testes também incentiva seus desenvolvedores a escrever um código fácil de testar, porque eles não querem se esforçar ainda mais! O código fácil de testar tende a ser fácil de entender, reutilizar e manter.
E a manutenção é onde você realmente colherá as recompensas do TDD. A grande maioria do esforço de programação gasto em software está relacionada à manutenção. Isso significa fazer alterações no código ativo para fornecer novos recursos, corrigir bugs ou adaptá-lo a novas situações. Ao fazer essas alterações, você quer ter certeza de que as alterações efetuadas têm o efeito desejado e, mais importante, não causam efeitos inesperados. Se você possui um conjunto de testes completo para o seu código, é fácil verificar se as alterações feitas não estão quebrando outra coisa; se as alterações feitas quebram alguma outra coisa, você pode localizar rapidamente o motivo. Os benefícios são de longo prazo.
Você disse o seguinte em sua pergunta:
Isso parece me sugerir que você não está fazendo testes. Um teste de unidade deve ser extremamente simples, apenas uma sequência de chamadas de método, seguida de uma asserção para comparar o resultado esperado com o resultado real. Eles são feitos para serem simples, porque os erros em seus testes seriam desastrosos e, se você introduzir loops, ramificações ou outro programa, lançará controle no teste, será mais provável que o teste tenha um bug introduzido nele. Se você está gastando muito tempo depurando testes, isso indica que seus testes são muito complicados e você deve simplificá-los.
Se os testes não puderem ser simplificados, apenas esse fato sugere que há algo errado com o código em teste. Por exemplo, se sua classe possui métodos longos, métodos com muitas instruções if / elseif / else ou switch ou um número alto de métodos que possuem interações complexas ditadas pelo estado atual da classe, os testes precisam, por necessidade, ser extremamente complexos para fornecer cobertura completa do código e testar todas as eventualidades. Se sua classe tiver dependências codificadas em outras classes, isso aumentará novamente o número de hoops para os quais você terá que pular para testar efetivamente seu código.
Se você mantiver suas classes pequenas e altamente focadas, com métodos curtos com poucos caminhos de execução e tentar eliminar o estado interno, os testes poderão ser simplificados. E esse é o cerne da questão. Um bom código é inerentemente fácil de testar. Se o código não for fácil de testar, provavelmente há algo errado com ele.
Escrever testes de unidade é algo que beneficia você a longo prazo, e evitá-los é simplesmente armazenar problemas para mais tarde. Você pode não estar familiarizado com o conceito de dívida técnica, mas funciona muito como dívida financeira. Não escrever testes, não comentar códigos, escrever em dependências codificadas e assim por diante são formas de endividar-se. Você "empresta" tempo cortando os cantos desde o início e isso pode ajudá-lo a atingir um prazo apertado, mas o tempo que você economiza no início do projeto é emprestado. Cada dia que passa sem limpar o código, comentá-lo adequadamente ou criar um conjunto de testes custará seu interesse. Quanto mais tempo, mais juros se acumulam. Eventualmente, você descobrirá que seu código se tornou uma bagunça emaranhada na qual você não pode fazer alterações sem desencadear consequências não intencionais.
Você pode pensar em escrever testes de unidade com antecedência e mantê-los atualizados como uma forma de "crédito técnico". Você está investindo tempo no banco gastando-o no início do projeto seguindo as boas práticas. Você ganhará interesse nessa previsão mais tarde, quando chegar à fase de manutenção do projeto. Quando você deseja fazer uma alteração, pode facilmente validar a correção da alteração e se ela não tem efeitos colaterais indesejados, além de obter atualizações rapidamente e sem problemas. Se os erros aparecerem, você poderá adicionar um novo teste de unidade que exerça o erro e, em seguida, corrigir o erro no código. Na próxima execução do teste de unidade, você poderá verificar se o bug foi corrigido e se não causou outros problemas. Além disso, você evitará "regressões",
TL: DR - Sim, eles são uma ajuda do mundo real, mas são um investimento. Os benefícios só se tornam aparentes mais tarde.
fonte
Estou usando TDD com bastante frequência no trabalho. Minha experiência é que o TDD se justifica porque você não paga tempo ou esforço adicional, mas o salva .
Desde que eu uso o TDD, gasto muito menos tempo depurando ou algo assim. Funciona desde o início, porque não considero o código produtivo escrito, desde que os testes não passem.
O controle de qualidade relata muito menos erros, portanto, economizamos custos com a reparação de nosso código após o lançamento. Isso ocorre porque o TDD não permite escrever código sem um teste, portanto a cobertura do código é muito melhor.
Posso executar meu código (produtivo) com muito mais frequência e rapidez, porque não preciso iniciar todo o servidor de aplicativos. Iniciar o teste de unidade é uma ordem de magnitude mais rápida. É claro que só me beneficio quando o teste já é executável quando quero experimentar o código produtivo. Quando os testes são realizados posteriormente, esse benefício é perdido.
Eu faço muito menos testes manuais. Meus colegas que não praticam TDD passam muito tempo clicando no aplicativo até chegarem ao ponto em que o novo código é executado. Teste apenas manualmente uma vez, pouco antes de me comprometer com o controle de versão.
Mesmo se eu usar um depurador, é muito mais rápido depurar a execução de um teste do que de todo o aplicativo.
Talvez você pense em testes de unidade como testes de regressão. Esse é um dos seus objetivos, mas entendê-los como uma ferramenta para o desenvolvimento os torna muito mais valiosos.
fonte
Outra vantagem (além das mencionadas pelas outras pessoas que responderam) aparece quando os testadores de aceitação do cliente, ou (proibidos), os usuários de produção descobrem um bug. Transforme o relatório de erro em um teste no estilo TDD para a classe que parece estar com falha. Veja isso falhar. Consertá-lo. Assista passar. Então você sabe que corrigiu o erro. Essa técnica me salvou horas.
fonte
Bem, eu sei que pessoalmente me beneficio por ser duas vezes mais rápido que meus colegas desenvolvedores e escrever menos da metade dos bugs que eles fazem porque não fazem TDD. Pessoas que provavelmente deveriam ser melhores do que eu mesmo ... supero-as em pelo menos um fator de 2.
Eu não cheguei lá imediatamente. Eu sou muito bom em escrever código fora do manguito e sem arreios. Parecia um grande desperdício escrever toda essa porcaria extra. Mas faz várias coisas, incluindo (não exclusivo):
Um exemplo desse bit posterior é um projeto no qual estou trabalhando no momento em que o lead decidiu repentinamente TOTALMENTE reescrever o protocolo de comunicação usado por praticamente 0 motivo. Eu era capaz de responder a essa mudança em 2 horas, já que a dissociava de todo o resto e já era capaz de trabalhar com total independência até o último empate e integração da etapa de teste. A maioria dos meus colegas de trabalho provavelmente estaria lá por um dia ou mais, porque seu código não seria dissociado e eles mudariam aqui, ali, em todos os lugares ... compilando tudo ... testes de integração ... repita, repita ... Leva muito mais tempo e não é nem de longe tão estável.
fonte
A resposta é sim. Na minha empresa, desenvolvemos um aplicativo C ++ há mais de 20 anos. No ano passado, entramos no TDD em alguns novos módulos e as taxas de defeitos diminuíram significativamente. Gostamos tanto que alguns de nós estão adicionando testes ao código legado toda vez que mudamos algo lá.
Além disso, um módulo inteiro foi concluído do início ao fim, passando pela produção, sem nunca demonstrar um bug (e também é um módulo crítico). Dessa forma, seu desenvolvimento foi mais rápido do que o habitual, porque normalmente o que aconteceria de outra forma é que um módulo fosse "concluído", apenas para retornar 4-5 vezes do teste beta para correção de bugs. Foi uma melhoria substancial, e os desenvolvedores ficaram mais satisfeitos com o novo processo.
Não fiz muito TDD do Rails, mas já fiz muito em C ++, C #, Java e Python. Eu posso lhe dizer que definitivamente funciona. Meu palpite é que você está gastando muito tempo pensando em nomes de teste porque não está confiante o suficiente. Escreva seu teste primeiro, mas deixe sua criatividade fluir ...
Percebi que, quando você realmente entende o TDD, começa a se importar um pouco menos com "Como vou nomear esse teste ... argh!", E você apenas flui com ele, refatorando e adaptando os documentos já escritos. testes para se ajustar à situação atual.
Hora de uma dica
Dica # 1
Portanto, a dica que acho que deve ajudá-lo mais é não se preocupar tanto. Uma das coisas mais bonitas do TDD é que ele oferece coragem para mudar as coisas que já estão escritas e funcionando. E isso inclui os testes.
Dica 2
Comece novos testes de classe com um simples teste "canCreate", apenas para colocar sua mente na direção certa, como em "Ok, estou trabalhando nessa classe agora ... certo".
Em seguida, comece a adicionar mais testes, mas apenas um de cada vez, e verifique se cada teste que você cria é o próximo caso mais simples que lhe vem à cabeça naquele momento (pense nisso por não mais que 30 segundos e depois expire) com o melhor que você tem nesse ponto).
E lembre-se
Não se preocupe em refatorar testes existentes ou mesmo remover testes obsoletos ou redundantes. Poucas pessoas percebem isso, mas no TDD você recebe duas redes de segurança pelo preço de 1. Seus testes são uma rede de segurança para alterações no código de produção, mas seu código de produção também é uma rede de segurança para refatoração dos testes. O relacionamento é mútuo. Na verdade, é um bom caso de acoplamento apertado.
Dê outra chance. E deixe-me recomendar assistir ao Clean Code Casts , especialmente os sobre TDD.
fonte
Exemplo não trivial do mundo real:
Eu tive que escrever uma função de transformação da estrutura de dados. A entrada seria uma estrutura de dados (na verdade, uma estrutura de dados aninhada, semelhante a uma árvore) e a saída seria uma estrutura de dados semelhante. Eu não conseguia visualizar a transformação real em minha mente. Um dos principais benefícios do TDD (para mim, de qualquer maneira) é a execução de etapas do bebê se você não souber como proceder (consulte Kent Becks "TDD por exemplo"). Como eu não sabia para onde isso estava indo, comecei com os casos básicos simples, como entradas vazias ou triviais, e trabalhei até casos mais complicados, até que achei que todos estavam cobertos. No final, eu tinha um algoritmo de trabalho e os testes que o provaram. Os testes não apenas provam que minha implementação está funcionando no momento, como também me impedem de estragar tudo mais tarde.
fonte
Não gosto da ideia de seguir cegamente os conselhos genéricos, porque não acredito que exista uma sugestão única que ajude a maioria dos desenvolvedores a se tornarem mais produtivos e a reduzir defeitos nos aplicativos. Pela minha experiência, quanto mais você se preocupa com a qualidade, mais perde na quantidade de novos recursos entregues. Portanto, o nível de importância que você deseja atribuir à qualidade versus capacidade de entrega dependerá realmente do seu produto e da estratégia atual e, provavelmente, será alguém que decidirá estrategicamente o que é mais importante no momento: robustez ou capacidade de entrega.
Mesmo essa decisão não é preta ou branca. Provavelmente, algumas partes do seu aplicativo devem ser robustas, enquanto outras não precisam. Depois de identificar quais peças devem ter um alto grau de qualidade, você deve se concentrar nelas da perspectiva do teste, pois deseja garantir alta qualidade para essas peças.
Tudo o que eu disse até agora não tem nada a ver com o TDD especificamente no sentido de escrever testes antes da implementação, mas acredito que é importante separar os benefícios de ter testado o código versus escrever os testes primeiro.
Depois de entender os benefícios do teste em si, TDD ou não, você poderá discutir a estratégia de teste do código que deseja que seja coberto pelos testes. Algumas pessoas argumentam que, se você escrever os testes posteriormente, perderá algumas condições em seus testes, mas acredito que você deve avaliar se isso se aplica a você. Certamente não se aplica a mim.
Então, aqui está como isso funciona para mim. Existem basicamente duas situações que me farão escrever testes: ele melhorará apenas a qualidade ou acelerará meu desenvolvimento de algum recurso também. Portanto, uma situação em que escreverei testes é quando não há novos recursos no backlog e posso decidir melhorar o desempenho do aplicativo, simplificar a base de códigos ou aprimorar o conjunto de testes. Outra situação é a necessidade de ter um código de trabalho sólido, em que os bugs tenham um impacto suficientemente grande nos clientes reais. Ainda outro é para testar código complexo que é fácil de quebrar ao trabalhar nele. Como exemplo, há uma classe QueryBuilder em minha base de código que cuida de muitos casos de uso e seria fácil quebrar alguns deles enquanto corrigia um bug ou adicionava um novo recurso.
Finalmente, há o caso em que escrever os testes primeiro me permite escrever um recurso mais rapidamente do que não escrever os testes. Esse QueryBuilder também foi um caso em que essa regra também se aplicou, mas isso não significa que o TDD também será o melhor caminho. Outro exemplo de TDD ajudando na velocidade de desenvolvimento é testar a geração do Excel, por exemplo, enquanto no aplicativo real você pode precisar executar várias etapas sempre que quiser testar alguma condição específica da geração. Ou se você precisar criar alguns registros para testar um recurso e for difícil ou impossível excluí-los manualmente depois de testar o código manualmente.
Portanto, se for mais fácil reproduzir as etapas para executar algum código em desenvolvimento programaticamente (por meio de testes), faça isso. Mas se escrever o teste é mais complicado do que testá-lo manualmente, você deve decidir se é hora de se concentrar na qualidade ou se há muitos pedidos em sua lista de pendências e alguém da empresa provavelmente o conhecerá melhor e permitirá que você saiba onde você deve se concentrar de acordo com a necessidade atual e a estratégia da empresa.
Em um mundo ideal, todo o código é testado, mas não se pode fingir que não há uma troca e assumir que o TDD é sempre o melhor e único caminho. Como em todas as melhores práticas existentes, você deve sempre se concentrar no que é melhor para a empresa em que trabalha e não no que é melhor para você. Depois de se tornar autônomo, você pode decidir executar o TDD o tempo todo, se achar que esse é o melhor caminho. Se sua empresa acredita que todo o código deve ser testado, você deve escrever testes para todo o código que escrever. Mas, na maioria dos casos, é necessário ter uma visão geral e entender os compromissos antes de tomar qualquer decisão. Desculpe, mas essa não é uma ciência exata e não há uma resposta fácil (ou difícil) que sirva para todos que você deve seguir sempre.
Da mesma forma que com os padrões de design. Entenda como eles funcionam e por que foram criados, que tipo de problemas eles resolvem e quais são suas desvantagens. Compreender o raciocínio é muito mais importante do que lembrar as soluções propostas. O que hoje é uma operação cara pode ser facilmente alcançado amanhã com outras tecnologias. Se a premissa de alguma solução bem estabelecida não for mais válida, provavelmente a solução não será mais a melhor a ser usada. Quando os requisitos, a tecnologia disponível ou a estratégia da empresa forem alterados, você sempre deve reavaliar sua caixa de ferramentas e, quando isso acontecer, precisa entender por que você escolheu cada caminho em primeiro lugar, em vez de aceitá-los como as melhores opções.
fonte