O teste de unidade ou o desenvolvimento orientado a testes vale a pena?

48

Minha equipe no trabalho está migrando para o Scrum e outras equipes estão começando a desenvolver desenvolvimento orientado a testes usando testes de unidade e testes de aceitação do usuário. Gosto dos UATs, mas não sou vendido em testes de unidade para desenvolvimento orientado a testes ou desenvolvimento orientado a testes em geral.

Parece que escrever testes é um trabalho extra, dá às pessoas uma muleta quando escrevem o código real e pode não ser eficaz com muita frequência.

Entendo como os testes de unidade funcionam e como escrevê-los, mas alguém pode argumentar que é realmente uma boa ideia e vale o esforço e o tempo?

Além disso, existe algo que torna o TDD especialmente bom para o Scrum?

Owen Johnson
fonte
27
Se você deseja ter certeza de que o seu software falha com frequência, é mais ou menos completamente impossível de manter e deve ser substituído antes que esteja pronto para a produção; então eu sugiro que você dispense totalmente o teste de unidade e nunca tome tempo para aprender TDD.
Dawood diz que restabelece Monica
3
Pense no desejo / necessidade de um refatorador. Você estaria mais confiante em fazer a refatoração (de qualquer magnitude) com ou sem um conjunto abrangente de testes de unidade para capturá-lo quando você inadvertidamente quebrou alguma coisa?
Marjan Venema
2
"Dá às pessoas uma muleta quando escrevem código real"? A maioria das práticas recomendadas não pode ser descrita dessa maneira?
user16764
4
@ DavidWallace: Esse é o problema de desenvolvedores incompetentes, não a falta de TDD. Além disso, mesmo quando o TDD é usado extensivamente, ele oferece zero garantias de que a alteração feita não quebra nada.
20/12
6
@NimChimpsky: Eu não tenho nenhuma negatividade em relação ao TDD, apenas não estou seguindo o hype. Tem seus lados positivos e negativos também. A falsa sensação de segurança é uma delas.
Coder

Respostas:

68

Resposta curta: Absolutamente positivo.

Resposta longa: Os testes de unidade são uma das práticas mais importantes que tento influenciar no meu local de trabalho (banco grande, negociação de câmbio). Sim, eles são trabalho extra, mas é um trabalho que retribui repetidamente. Os testes de unidade automatizados não apenas ajudam a executar o código que você está escrevendo e, claro, a verificar suas expectativas, mas também agem como uma espécie de cão de guarda para futuras mudanças que você ou outra pessoa possa fazer. A quebra do teste ocorrerá quando alguém alterar o código de maneiras indesejáveis. Penso que o valor relativo dos testes de unidade diminui em correlação com o nível de mudança e crescimento esperado em uma base de código, mas a verificação inicial do que o código faz valer a pena, mesmo onde a mudança esperada é baixa. O valor do teste de unidade também depende do custo dos defeitos. Se o custo (em que custo é perda de tempo / dinheiro / reputação / esforço futuro) de um defeito for zero, o valor relativo de um teste também será zero; no entanto, isso quase nunca ocorre em um ambiente comercial.

Geralmente, não contratamos mais pessoas que não criam rotineiramente testes de unidade como parte de seu trabalho - é apenas algo que esperamos, como aparecer todos os dias. Eu não vi uma análise de custo-benefício pura de ter testes de unidade (alguém se sente à vontade para me indicar um), no entanto, posso dizer por experiência que em um ambiente comercial, ser capaz de provar que o código funciona em um sistema importante e importante vale a pena . Também me permite dormir melhor à noite, sabendo que o código que eu escrevi provavelmente funciona (até um certo nível) e, se ele mudar, alguém será alertado sobre qualquer efeito colateral inesperado causado por uma compilação quebrada.

Desenvolvimento orientado a teste, na minha opinião, não é uma abordagem de teste. Na verdade, é uma abordagem / prática de design, com a saída sendo o sistema de trabalho e um conjunto de testes de unidade. Sou menos religioso sobre essa prática, pois é uma habilidade bastante difícil de desenvolver e aperfeiçoar. Pessoalmente, se estou construindo um sistema e não tenho uma ideia clara de como ele funcionará, empregarei o TDD para me ajudar a encontrar meu caminho no escuro. No entanto, se estou aplicando um padrão / solução existente, normalmente não o faço.

