TDD vs. Teste de unidade [fechado]

117

Minha empresa é relativamente nova em testes de unidade de nosso código. Tenho lido sobre TDD e testes de unidade há algum tempo e estou convencido de seu valor. Tentei convencer nossa equipe de que TDD vale o esforço de aprender e mudar nossa mentalidade sobre como programamos, mas é uma luta. O que me leva à (s) minha (s) pergunta (s).

Existem muitos na comunidade TDD que são muito religiosos quanto a escrever o teste e depois o código (e eu estou com eles), mas para uma equipe que está lutando com o TDD, um acordo ainda traz benefícios adicionais?

Provavelmente, posso conseguir que a equipe escreva testes de unidade depois que o código for escrito (talvez como um requisito para fazer o check-in do código) e suponho que ainda há valor em escrever esses testes de unidade.

Qual é a melhor maneira de trazer uma equipe em dificuldades para o TDD? E, se isso falhar, ainda vale a pena escrever testes de unidade, mesmo que seja depois de o código ser escrito?

EDITAR

O que eu deduzi disso é que é importante para nós começarmos os testes de unidade, em algum ponto do processo de codificação. Para aqueles na equipe que pegaram o conceito, comece a se mover mais em direção ao TDD e aos testes. Obrigado pela contribuição de todos.

ACOMPANHAMENTO

Recentemente, iniciamos um novo pequeno projeto e uma pequena parte da equipe usou TDD, o restante escreveu testes de unidade após o código. Depois de encerrarmos a parte de codificação do projeto, aqueles que escreveram testes de unidade após o código ficaram surpresos ao ver os codificadores TDD já prontos e com um código mais sólido. Foi uma boa maneira de conquistar os céticos. Ainda temos muitas dores de crescimento pela frente, mas a batalha de vontades parece ter acabado. Obrigado a todos que deram conselhos!

Walter
fonte
1
Você pode achar este tópico útil: stackoverflow.com/questions/917334/should-i-use-tdd
Randolpho
29
1 para o FOLLOW UP. Essa é uma ótima história.
Carl Manaster,

Respostas:

76

Se a equipe está se debatendo na implementação de TDD, mas eles não estavam criando nenhum Teste de Unidade antes ... então comece criando Testes de Unidade depois que seu código for escrito. Mesmo os testes de unidade escritos após o código são melhores do que nenhum teste de unidade!

Assim que eles forem proficientes em Teste de Unidade (e tudo o que vem com ele), você pode trabalhar para fazê-los criar os testes primeiro ... e depois o código.

Justin Niessner
fonte
3
Isso é correto, a equipe não estava criando nenhum teste de unidade antes. Isso parece um bom ponto de partida para o TDD completo.
Walter
Não posso concordar mais com isso. Na verdade, acho que escrevi algo semelhante para uma pergunta semelhante há alguns meses. Onde está ... Aah! stackoverflow.com/questions/917334/should-i-use-tdd/…
Randolpho
27

Ainda vale a pena escrever os testes de unidade depois que o código for escrito. Acontece que às vezes é mais difícil porque seu código não foi projetado para ser testável e você pode tê-lo complicado demais.

Acho que uma boa maneira pragmática de trazer uma equipe para o TDD é fornecer o método alternativo de "teste durante o desenvolvimento" no período de transição ou, possivelmente, a longo prazo. Eles devem ser encorajados a usar seções de código TDD que pareçam naturais para eles. No entanto, em seções de código que parecem difíceis de abordar primeiro o teste ou ao usar objetos que são predeterminados por um processo A&D não ágil, os desenvolvedores podem ter a opção de escrever uma pequena seção do código e, em seguida, escrever testes para cobrir isso código e repetindo este processo. Escrever testes de unidade para algum código imediatamente após escrever esse código é melhor do que não escrever nenhum teste de unidade.

Kaleb Brasee
fonte
16

