O desenvolvimento orientado a testes (TDD) realmente beneficiou um projeto do mundo real?


36

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?


1
Isso me salvou mais tempo: porque somos muitas pessoas no mesmo projeto, porque as atualizações das gemas podem ter alguns efeitos colaterais desconhecidos, porque se tudo estiver verde e eu tiver um bug, sei onde não vale a pena encontrar sua raiz.
apneadiving 12/12/12


3
butunclebob.com/ArticleS.UncleBob.JustTenMinutesWithoutAtest Aqui está uma história do tio Bob sobre uma situação do mundo real que ele enfrentou.
Hakan Deryal

1
No começo, pensei que os testes seriam ótimos para saber onde os bugs não estavam, mas aprendi rapidamente, como @Hakan apontou no artigo do tio Bob, geralmente ocorre porque você perdeu um caso de teste. O que torna esses testes bastante inúteis. De fato, esse artigo afirma que o desenvolvimento incremental é o que funciona.
31412 James

1
"Acho que gasto substancialmente mais tempo tentando depurar meus testes para que eles digam o que eu realmente quero dizer do que depurando código real" : mas isso não é exatamente o benefício? Depois, você ainda acha que passa muito tempo depurando o "código real"? Os defensores do TDD argumentam que o tempo gasto para descobrir uma maneira de tornar seu código testável é na verdade um esforço de design que beneficiará seu código.
Andres F.

Respostas:


26

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 .

AbstratoO TDD (Test-driven Development) é uma prática de desenvolvimento de software usada esporadicamente há décadas. Com essa prática, um engenheiro de software alterna minuto a minuto entre a gravação de testes de unidade com falha e a gravação do código de implementação para passar nesses testes. O desenvolvimento orientado a testes ressurgiu recentemente como uma prática crítica capacitadora de metodologias ágeis de desenvolvimento de software. No entanto, poucas evidências empíricas apóiam ou refutam a utilidade dessa prática em um contexto industrial. Os estudos de caso foram conduzidos com três equipes de desenvolvimento da Microsoft e uma da IBM que adotaram o TDD. Os resultados dos estudos de caso indicam que a densidade de defeitos de pré-liberação dos quatro produtos diminuiu entre 40% e 90% em relação a projetos semelhantes que não usavam a prática de TDD. Subjetivamente,

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).


2
Em uma discussão sobre o Meta.StackOverflow , você poderia adicionar informações adicionais do documento que possam ser relevantes para o solicitante e também para as futuras pessoas que encontrarem essa pergunta?
Thomas Owens

2
@ThomasOwens, pensei que a conclusão ("TDD adiciona 15 a 35% do tempo de desenvolvimento em troca de uma redução de 40 a 90% na densidade de defeitos") foi a informação adicional que responde à pergunta original <_ <

4
Esta postagem foi sinalizada por não conter informações suficientes. Ainda não li o jornal, mas parece que as pessoas querem mais informações adicionadas ao corpo da resposta. Talvez discuta mais sobre as condições específicas usadas no estudo?
Thomas Owens

99% de todas as estatísticas são fictícias. : P Mas realmente é sobre o contexto. Em que tipo de equipe? Um grande bando de desenvolvedores Java medíocres? Sim, eu acredito que o TDD os ajudaria com a produtividade. Mas isso não significa que ter as habilidades de arquitetura para projetar e valorizar códigos robustos em primeiro lugar não os ajudaria ainda mais e, na IMO, o TDD do primeiro teste poderia muito facilmente impedir que aprendessem a fazer isso corretamente. E sim, ouvi dizer que isso ajuda no design. Até certo ponto, provavelmente é verdade, mas ainda é um erro de reconhecimento e um band-aid para o problema raiz da IMO.
precisa

seria bom se mais alguns documentos fossem listados na Biblioteca Digital ACM ou se fossem adicionadas as palavras-chave a serem usadas no mecanismo de pesquisa. precisamos de mais rigor em nossas respostas ao falar sobre ágeis e TDD
Rudolf Olah

16

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.

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.

Mas quão bem ele funciona em projetos reais?

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.


9

Nós nos beneficiamos maciçamente.

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


3
"Voltaremos e resolveremos esses problemas eventualmente". - provavelmente não ... não, a menos que a puta lhe dê um tapa com algum inseto horrendo. Essas áreas se tornarão a espinha dorsal de todo o resto e guiarão todo o projeto a avançar, porque ninguém desejará investir os recursos para refazê-los e ninguém desejará forçar qualquer mudança que possa fazer algo ruim. Acontece sempre: P
Edward Strange