Na ausência de uma prova matemática para você de que faz sentido escrever testes de unidade, encorajo você a experimentá-lo por um longo período e experimentar os benefícios.

rupjones
fonte
5
O que eu gostaria de acrescentar é que o teste de unidade também faz você pensar no seu design de interface. Quando você chega a uma parte em que pensa "como faço para testar métodos particulares?", Você sabe que provavelmente é a sua interface que está errada.
TC1
11
"Convido você a experimentá-lo por um longo período e experimentar os benefícios por si mesmo." Apenas tentar uma vez foi suficiente para mim, os benefícios pareciam óbvios.
NimChimpsky
11
+1 em "Geralmente, não contratamos mais pessoas que não criam rotineiramente testes de unidade como parte de seu trabalho". Recentemente, tive que rejeitar um candidato que, entre outras deficiências, proclamou veementemente que ele não gosta de escrever testes automáticos porque é uma perda de tempo e ele mesmo pode testar o código.
ftr 21/03
4
você não pode provar que um código não trivial funciona de maneira relevante apenas usando testes automatizados. Com testes automatizados, você só pode provar que o código passa nos testes - se os testes abrangem 100% dos seus casos de uso, você provavelmente tem seu "certo nível", mas isso ainda não significa que o código "provavelmente funcione". Para ter uma possibilidade real, você precisa en.wikipedia.org/wiki/Formal_verification - como tal, você está usando o termo "provavelmente" errado aqui.
vaxquis
11
@vaxquis Sim, você está estritamente correto sobre o uso do termo prova. Mas aposto que a presença de testes (ou a prática do TDD) é uma evidência melhor de um sistema operacional do que a ausência de testes.
rupjones
16

Os erros encontrados anteriormente são mais baratos de corrigir do que os erros encontrados posteriormente. O TDD ajuda a verificar a correção do seu sistema. Você investe um pouco mais antecipadamente, mas recupera mais tarde. O gráfico é um pouco exagerado, mas mostra bem a ideia.

insira a descrição da imagem aqui

Fonte da imagem

Martin Wickman
fonte
O que você quer dizer com tradicional ? Algo que não é TDD?
Giorgio
Parece que esse gráfico não se baseia em estatísticas reais, mas representa apenas a experiência de uma única pessoa que escreveu esta entrada do Blog em 2006. Não que eu esteja dizendo que está totalmente errado, mas a realidade é muito mais complicada.
Doc Brown
9

O teste de unidade ou o desenvolvimento orientado a testes vale a pena?

Sim sim . Tio Bob (Robert C Martin) contou em uma apresentação;

Para um desenvolvedor provar que seu código está funcionando melhor para escrever e passar no teste do que gritar, cantar ou dançar sobre ele.

E como você não excluirá o teste, desde que o teste seja aprovado, você tem certeza de que a funcionalidade está funcionando - os problemas de regressão foram resolvidos.

Há muitas coisas escritas nele,

  1. Você é responsável por fazer esse recurso funcionar. Escreva um teste. Apenas faça.
  2. Quando substituir os testes de unidade pelo teste de integração

O SCRUM, o teste de unidade e o TDD estão relacionados?

Em breve, quando você for mestre, Unit testingestará perto de TDD. O SCRUM não tem nada a ver com isso, mas, como se costuma dizer, grandes coisas se misturam bem, essas técnicas de desenvolvimento de um software se somam a uma pilha excelente , se você ainda não o experimentou, tente.

Existe algo que torne o TDD especialmente bom para o SCRUM?

Como eu disse acima, eles fazem uma boa combinação ; Se você adicionar alguns testes de automação a ele, será mais especial .

ManuPK
fonte
8

Parece que escrever testes é um trabalho extra, dá às pessoas uma muleta quando escrevem o código real e pode não ser eficaz com muita frequência.

O teste de unidade tem valor como uma muleta. Ele suporta seus esforços de desenvolvimento, permitindo que você altere sua implementação sem temer que seu aplicativo deixe de funcionar conforme necessário. Os testes de unidade também são muito mais do que uma muleta, pois oferecem uma ferramenta com a qual você pode validar se sua implementação atende aos requisitos.