Na minha humilde opinião, é melhor ter 50% de cobertura de teste com "código primeiro, teste depois" e uma biblioteca 100% concluída, do que 100% de cobertura de teste e 50% de biblioteca concluída com TDD. Depois de um tempo, seus colegas desenvolvedores provavelmente acharão divertido e educativo escrever testes para todo o publiccódigo que escreverem, de modo que o TDD se infiltrará em sua rotina de desenvolvimento.

Asbjørn Ulsberg
fonte
3
Eu entendo sua sugestão, mas estou desconfiado sobre a "biblioteca 100% concluída" com cobertura de teste de 50% ... só pela minha experiência que cada pedaço de código que não é coberto por alguns testes contém pelo menos um bug. Ou, colocando de outra forma: as pessoas tendem a evitar escrever testes para código que realmente se beneficiariam de mais alguns testes :)
Aaron Digulla
2
Bem, outra forma de colocar isso é código com bugs que foi lançado é melhor do que código perfeito que definha para sempre. Obviamente existem exceções tosse NASA tosse , mas para a maior parte, obter o seu código lá fora. Você ainda pode adicionar testes após seu lançamento.
jcdyer
3
O que você quer dizer com "biblioteca 100% concluída". Você o considera completo se houver bugs? Você não inclui testado na definição de pronto?
Pascal Thivent
10
sendo testado não é uma condição suficiente para estar livre de erros
fa.
2
A cobertura de teste medida pelas ferramentas de cobertura de teste é uma faca de dois gumes. Se for alcançado invocando todos os métodos no IUT, mas os testes não estão realmente testando o comportamento que provavelmente será interrompido, os desenvolvedores e outras partes interessadas terão uma falsa sensação de segurança. Todo o movimento em direção ao TDD dentro de sua organização pode explodir na sua cara quando o comportamento crítico não é testado, mas você tem 100% de cobertura de teste. O mais importante não é a quantidade, mas a qualidade.
Doug Knesek
12

Acabei de ler isto em um calendário: "Cada regra, executada ao máximo, torna-se ridícula ou mesmo perigosa." Portanto, minha sugestão é não ser religioso a respeito. Cada membro de sua equipe deve encontrar um equilíbrio entre o que eles consideram "certo" quando se trata de testes. Dessa forma, todos os membros de sua equipe serão mais produtivos (em vez de, digamos, pensar "por que tenho que escrever este teste sti **** ??").

Portanto, alguns testes são melhores do que nenhum, os testes após o código são melhores do que poucos testes e os testes antes do código são melhores do que depois. Mas cada passo tem seus próprios méritos e você não deve desaprovar nem mesmo pequenos passos.

Aaron Digulla
fonte
"o que eles sentem" Como desenvolvedor, não me lembro de jamais ter tido qualquer desejo (correto) de fazer qualquer teste de unidade automatizado por conta própria, apenas os manuais. Eu não acho que estou sozinho com falta de entusiasmo com os testes
Gennady Vanin Геннадий Ванин
@ vgv8: Isso significa que seus testes não o ajudam. Pode haver uma série de razões para isso; Eu sugiro cavar mais fundo. Qualquer projeto se beneficia de bons testes e sofre com os ruins. Você notará quando começar a escrever bons testes e, a partir desse momento, nada será capaz de impedi-lo de escrever mais.
Aaron Digulla
o que parece certo para mim, é um nível de teste que cobre o que as unidades de programação devem fazer, e de um nível funcional: o que os usuários estão fazendo normalmente, o que inclui os resultados ruins que alguns chamam de "bugs relatados". Se um bug for confirmado, pelo menos um teste é escrito! quanto maior o projeto e quanto maior a equipe, mais isso é importante.
DaFi4 de
12

TDD é sobre design! Portanto, se você usá-lo, terá a certeza de ter um design testável de seu código, tornando mais fácil escrever seus testes. Se você escrever testes depois que o código for escrito, eles ainda serão valiosos, mas, IMHO, você estará perdendo tempo, pois provavelmente não terá um design testável.

Uma sugestão que posso dar para tentar convencer sua equipe a adotar o TDD é usar algumas das técnicas descritas em Fearless Change: Patterns for Introducing New Ideas, de Mary Lynn Manns e Linda Rising .

