Mais uma vez… TDD não é bala de prata!

Essa semana, o DHH, o famoso criador do Ruby on Rails, fez um post polêmico sobre o assunto, entitulado “TDD is Dead, Long Live Testing”, que em uma tradução livre, é algo como “TDD está morto, Vida Longa ao Teste”. Nele, DHH afirma que não pratica mais TDD, que acredita que a prática mais atrapalha do que ajuda seu dia a dia como desenvolvedor. Para entender melhor os argumentos dele, sugiro que você leia o post original.

É bem difícil discutir sobre opiniões de autores que afirmam categoricamente “nunca use X” ou “sempre use Y”. Acho que a experiência já me ensinou (e ensinou você) que sempre e nunca são palavras que devem ser evitadas ao máximo em engenharia de software.

Qualquer um que desenvolve software sabe que deve buscar por duas coisas: (i) uma boa bateria de testes, afinal, precisamos garantir que o sistema funcione; (ii) um bom projeto de classes, afinal, precisamos de um código de qualidade.

E por que praticamos TDD, afinal? Justamente porque acreditamos que TDD nos ajuda a alcançar esses dois pontos. Para muitos desenvolvedores, escrever os testes antes os ajudam a pensar em mais cenários para o teste. Para outros, o teste é uma excelente folha de rascunho na qual eles pensam melhor sobre o projeto de classes. Entretanto, alguns desenvolvedores conseguem escrever melhor seus testes depois que já escreveram o código. Outros pensam melhor no projeto de classes rabiscando em um papel. Você, desenvolvedor, deve obviamente escolher a prática que melhor o ajuda a alcançar esses pontos. 

Eu, por exemplo, faço parte do grupo de desenvolvedores que usam TDD para essas duas coisas. Isso também acontece com muitos desenvolvedores na Caelum. Em meus trabalhos, inclusive, cito muitas maneiras na qual a prática de TDD ajuda. O quê olhar no teste para saber que seu código tem problemas de acoplamento ou coesão, como refatorar sua bateria de testes, e etc. É claro que eu não uso TDD 100% do tempo, eu o alterno com o uso de outras práticas (gosto muito de rabiscar em um papel para pensar no projeto de classes, e com frequência, escrevo testes depois da implementação). Mas ainda sim, muitas vezes ela é a melhor maneira que encontro para me ajudar.

No post, ele também usa o fraco argumento de que TDD o fazia mockar ActiveRecord, e que hoje ele prefere testes que integram (com banco de dados, IO, e etc). Essa discussão existe no meu livro, e o resumo dela é: se o objetivo da sua classe é interagir com um sistema externo (como é o caso de um DAO, ou dos métodos Active Record das entidades no Rails), o melhor teste para ela, é aquele que se comunica com esse sistema; não faz sentido simular o banco de dados para testar um método que só serve para comunicar com o banco.

Não me incomoda o DHH (ou qualquer outro desenvolvedor) dizer que não usa TDD. Mas, do meu ponto de vista, a grande falha no post é que ele não cogitou a possibilidade da prática ser a maneira mais produtiva para alguns desenvolvedores; não para todos, claro, mas sim, para alguns.

TDD tem que morrer! TDD tem que viver! Tudo depende do quanto você é um desenvolvedor melhor com ele.

Tags: , ,