Todos os testes, sejam testes de unidade, testes de aceitação, testes de integração, etc., são tão eficazes quanto as pessoas que os utilizam. Se você abordar seu trabalho com desleixo, seus testes serão desleixados e sua implementação terá problemas. Então, por que se preocupar? Você se incomoda em testar porque precisa provar a si mesmo e a seus clientes que seu software funciona e não possui problemas que possam impedir o uso do software. Sim, os testes são definitivamente um trabalho extra, mas a forma como você realiza os testes determinará quanto esforço será necessário para corrigir bugs após o lançamento e quanto esforço seu código exigirá para alterar e manter.

Entendo como os testes de unidade funcionam e como escrevê-los, mas alguém pode argumentar que é realmente uma boa ideia e vale o esforço e o tempo?

TDD e realmente qualquer método que exija que você escreva testes antes de codificar adota a abordagem que você faz em um esforço antecipado como adiantamento de dívidas técnicas futuras. À medida que você trabalha no projeto, qualquer coisa que seja perdida ou que não seja implementada corretamente terá mais dívidas técnicas na forma de maior dificuldade de manutenção, o que afeta diretamente os custos futuros e os requisitos de recursos. Testar antecipadamente garante que você não apenas se esforçou para lidar com futuras dívidas técnicas, mas também codificou seus requisitos de forma que eles possam ser verificados simplesmente executando seu código. O teste primeiro também oferece a oportunidade de validar sua compreensão do domínio do problema antes de se comprometer a resolver o problema no código, e valida seus esforços de implementação.

Tudo se resume a tentar maximizar o valor comercial do seu código. O código geralmente não testado e de difícil manutenção é geralmente barato e rápido de criar, e muito caro de manter durante o tempo de vida útil do produto após o lançamento. O código que foi testado minuciosamente no nível da unidade geralmente é mais caro para criar, mas custa relativamente pouco para manter durante a vida útil do produto após o lançamento.

Além disso, existe algo que torna o TDD especialmente bom para o SCRUM?

TDD não é especificamente bom para nenhuma metodologia específica. É simplesmente uma ferramenta. Uma prática que você pode integrar em seus processos de desenvolvimento para ajudá-lo a alcançar seus resultados específicos. Portanto, para responder sua pergunta, o TDD é complementar ao seu método, seja SCRUM ou qualquer outra abordagem.

S.Robins
fonte
6

As pessoas pensam que é um esforço extra, porque é uma atividade inicial. O que você perde com o tempo agora ganha mais tarde.

Minhas razões para o teste de unidade também incluem:

Oferece um objetivo: você não pode escrever um teste se não souber o que o software deve fazer. Isso ajuda a eliminar problemas nas especificações mais cedo ou mais tarde.

Dá a você uma sensação de progresso.

Avisa se uma alteração de código altera a saída de outras áreas do código. Isso facilita a refatoração.

Fornece uma camada adicional de documentação (especialmente se você comentar seus testes corretamente).

Incentiva todos os tipos de boas práticas. Como os testes devem ser executados rapidamente, ele incentiva você a escrever um código dissociado e que suporte a simulação. Isso tudo ajuda na refatoração.

Existem outros também abordados em outras postagens neste tópico. Vale a pena.

Ian
fonte
2

O teste de unidade ou o desenvolvimento orientado a testes vale a pena?

Definitivamente sim (veja as outras respostas)

[É] realmente uma boa ideia e vale o esforço e o tempo?

  • Sim, se você iniciar algo novo (adicione um novo módulo ou um aplicativo completamente novo)
  • Não, se já existe muito código existente que não foi desenvolvido orientado a testes e que deve ser estendido (herdado).

Na minha opinião, o desenvolvimento orientado a testes é mais eficaz se você escrever os testes de unidade antes do código real. dessa forma, o código que realiza os testes se torna claramente separado com um mínimo de referências externas fáceis de serem testadas.

Se o código já existir sem os testes de unidade, geralmente é muito trabalhoso escrever os testes de unidade posteriormente, porque o código não foi escrito para facilitar o teste.