Diego dias
fonte
3
+1: Desenvolvimento Orientado a Testes significa que o design foi conduzido por considerações de teste.
S.Lott
+1. Os testes de unidade posteriores obviamente irão ajudá-lo, mas você perderia os benefícios de ter um "design testável" se não escrever testes de unidade antecipadamente.
Noufal Ibrahim
9

Se eles são novos em testes do que o IMO, comece testando o código que já foi escrito e lentamente passe a escrever testes primeiro. Como alguém que está tentando aprender TDD e é novo em testes de unidade, achei meio difícil fazer um 180 completo e mudar minha mentalidade para escrever testes antes do código, então a abordagem que estou fazendo é uma mistura de 50-50 ; quando eu sei exatamente como o código vai se parecer, vou escrever o código e, em seguida, escrever um teste para verificá-lo. Para situações nas quais não tenho total certeza, começarei com um teste e retrocederei.

Lembre-se também de que não há nada de errado em escrever testes para verificar o código, em vez de escrever código para satisfazer os testes. Se sua equipe não quer seguir a rota do TDD, não force isso a eles.

Wayne Molina
fonte
6

Provavelmente, posso conseguir que a equipe escreva testes de unidade depois que o código for escrito (talvez como um requisito para fazer o check-in do código) e suponho que ainda há valor em escrever esses testes de unidade.

Não há absolutamente nenhuma dúvida sobre o fato de que há valor no código testado por unidade (independentemente de quando os testes foram escritos) e eu incluo "o código é testado por unidade" na "Definição de Concluído". As pessoas podem usar TDD ou não, desde que testem.

Em relação ao controle de versão, gosto de usar " ramos de desenvolvimento " com uma política de teste de unidade (ou seja, o código compila e constrói, todos os testes de unidade passam). Quando os recursos são concluídos, eles são publicados das ramificações de desenvolvimento para o tronco. Em outras palavras, o ramo de tronco é o " ramo concluído " (sem lixo no tronco!) E tem uma política de entrega (pode liberar a qualquer momento) que é mais estrita e inclui mais coisas do que "unidade testada".

Pascal Thivent
fonte
4

Isso é algo que sua equipe terá que ter seus próprios sucessos antes de começar a acreditar. Vou reclamar sobre minha epifania nUnit para quem se importa:

Há cerca de 5 anos, descobri o nUnit ao trabalhar em um projeto. Tínhamos quase concluído a V1.0 e criei alguns testes apenas para experimentar esta nova ferramenta. Tivemos muitos bugs (obviamente!) Porque éramos uma nova equipe, com um prazo apertado, grandes expectativas (parece familiar?) Etc. De qualquer forma, colocamos o 1.0 e começamos no 1.1. Nós reorganizamos a equipe um pouco e eu tenho 2 desenvolvedores designados para mim. Eu fiz uma demonstração de 1 hora para eles e disse-lhes que tudo o que escrevíamos tinha que ter um caso de teste com ele. Constantemente corremos "atrás" do resto da equipe durante o ciclo de desenvolvimento de 1.1 porque estávamos escrevendo mais código, os testes de unidade. Acabamos trabalhando mais, mas aqui está a recompensa - quando finalmente começamos os testes, tínhamos exatamente 0 bugs em nosso código. Ajudamos todo mundo a depurar e reparar seus bugs. No post mortem, quando a contagem de bugs apareceu,

Não sou burro o suficiente para pensar que você pode testar o seu caminho para o sucesso, mas acredito verdadeiramente quando se trata de testes de unidade. O projeto adotou o nUnit e logo se espalhou para a empresa para todos os projetos .Net como resultado de 1 sucesso. O período total para o nosso lançamento V1.1 foi de 9 semanas de desenvolvimento, então definitivamente NÃO foi um sucesso noturno. Mas, a longo prazo, provou ser um sucesso para nosso projeto e para a empresa para a qual construímos soluções.