Você está adivinhando, quando estou lhe dizendo o que está acontecendo dentro da empresa. Quando confirmamos, podemos confirmar código com 70% de cobertura. Isso aumenta constantemente com o lead do IC. Dentro de meses, o limite mínimo de cobertura do código será aumentado em uma pequena porcentagem. Depois disso, não haverá escolha, a não ser introduzir mais testes.
CodeART 12/12/12

7

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.


2
Eu sinto que esta pergunta está cutucando mais no teste primeiro, implemente depois na estratgia. Obviamente, os testes são úteis para depurar aplicativos, onde seria tedioso testar todas as possibilidades.
Alex Hope O'Connor

6

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.


8
Essa resposta parece estar inteiramente ao lado da pergunta, pois ela exige exemplos do mundo real . Mas como três pessoas pensaram "esta resposta é útil", devo estar perdendo alguma coisa.

3
Concordo, mas me falta a reputação de voto negativo. Este é apenas o "TDD fornece melhores resultados", sem exemplo de um projeto derivado do TDD em manutenção para fazer backup da resposta que eu queria evitar.
12124 James

Agora que várias pessoas concordaram comigo, ouso votar. Algum incentivador ou o autor, por favor, avance e diga-nos por que essa é uma boa resposta?

@ delnan "Atrevo-me a voto negativo" - uma escolha interessante de palavras. A edição caiu no seu gosto?

Sim, removi meu voto negativo agora que percebi.

5

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:

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 (rspec neste caso).

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.


1
Eu comprei essa lógica meses atrás. Eu amo a idéia por trás do TDD, estou apenas achando a realidade um pouco desconcertante. Além disso, percebo que, mesmo aqui, não há exemplos reais em que a herança de um projeto baseado em TDD tenha valido a pena. Você realmente voltou para uma base de código antiga que tinha vários testes de unidade e valeu a pena.
James

Infelizmente não, porque mais ninguém parece criar testes de unidade, pelo menos não em nenhum código que eu herdei de desenvolvedores anteriores. Minha vida teria sido muito mais fácil se eles tivessem. Eu sugiro que você verifique o livro no link, que tem exemplos do mundo real, embora seja para PHP e não para Rails. amazon.com/...
GordonM

Sou um grande crítico do uso geral, mas não culpo ninguém por usar essa abordagem em um sistema financeiro incorporado ou crítico.
precisa

4

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.


Qualidade é grátis!
MathAttack # 15/12

2
Má qualidade é cara!
Wolfgang

3

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.


2

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):

  • Forçar um design voltado para dissociação e reutilização (tudo precisa ser reutilizado em um teste de unidade).
  • Fornecer uma plataforma para desenvolver código em pequenos blocos e módulos, para que eu não precise entender e concluir tudo antes de executar um tipo de teste simples "Será que ele compila e recebe entrada"?
  • Fornecer uma plataforma de teste rápida para fazer alterações quando as pessoas exigem alterações nos recursos que eu não esperava.

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.


2

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.


1

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.


-1

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.


isso nem tenta responder à pergunta: "finalmente temos algum exemplo mostrando que a recompensa é real? Alguém realmente herdou ou voltou ao código que foi projetado / desenvolvido com o TDD e tem um conjunto completo de testes de unidade e realmente sentiu uma recompensa? "
gnat 27/05

1
Responde, mas como você não compartilha da minha opinião, você dá -1 a ela :) Basicamente, qualquer pessoa que não tente mostrar os valores do TDD dará uma resposta indesejada do seu ponto de vista;) Deixe-me adivinhar . Você é um evangelizador TDD, certo? :) A propósito, a verdadeira pergunta do autor é se o TDD compensa ou não. Você não precisa praticar o TDD para responder a isso. O Fortran é recompensado por escrever aplicativos da web? Você já tentou antes de responder?
Rosenfeld 27/05

Eu não tenho uma opinião sobre o TDD e não uso votos como gostos / desgostos (é um site de perguntas e respostas, não um Facebook). Por minha leitura, esta "resposta" simplesmente não aborda a pergunta feita em tudo, nem positivamente nem negativamente
mosquito

Do meu ponto de vista, essa não é uma questão técnica, como "como faço para X com o nginx?". Existem respostas corretas para perguntas como essa, mas não para perguntas qualitativas e subjetivas como essa, quando o autor realmente deseja conhecer as opiniões dos outros sobre TDD e se vale a pena. Essa foi a minha tentativa de mostrar meu ponto de vista. Não tenho ideia de como uma resposta poderia ser a certa, pois todas parecem apenas opiniões pessoais para mim. Você não pode medir efetivamente se o TDD vale ou não. Qualquer artigo que tente fazer isso é fundamentalmente errado.
Rosenfeld 27/05

"Este site é todo tour, obtendo respostas . Não é um fórum de discussão ..."
gnat
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.