Se você fizer TDD, o código será automaticamente testado facilmente.

k3b
fonte
2

Deixe-me abordar isso do outro lado. O que acontece quando você desenvolve um aplicativo não trivial sem testes de unidade? Se você tem um bom departamento de controle de qualidade, uma das primeiras coisas que acontecerá é que você encontrará um grande número de problemas relatados. Por que, porque você não testou o que fez e presumiu que funcionaria e porque não prestou muita atenção aos requisitos e seu aplicativo não os atende. Opa, de volta à prancheta para reescrever e corrigir. Agora você fez as correções e encontrou um novo conjunto de problemas porque não tinha como verificar se as correções não afetaram mais nada antes de enviar para o controle de qualidade. Opa, o prazo já chegou e se foi e a gerência está chateada.

A situação é pior se você não tiver um bom departamento de controle de qualidade, porque os usuários encontrarão os bugs e não apenas isso deixará seu chefe infeliz, como também poderá deixar o ambiente de produção de joelhos e centenas ou centenas de pessoas estarão em uma paralisação enquanto você corrige os bugs que o teste de unidade teria impedido. Esta não é uma boa escolha de carreira.

Agora, suponha que essa abordagem de cowboy continue por anos? Agora, todas as mudanças, mesmo as triviais, parecem provocar novos problemas inesperados. Não apenas isso, mas muitas das coisas que você gostaria de fazer para que o aplicativo funcionasse melhor, você não pode fazer porque elas são muito arriscadas ou muito caras ou ambas. Então você coloca patches nos patches, tornando o sistema cada vez mais complicado, mais complicado e mais difícil de usar.

Os usuários começam a questionar suas estimativas de tempo porque ficam cada vez maiores e é difícil explicar a eles que o sistema se tornou uma bagunça tão complicada que é difícil encontrar onde fazer as alterações e ainda mais difícil para garantir que eles não façam ' Não quebre outra coisa.

Trabalhei em um local como este, onde, após dez anos de desenvolvimento, praticamente nada do que queríamos fazer para solucionar os problemas reais poderia ser feito, porque não sabíamos qual das centenas de aplicativos clientes personalizados seria interrompida. Os desenvolvedores iniciais eram basicamente o tipo de "testes de unidade, não precisamos de testes de unidades fedorentos". Todos que os seguiram sofreram graças à miopia.

Sem testes de unidade, o software é mais complicado e leva mais tempo para desenvolver e manter inicialmente. Por que diabos você não gostaria de fazer testes de unidade? O tempo que você gasta escrevendo o teste será muito menor do que o tempo gasto consertando os problemas que você deveria ter encontrado mais cedo (quanto mais cedo o bug é encontrado, menos tempo leva para ser corrigido) e os problemas que você teria evitado completamente escrevendo os testes primeiro, que fornece uma melhor compreensão dos requisitos antes de começar a codificar.

HLGEM
fonte
1

Todo o código que você escreve precisa ser testado em algum momento. Você não quer escrever a coisa toda de uma só vez, depois apertar o botão de compilação e cruzar os dedos. Você escreve e compila pequenos blocos e envia entradas cuidadosamente criadas em seu código para verificar se ele faz o que você pensa que faz. Em seguida, você geralmente exclui seu aparelho de teste ad-hoc e passa para o próximo componente.

Com o teste de unidade, ele simplifica esse processo e oferece uma desculpa para manter seus testes por perto. Dessa forma, se você fizer alterações que quebrem as coisas testadas no passado, poderá capturar essa regressão explicitamente, em vez de permitir que ela afete outras partes do seu código. Há um valor real nisso.

Quanto à abordagem do refator vermelho-verde para o TDD, acho isso um pouco tedioso. Mas cada um na sua.

tylerl
fonte
11
Para o meu 2c: para saber se seus testes estão realmente funcionando, você precisa vê-los falhar antes de passar. Infelizmente, testemunhei muitos desenvolvedores escreverem testes que pareciam estar funcionando, mas quando as condições de teste foram alteradas, o código ainda passaria no teste, mesmo que tivesse falhado. Se o teste falhar primeiro e passar em segundo, é mais provável que você tenha escrito um teste sem erros. Se você acabar modificando o teste após a alteração do código, não poderá ter certeza de que o código está correto. Sim, é tedioso, mas tem uma chance melhor de estar correto. :-)
S.Robins
0