Sem Reembolsos Sem Devoluções
fonte
“O projeto adotou o nUnit e logo se espalhou para a empresa para todos os projetos .Net” E o que fazer se um produto / projeto tiver código C #, Java, C ++, SQL Server?
Gennady Vanin Геннадий Ванин
Não sei ... Encontrar uma maneira de testar todos os componentes antes de implantá-los na produção? O teste de unidade é apenas uma faceta de um plano de teste abrangente antes de ir ao ar. Você pode abrir buracos em qualquer cenário.
Sem Reembolsos Sem Devoluções
4

Não há dúvida de que o teste (primeiro, durante ou mesmo depois) salvará seu bacon e aumentará sua produtividade e confiança. Eu recomendo adotá-lo!

Eu estava em uma situação semelhante, porque eu era um desenvolvedor "novato", muitas vezes ficava frustrado ao trabalhar em um projeto de equipe pelo fato de que uma contribuição havia quebrado a compilação. Não sabia se a culpa era minha ou mesmo em alguns casos, de quem era a culpa. Mas eu estava mais preocupado em fazer a mesma coisa com meus colegas desenvolvedores. Essa constatação motivou então a adoção de algumas estratégias de TDD. Nossa equipe começou com jogos bobos e regras, como você não pode ir para casa até que todos os seus testes passem, ou se você enviar algo sem um teste, então você tem que comprar "cerveja / almoço / etc" para todos e isso torna o TDD mais divertido.

Dai Bok
fonte
3

Um dos aspectos mais úteis do teste de unidade é garantir a correção contínua do código que já está funcionando. Quando você puder refatorar à vontade, deixe um IDE lembrá-lo dos erros de tempo de compilação e, em seguida, clique em um botão para permitir que seus testes identifiquem quaisquer erros de tempo de execução em potencial - às vezes chegando em blocos de código anteriormente triviais, então acho que você encontrará sua equipe começando a apreciar TDD. Portanto, começar com o teste do código existente é definitivamente útil.

Além disso, para ser franco, aprendi mais sobre como escrever código testável tentando testar o código escrito do que começando com TDD. Pode ser muito abstrato no início se você estiver tentando pensar em contratos que irão cumprir o objetivo final e permitir testes. Mas quando você olha para o código e pode dizer "Este singleton aqui estraga completamente a injeção de dependência e torna o teste impossível", você começa a desenvolver uma apreciação de quais padrões tornam sua vida de teste mais fácil.

David Berger
fonte
3

Bem, se você não escreve os primeiros testes, não é "Test Driven", é apenas um teste. Ele tem benefícios em si mesmo e se você já tem uma base de código adicionando testes, certamente é útil, mesmo que não seja TDD, mas apenas teste.

Escrever testes primeiro é focar no que o código deve fazer antes de escrevê-lo. Sim, você também faz um teste fazendo isso e é bom, mas alguns podem argumentar que nem mesmo é o ponto mais importante.

O que eu faria é treinar a equipe em projetos de brinquedo como esses (veja Coding Dojo, Katas) usando TDD (se você conseguir que programadores TDD experientes participem desse workshop, seria ainda melhor). Quando virem os benefícios, usarão o TDD para o projeto real. Mas enquanto isso não os force, se eles não virem o benefício não farão direito.

Kriss
fonte
3

Se você tem sessões de design antes de escrever o código ou precisa produzir um documento de design, você pode adicionar Testes de Unidade como o resultado tangível de uma sessão.

Isso pode servir como uma especificação de como seu código deve funcionar. Incentive o emparelhamento na sessão de design, para que as pessoas falem sobre como algo deve funcionar e o que deve ser feito em determinados cenários. Quais são os casos extremos, com casos de teste explícitos para eles para que todos saibam o que acontecerá se receber um argumento nulo, por exemplo.

Um aparte, mas o BDD também pode ser de interesse

danswain
fonte
Eu não conhecia o BDD. Vou ter que ler mais sobre isso.
Walter
3