30 Comentários

  1. Márcio 24/04/2014 at 18:24 #

    Maurício, não entendi a razão de um post como o seu. DHH diz: “Yes, test-first is dead to me”. É a opinião dele, posso estar enganado, mas ele não generaliza em seu post, muito pelo contrário, compartilha sua experiência, a experiência de quem trabalhou muito duro, a de quem olhou teoria de um lado e casou com a prática. Acho que foi mais para desabafo. Eu não compartilho da visão dele, porque minha experiência diz o contrário. Eu não “acredito”em TDD, eu “sei” que TDD funciona. Acreditar em algo é perigo… não posso convencer meu chefe a aplicar TDD porque eu “acredito” que funcione, há sempre muito dinheiro envolvido.

  2. Hugo Henrique 24/04/2014 at 20:41 #

    Post interessante!
    Ótimo ponto de vista!

  3. Fabricio Buzeto 25/04/2014 at 09:37 #

    Eu acho que ele foi longe demais. Foi como dizer que o rails faz mals programadores por que a galera entope os controllers de lógica. Ou que JavaScript é ruim pois a galera entope a interface com lógica não testada.

    Se tem uma máxima na computação que é bem válida sempre é:

    “Maus programadores farão código ruim. Não importa o quanto você tente impedir.”

    No mais. Galera Xiita é sempre ruim pra comunidade. Os extremos escondem as nuances que fazem a diferença.

  4. Priscila 25/04/2014 at 09:58 #

    Bem… o que eu acho é que existe uma grande resistência a se praticar TDD hj em dia. Isso por que no início as coisas sao difíceis mesmo.

    Eu nao acho que TDD resolva todos os problemas, mas a mim tb ajuda a pensar na implementação. Mas não acho que isso seja uma regra.

    E concordo com Aniche. Fazer testes para mokar DAOs e afins, considero totalmente desnecessário. Neste caso… teste integrado.

    O teste é visto como problema muitas vezes quando a implementação muda no decorrer do desenvolvimento e os devs não corrigem os testes que quebraram. Aí vira uma bola de neve. Razão pelas quais muitos detestam ao menos testar.

  5. Raphael 25/04/2014 at 20:58 #

    Muito bom Aniche! Ano passado a polêmica foi com o Bill Burke.

    Mas enfim, TDD está aí, é uma ferramenta, vc pode ou não ser mais produtivo com ela, desde que vc chegue à conclusão de que vc DEVE automizar os testes.

  6. Ronald B. Falcão 26/04/2014 at 10:24 #

    Achei ótimo o primeiro parágrafo: Test-first fundamentalism is like abstinence-only sex ed: An unrealistic, ineffective morality campaign for self-loathing and shaming.

    Em TI existe uma tendência um pouco perigosa de certos grupos elegerem o Santo Graal para resolver a problemática do desenvolvimento de software, cito: tecnologia e custo. Erroneamente muitas empresas pregam o TDD como uma alternativa para baixar custos, pois tira da equipe de testes a responsabilidade por avaliar e validar o sistema, e coloca essa tarefa nas costas do desenvolvedor. Sendo esse muitas vezes chamado de analista desenvolvedor por já ter incorporado as responsabilidades do analista. Essa é a parte “burocrática” que vejo na venda do TDD e que está fora do conceito do que é TDD.

    Usando o ponto acima como base, TDD fica na responsabilidade do desenvolvedor. Projetos grandes, com diversos casos de uso (Processo unificado) tendem a fugir do controle da equipe de desenvolvimento, que assim como todos nós, é falha. Sempre me preocupa ter apenas uma visão durante o desenvolvimento, isso cria visões “viciadas” do sistema, onde o desenvolvedor analisou, criou o teste e desenvolveu o requisito. Em que momento teremos o resultado desse requisito? Eu acredito que o caso de uso tem que ser analisado pelo analista, desenvolvido pelo desenvolvedor e testado pelo tester. E saibam que isso não é tirar o TDD, mas usá-lo de forma a realmente ser uma ferramenta de criar o melhor código (padronizado e extensível), que facilite a vida do desenvolvedor e do tester, pois o primeiro tendo claro os requisitos discutidos, analisados e validados pelo analista, terá uma visão clara da funcionalidade com seus resultados e limitações, e poderá passar ao tester uma forma clara desse saber onde estão os caminhos normal e alternativos do caso de uso.

    Apesar do exagero do texto ele nos coloca uma pulga atrás da orelha, nos cria uma dúvida, nos faz pensar se realmente estamos usando o TDD como uma ferramenta de trabalho afim de lapidar nosso sistema ou como um machado mal afiado macetando o que aparece na frente.

  7. Alexandre Aquiles 26/04/2014 at 11:32 #

    Acho que o que mais me decepciona no post do DHH é o título marqueteiro: “TDD está morto”.

    Me lembro da primeira vez que ouvi sobre a ideia, em 2009. Aprendi JUnit quase junto com TDD. Achei estranho, não entendi direito. Mas percebi que era poderoso e me esforcei para usar (ou tentar). Bati cabeça, corri atrás, li uma penca de livros.

    E me tornei (e tenho me tornado) um programador melhor no caminho. O código que produzo, fruto do meu trabalho, melhorou: tanto tem menos bugs como é mais fácil de manter. E minha vida como programador profissional, que desenvolve com seriedade, melhorou [1].

    Não pedi permissão pra usar TDD (e testes automatizados) nos meus projetos. Percebi que precisa convencer a equipe, mostrar os benefícios. Encontrei colegas que estavam estudando a idéia e somamos esforços. E o pessoal de negócio percebeu que os sistemas desenvolvidos por uma parcela da equipe tinham menos bugs no que era crucial, nas partes difíceis e importantes.

    TDD não está morto. Espero que os desenvolvedores iniciantes não leiam o post do DHH como uma desculpa para não estudar essa técnica tão importante.

    ___

    Por outro lado, o DHH tem razão quando critica os xiitas do TDD que falam que quem não usa pra tudo não é profissional (na minha interpretação).

    Mas, convenhamos, boa parte das aplicações que fazemos são CRUDs simples. Será que vale a pena guiar desenvolvimento de CRUD por testes? A gente não domina (ou pelo menos deveria dominar) as tecnologias pra criar CRUD suficientemente? A gente não pode automatizar a geração de CRUDs com frameworks? E até será que vale a pena fazer testes unitários, em partes que a gente não erra tanto [2]?

    Hoje em dia, gosto de focar naquelas partes complicadas, cheias de nuances e regras de negócio complexas. Essas partes, como dizia um colega: “Não consigo programar sem testes”.

    [1] http://blog.gdinwiddie.com/2013/07/23/why-i-practice-tdd/
    [2] http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests/153565#153565

  8. Fernando Vitor Santos Vasconcellos 27/04/2014 at 11:35 #

    Post do uncle bob sobre o assunto.

    http://blog.8thlight.com/uncle-bob/2014/04/25/MonogamousTDD.html

  9. Maurício Aniche 28/04/2014 at 12:12 #

    Oi pessoal,

    Obrigado. A minha ideia era justamente mostrar que não tem certo ou errado quando se trata de engenharia de software. Toda prática tem suas vantagens e desvantagens.

    Oi Márcio,

    Achei que ele foi bem forte nas afirmações dele sim. Começando até pelo nome do post: “TDD is dead”. Ou mesmo no fim, “it’s time to move on”. Ele precisa ser mais cuidadoso com as afirmações dele, afinal ele influencia muita gente.

    Um abraço,

  10. Guilherme Silveira 29/04/2014 at 11:37 #

    Pelo texto do David fico com a impressão que ele está certo em um contexto: para quem faz código lixo e não está preocupado em melhorar a qualidade de seu código, mas somente em fazer TDD, fazer TDD não vai ajudar tanto. Tenho até a impressão que esse é o resultado da pesquisa de um colega (é?)…. fazer test first e não conhecer as técnicas de design de código, ou ignorar elas, não traz vantagem para a qualidade do design do código, traz?

    E tenho a impressão que é assim que o TDD foi vendido na comunidade que o David participa: faça teste antes pois seu código sairá melhor. Pessoalmente eu não via isso acontecendo na comunidade Ruby no começo. Via mocks a rodo testando coisas que podiam mudar a qualquer instante e o teste continuava passando e más práticas de código feitas por quem ainda não tinha experiência de boas práticas de código em outra linguagem – o mesmo padrão de más práticas de código de Java, de ASP etc. E claro, quem tinha boas práticas de código continuava usando as boas práticas de código, independente do TDD, melhorando com o conhecimento maior da linguagem. Claro, isso é uma visão minha (sem números para comprovar), mas a pesquisa do meu colega (feita em Java?) acho que pode ser repensada para o mundo Ruby (ou Rails) do David.

    Se isso que disse faz sentido, o argumento do David, no mundo Ruby e Rails da época, fazia sentido. Faz sentido para um “TDD” de evangelização despreparado, que não ensina boas práticas juntos.

    Por outro lado, quem conheço que ensina “TDD” de evangelização preparado, ensina junto boas práticas de código, como o Uncle Bob (SOLID, seu livro e suas aulas), e o Aniche (suas pesquisas sobre qualidade de código no blog, na Caelum e no Alura).

    Reclamar do TDD sem qualidade como se ele fosse o TDD com qualidade de código é chamar duas coisas da mesma coisa, e acho que ai que ele errou. Quem ensina, como ensina, faz diferença.

  11. Stélio Moiane 29/04/2014 at 12:06 #

    Maurício,

    Acho que tem haver com a forma de como se lida com a coisa, para mim por exemplo, ja é dificil pensar em programar alguma coisa sem antes pensar no teste. mas claro exitem vezes que da para fazer. mas é a historia de sempre nunca nos sentimos seguros em entregrar codigo não testado pelo simples facto de não confiarmos nele. para mim sem TDD sinto como se fosse voltar pra forca. Acho que quando a coisa traz resultados notáveis há desvantagens que valem a pena manter.

    Sucessos!

  12. Yuri Tavares 29/04/2014 at 12:08 #

    Excelente post, concordo inteiramente, o que pode funcionar pra um pode não funcionar pra outros.

  13. VSVeras 29/04/2014 at 12:17 #

    Vou lhes dizer o que o TDD não é ou não faz:

    – Resolver todos os seus problemas (PROJETO/INTEGRAÇÃO/GERENCIAMENTO/EQUIPE etc.) IS NO SILVER BULLET.

    – Baixar custos
    – Aumentar a produtividade

    Concordo com o Maurício Aniche, o fator desconhecido gera um medo tremendo.

  14. Bruno Nardini 29/04/2014 at 12:22 #

    Concordo com você, Maurício.
    Primeiro que ele e toda a galera do Rails tem uma visão conturbada sobre o TDD.
    Fazer testes integrados com banco só deixa o teste mais lento, e se é integrado, não é teste de unidade, muito menos TDD.
    O negócio é que fazer teste antes, além de aumentar a qualidade, é mais motivador do que fazer o teste depois, porque fazer teste depois de algo já pronto sempre é chato e muitos acabam procrastinando.
    O que me deixa mais incomodado com o artigo é que ele não propõe uma solução melhor, apenas faz críticas.

  15. Steimntz M. de Figueiredo 29/04/2014 at 12:51 #

    Ola Ronald B. Falcão,

    Acho que você está equivocado quando fala que “(…) Eu acredito que o caso de uso tem que ser analisado pelo analista, desenvolvido pelo desenvolvedor e testado pelo tester (…)”, pois TDD é modelagem e não veio para substituir a equipe de teste.

    A grosso modo teste de Unidade são para garantir que seu código não regrida, que o código esteja fazendo o que deve fazer (como um ‘requisito executável’) e umas das vantagem que se ganha com essa técnica é que, assim fica possível refatorar ou evoluir o código sem medo de quebrar outras partes do código.

  16. Jesse James 29/04/2014 at 13:02 #

    Acho que precisamos de mais ciência em computação. Atualmente vivemos a era das trevas, de cultos religiosos, de teoria da biogênese e do homúnculo. Existem defesas de idéias não comprovadas ou testadas em casos específicos e generalizados, enfim, me parece que o método científico, inserido nas ciências tradicionais há séculos não perdura na computação, ficando, no máximo os famosos corpos de conhecimento que não se aplicam à maioria dos projetos e à opinião de gurus tecnológicos.

    Só pra comprovar isso, a grande maioria dos que leram esse post jamais leram o artigo original sobre a bala de prata da engenharia de software, artigo esse que, quase 30 anos da sua publicação continua atual e se atualizando pois todo dia surgem candidatos a bala de prata e esses candidatos sempre trazem consigo os seguidores tão cegos e crentes como qualquer seguidor de seitas fundamentalistas.

    Então, por favor, não sigam gurus, sigam cientistas. Procurem a prova de que TDD é realmente melhor que algo, procurem um estudo estatístico sério, com uma amostra controlada que comprove ou descarte as idéias e mais uma vez: procurem ciência na computação e não uma religião.

    Aliás abomino o termo: “evangelista” utilizado para algumas tecnologias. Que tal: cientistas? Pessoas que provam ou buscam provar aquilo que afirmam!

  17. Maurício Aniche 29/04/2014 at 13:46 #

    Oi Guilherme,

    É isso mesmo. Minha própria dissertação de mestrado afirma algo parecido. Fazer TDD por fazer não adianta; o desenvolvedor precisa ler (e saber como ler) o feedback do teste e melhorar seu código.

    É bem complicado pedir para um desenvolvedor que não entende muito de testes nem de boas práticas de desenvolvimento para praticar TDD. Não vai sair muita coisa mesmo.

    Oi Jesse,

    Sem dúvida. Mas eu não generalizaria tanto. Acho que precisamos mais de ciência em engenharia de software. Tem outras áreas da computação que já fazem bem isso. Juro que é o que tento fazer antes de publicar qualquer coisa! 🙂

    Espero que mais desenvolvedores/pesquisadores vejam valor nisso e façam um pouco de ciência na área.

    Um abraço!

  18. Alexandre Aquiles 29/04/2014 at 13:59 #

    O Kent Beck, pai do suposto defunto, escreveu um “obituário”:
    https://www.facebook.com/notes/kent-beck/rip-tdd/750840194948847

    O texto é irônico e diz que está procurando novas técnicas para substituir algumas vantagens do TDD como evitar fazer código desnecessário, ter uma maneira precisa de comunicar o problema que queremos resolver, separar o ato de pensar na interface (comportamento público) do pensar nos detalhes de implementação, etc.

  19. Fernando Boaglio 29/04/2014 at 15:50 #

    Até aí o Donald Knuth acha que teste unitário é perda de tempo (http://beta.slashdot.org/story/100540) , não dá pra agradar todo mundo! =)

  20. Arthur 29/04/2014 at 16:46 #

    TDD só serve quando você sabe que implementação vai fazer e que esta tem uma certa complexidade. Como ser criativo quando você tem que, antes de tudo, implementar um chato que fica acusando erros de um código que nem existe? Gosto de testes, mas não antes da implementação. Isso me dá mais liberdade de tentar implementações diferentes. Depois, caso o código tenha uma complexidade suficiente para me deixar desconfortável aí sim implemento testes. O bom disso é que quando o código é bem complexo, os testes não só me ajudam a corrigir alguns erros, como me ajudam a ter novas ideias. Por vezes acabo refazendo uma parte ou até mesmo tudo. Portanto, para aqueles que falam que TDD deixa o desenvolvimento mais lento, nem concordo nem discordo. Produtividade você conquista é com competência. Quer produtividade? Vá estudar! E para os gestores: quer produtividade da sua equipe? Implemente uma metodologia ágil combinada com DDD e você vai conseguir.

  21. Ismael Soares 12/05/2014 at 09:24 #

    Esta discussão sobre TDD vai longe, mas não acredito que isto vai levar ao fim da prática.
    Concordo com a opinião do Aniche. TDD pode ser útil ou não, depende de como e quando você usa.
    Quanto ao escrever os testes depois, eu penso que só é recomendável para desenvolvedores experientes. Já vi muita gente inexperiente escrevendo testes depois que não testam nada, escrevem apenas para dizer: “meu código tem testes”.

  22. Joaquim Oliveira 13/05/2014 at 11:18 #

    Oi, pessoal! Vocês viram o hangout do DHH, Martin Fowler e Kent Beck conversando sobre o assunto? https://plus.google.com/events/ci2g23mk0lh9too9bgbp3rbut0k

  23. Maurício Aniche 13/05/2014 at 13:19 #

    Oi Joaquim,

    Vi sim. Preciso escrever minha opinião sobre isso ainda, e preciso pensar melhor. Em breve! 🙂

    Na lista de discussão do meu grupo teve um post bom lá sobre isso: https://groups.google.com/forum/#!topic/tdd-no-mundo-real/2xv4VckeCno

    Um abraço!

  24. Bruno Nardini 18/05/2014 at 20:02 #

    Maurício, fiz um post também sobre o assunto: http://wp.me/p2CLm3-aI
    Se puder dar seu parecer, ficaria muito grato. =)

  25. Maurício Aniche 19/05/2014 at 15:26 #

    Oi Bruno,

    Vou comentar seu post sim! 🙂

    Um abraço!

  26. Alexandre Magno Teles Zimerer 16/11/2017 at 09:36 #

    Olá, referenciei este excelente post no meu recente artigo:
    http://blog.alexandremagno.net/2017/11/os-testes-te-guiam-alguns-motivos-mais-para-voce-usar-tdd-e-bdd/

    Acho que pode complementar o assunto.

Deixe uma resposta