Na maioria das vezes, acho que os desenvolvedores são resilientes à ideia de escrever testes. Não é tanto que eles argumentem que os testes não têm valor, mas são apenas um meio de descobrir como resolver um problema específico. Normalmente, esse problema muda com base no contexto. Feito isso, os testes não servem para nada e podem ser excluídos. Aqui está uma amostra dos contextos que meus colegas deram no passado sobre como decidir quando escrever um teste e você encontrará a única resposta possível de acordo com eles nunca:

  • o problema em questão deve ser um exemplo de livro de texto para TDD, como uma pilha ou uma calculadora
  • código trivial não deve ser testado (invalida o argumento anterior)
  • código crítico ou difícil deve ser exaustivamente testado (implícito no argumento anterior)
  • os testes não devem ser acoplados à implementação para permitir uma refatoração abrangente (invalida o argumento anterior)
  • o teste de efeitos colaterais, como chamar um serviço de terceiros com uma carga útil específica, não é necessário (portanto, nenhum teste de caixa preta)

Na verdade, há um tipo de teste que eu acho que geralmente é aceito e que acredito que é inútil. Ou seja, testes baseados em GUI, como o selênio, webdriver, watir ou arquillian. É assim que obtemos os ciclos de compilação de 7 horas em vez dos 5 minutos nos meus projetos de TDD.

Esses mesmos desenvolvedores geralmente reclamam com todos os outros o quão ruim é o código e o quão incompetentes os desenvolvedores anteriores devem ter sido. Eles também consideram extremamente importante que você faça um design adequado usando um quadro branco, escritório da MS ou wiki e tome muito cuidado para garantir que esse design permaneça atualizado.

Esse último é o que realmente me fez perceber que esses desenvolvedores são fraudes. Todos sabemos que qualquer documento de design que não seja um teste de unidade ficará desatualizado e não será mantido atualizado devido ao grande custo de manutenção. Na verdade, tentei e tentei encontrar um bom meio de expressar idéias de design no formato MS office, que era útil e legível antes e depois do fato de escrever código. Eu falhei em todos os casos e, embora existam pessoas que conseguem produzir um documento do MS office que parece bonito, eu também nunca os achei úteis.

Então você tem uma escolha. Você pode criar design e documentação praticando o TDD, que é o único método conhecido e comprovado para produzir essa documentação com base em meus 10 anos de experiência em desenvolvimento. Ou você pode entrar na política.

Sebastian Gozin
fonte
11
testes não são documentação. O TDD é uma boa prática, mas muitas vezes os desenvolvedores usam as ferramentas de geração automática que emitem stubs de teste simplificados demais. Se você tem um desenvolvedor que é resistente a isso, em vez de escrever testes refinados, tente escrever um equipamento de teste maior que exercite mais o produto inteiro. Eles acharão isso obviamente útil. Você ainda precisa escrever a documentação adequada, não há como fugir disso.
precisa
@gbjbaanb: se os desenvolvedores usam ferramentas de geração automática, talvez haja testes de unidade de gravação, mas definitivamente não o TDD. No TDD, você deve escrever teste antes dos métodos. Você não pode automatizar o andaime do teste de um método que ainda não existe. Testes bem escritos também são documentação (documentação técnica para outros desenvolvedores do projeto, não requisitos nem manual do usuário). Testes de unidade bem escritos e mantidos mostram como os métodos devem ser testes. E se os testes são verificados regularmente e são bem-sucedidos, eles são obviamente mais precisos do que a documentação desatualizada. Você não pode negar isso.
Julio
Os unittests podem ser uma documentação muito boa para desenvolvedores, pois mostram exemplos de como a API pode ser usada.
K3b
O objetivo do selênio, do driver da web etc. é que você não precisa fazer o controle de qualidade manualmente do site. Portanto, você não está economizando tempo removendo-os do processo de compilação, porque eles próprios destinam-se a economizar tempo.
Muhd