Você pode encontrar um pouco de tração mostrando um exemplo ou dois em que o TDD resulta em menos código sendo escrito - porque você escreve apenas o código necessário para fazer o teste passar, é mais fácil resistir à tentação de dourar ou se envolver em YAGNI. O código que você não escreve não precisa ser mantido, refatorado, etc., então é uma "economia real" que pode ajudar a vender o conceito de TDD.

Se você puder demonstrar claramente o valor em termos de tempo, custo, código e bugs economizados, poderá achar que é mais fácil vender.

Michael Nash
fonte
2

Começar a construir classes de teste JUnit é a maneira de começar, para o código existente é a única maneira de começar. Na minha experiência, é muito útil criar classes de teste para o código existente. Se a gerência achar que isso vai investir muito tempo, você pode propor a gravação de classes de teste apenas quando for descoberto que a classe correspondente contém um bug ou precisa de uma limpeza.

Para o processo de manutenção, a abordagem para fazer a equipe ultrapassar os limites seria escrever testes JUnit para reproduzir bugs antes de corrigi-los, ou seja,

  • bug é relatado
  • criar classe de teste JUnit se necessário
  • adicione um teste que reproduza o bug
  • conserte seu código
  • execute o teste para mostrar que o código atual não reproduz o bug

Você pode explicar que, ao "documentar" bugs dessa forma, você evitará que eles voltem mais tarde. Esse é um benefício que a equipe pode experimentar imediatamente.

rsp
fonte
2

Eu fiz isso em muitas organizações e descobri que a melhor maneira de iniciar e seguir o TDD é configurar a programação em pares. Se você tem outra pessoa com quem pode contar que conhece TDD, então vocês dois podem se separar e formar pares com outros desenvolvedores para fazer alguma programação em pares usando TDD. Se não, treinaria alguém que o ajudasse a fazer isso antes de apresentá-lo ao resto da equipe.

Um dos maiores obstáculos com o teste de unidade e especialmente o TDD é que os desenvolvedores não sabem como fazê-lo, então não conseguem ver como vale a pena gastar seu tempo. Além disso, quando você começa, é muito mais lento e não parece trazer benefícios. Ele só está realmente lhe proporcionando benefícios quando você é bom nisso. Ao configurar sessões de programação emparelhadas, você pode fazer com que os desenvolvedores aprendam rapidamente e se tornem bons nisso mais rápido. Além disso, eles serão capazes de ver benefícios imediatos enquanto vocês trabalham juntos.

Essa abordagem funcionou muitas vezes para mim no passado.

John Sonmez
fonte
2

Uma maneira poderosa de descobrir os benefícios do TDD é fazer uma reescrita significativa de alguma funcionalidade existente, talvez por motivos de desempenho. Ao criar um conjunto de testes que fazem um bom trabalho cobrindo toda a funcionalidade do código existente, isso dá a você a confiança para refatorar o que quiser com total confiança de que suas alterações são seguras.

Observe que, neste caso, estou falando sobre testar o design ou contrato - testes de unidade que testam os detalhes de implementação não serão adequados aqui. Mas, novamente, o TDD não pode testar a implementação por definição, pois eles devem ser escritos antes da implementação.

Chris Welsh
fonte
1

TDD é uma ferramenta que os desenvolvedores podem usar para produzir um código melhor. Acontece que eu sinto que o exercício de escrever código testável é tão valioso quanto os próprios testes. Isolar o IUT (Implementation Under Test) para fins de teste tem o efeito colateral de desacoplar seu código.

O TDD não é para todos e não há mágica que levará uma equipe a escolher fazê-lo. O risco é que os escritores de teste de unidade que não sabem o que vale a pena testar escrevam muitos testes de baixo valor, que serão carne de canhão para os céticos do TDD em sua organização.

Eu normalmente torno os Testes de Aceitação automatizados não negociáveis, mas permito que os desenvolvedores adotem o TDD como lhes convém. Eu tenho meus TDDers experientes treinando / orientando o resto e "provando" a utilidade pelo exemplo durante um período de muitos meses.

Isso é tanto uma mudança social / cultural quanto técnica.

Doug Knesek
fonte