Falando de TDD

[fblike]

 

Pois é… sobre a importância de testar e dos testes unitários acho que todos concordamos.

Mas e sobre TDD? A gente sabe que é bom. Só que muita gente fala disto mas na prática nem todos adotam. É difícil fazer TDD? Será que estão errados os que não fazem? E quem faz, deve fazer sempre?

Hoje pela manhã tuitei sobre as dificuldades que tenho com TDD:
https://twitter.com/#!/lucabastos/status/125903882953043969

Aí vão respostas de alguns amigos aos quais agradeço (passem o mouse para ler):
@diegorv, @blackbnu, @VitorioRamon, @blackbnu, @rodrigoospinto, @rodrigoospinto, @mauricioaniche, @rodrigoospinto, @diegorv, @marcelotozzi, @blackbnu, @leandro_storoli, @leandro_storoli, @fnmunhoz, @VitorioRamon, @VitorioRamon, @VitorioRamon, @VitorioRamon, @adrianoalmeida7, @VitorioRamon@adrianoalmeida7, @rgalba, @wbotelhos, @srsaude, @alberto_souza

Ficou claro que não sou só eu com dificuldades. O @leandro_storoli listou exatamente o que penso. Pela segunda resposta do @rodrigoospinto, desconfio que gente como eu, deveria praticar mais dojos de códigos para aumentar a fluência.

Ainda sob a impressão do tech talk do Fábio Miranda sobre TDD e o livro GOOS, resolvi discutir mais este assunto até mesmo para realinhar idéias.

O Peter Sergeant blogou recentemente dizendo que não é sempre que se deve fazer os testes antes e isto causou um reboliço nos comentários: Test-Driven Development? Give me a break…. Vale a pena ler tudo inclusive os comentários (o @mauricioaniche comentou lá).

Vamos começar pelo princípio:

Test Driven Design ou projeto guiado por testes significa escrever o teste antes. A gente cria um teste que falha e completa o código só para fazer o teste passar. Então refatora e volta ao início.

Baby steps, passinhos curtos, TDD exige isto. Parece chato e improdutivo para muitos programadores experientes. Aliás é mesmo principalmente para quem não está acostumado.

Esta coisa de passinhos curtos depende da experiência do programador. Alguém que já conheça o domínio pode avançar mais rápido. Há ótimos programadores não fazem TDD de jeito algum apesar adeptos de testes e refatoração.

http://vinkamat.com/2011/tdd-unit-testing-and-benefits

 

A importância de começar pelos testes foi reconhecida muito antes do que muita gente imagina. Em 1968 o comitê de ciências da NATO (ou OTAN), promoveu uma conferência na Alemanha chamada de Working Conference on Software Engineering (juro que não sabia que naquela época já se usava este termo engenharia de software). O relatório da conferência foi publicado em 2001 e o PDF pode ser baixado.

Lá na página 32, o americano Alan Perlis, um dos pioneiros das linguagens de programação e primeiro ganhador do Turing Award,  escreve:

I’d like to read three sentences to close this issue.

  1. 1. A software system can best be designed if the testing is interlaced with the designing instead of being used after the design.

  2. 2. A simulation which matches the requirements contains the control which organizes the design of the system.

  3. 3. Through successive repetitions of this process of interlaced testing and design the model ultimately becomes the software system itself. I think that it is the key of the approach that has been suggested, that there is no such question as testing things after the fact with simulation models, but that in effect the testing and the replacement of simulations with modules that are deeper and more detailed goes on with the simulation model controlling, as it were, the place and order in which these things are done.

 

Isto fiquei sabendo no blog do Steve Freeman. Como bem disse o co-autor do livro Growing Object Oriented Software, Guided by Tests, está tudo na nossa história, só precisamos ser capazes de encontrar.

Os que costumam testar mas não fazem TDD, poderiam se beneficiar se o adotassem?

Com certeza no início perderiam produtividade. Pelo menos é o que acontece comigo. Fora que às vezes me sinto fazendo testes bobos descartáveis só para começar pelos testes. Quanto mais a gente conhece bem o domínio, menos paciência tem com os tais baby steps.

Pode parecer fácil e muita gente diz que é. Eu acredito que depende inclusive da personalidade do desenvolvedor. Em princípio, acho que vale a pena tentar. Principalmente quando a gente se depara com um sistema em um domínio novo em que para entender precisamos de baby steps. O duro como bem disse o @leandro_storoli, é saber exatamente o que testar e perceber quais testes são relevantes de forma isolada.

Nesta busca de encontrar um meio de mais rapidamente voltar a se sentir produtivo enquanto tenta fazer TDD, vale a pena buscar socorro com quem já passou desta fase.

Junto abaixo alguns links interessantes:

Steve Freeman e Nat Pryce, autores do livro acima conhecido como GOOS, são dois pioneiros do desenvolvimento ágil na Inglaterra. Participaram também da criação do conceito de objetos mocks e desenvolveram a conhecida bibloteca JMock. Isso ainda nos primórdios do Java e do Ruby. Este livro foi revisto e comentado por muita gente:

Então…

Falar de TDD nunca é demais. Há muito o que discutir. Principalmente para gente do tipo macaco velho como eu que tem mais dificuldades para se adaptar.

Daí a importância do tech talk de TDD do Fábio Miranda que abordou o livro GOOS apresentado no blog passado em http://blog.concretesolutions.com.br/2011/10/tech-talk-sobre-tdd-e-o-livro-goos/.

 

E você, faz testes e sempre começa pelos testes como recomendam as práticas de TDD?

Sempre mas sempre mesmo começa pelos testes?

É como eu, que apesar de favorável ao TDD, quando precisa implementar um algoritmo, acha mais fácil se concentrar no fluxo lógico ao invés de iniciar pelos testes?

Ou concorda com o Maurício Aniche, evangelista de TDD mas admite que é uma ferramenta que o desenvolvedor deve identificar os momentos adequados para usar e quando pode dispensar?

 

Comentem!

  • http://www.facebook.com/fabiolnm Fábio Miranda

    considero escrever testes uma atividade particularmente difícil quando se está numa fase “exploratória” de uma funcionalidade. Havia publicado essas impressões em http://fabiolnm.blogspot.com/2011/02/sudoku-solver_28.html. Outra impressão é que TDD envolve uma ruptura, uma quebra de paradigma, uma nova maneira de pensar e desenhar soluções… Fomos ensinados desde cedo a programar numa linguagem, a debugar, a usar printf… Abraçar uma nova cultura exige esforço, muito estudo e muitas experimentações… Mas eh gratificante quando vc começa a colher os frutos, a ter mais confiança no seu código e no código do seu time.

    • Alexandre Aquiles

      Fábio, é engraçado você mencionar Sudoku como exemplo… Há um episódio muito interessante que aconteceu em 2007, envolvendo TDD e Sudoku.

      Ron Jeffries (pioneiro de eXtreme Programming) tentou escrever um Sudoku Solver usando TDD. Ele tenta por 5 vezes e acho que até chega em uma solução, mas que não é tão elegante.

      Peter Norvig (autor do “Artificial Intelligence: a Modern Approach”, diretor de pesquisas da Google e professor do ai-class.com), fez um Sudoku Solver usando a técnica de Constraint Programming e ficou muito elegante.

      Você pode ver os links e discussões sobre o episódio em http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html

      No livro “Coders At Work”, Peter Norvig comentou:

      “I think test-driven design is great. I do that a lot more than I used to do. But you can test all you want and if you don’t know how to approach the problem, you’re not going to get a solution.”

      No caso acima, conhecer sobre IA e algoritmos de busca ajudou bastante na criação de uma boa solução. O Norvig fala no “Coders at Work” sobre algo como ter um indíce mental de Body of Knowleges pra procurar quando for necessário.
      ___

      A questão nem é se TDD ajuda ou não. Em muitos contextos, TDD ajuda a criar código melhor, dá ritmo para o desenvolvimento e foca a mente do programador. Não sei se mais alguém acha isso, mas pra mim codar guiado por testes faz programação parecer um jogo. E isso me ajudou a redescobrir o prazer de programar.

      Mas é apenas uma das ferramentas que um bom programador deve ter. TDD não é suficiente para todos os tipos de problema. Se você não entende direito o problema que está resolvendo, um quadro branco, uma conversa e modelagem (em UML ou não) ainda são as melhores ferramentas. Aí, quando você vai codar com os objetivos claros e o design de alto nível em mente, TDD é muito bom.

      Há um tempo atrás achava legal a postura xiita do Uncle Bob, que dizia pra seguir o ciclo Red-Green-Refactor à risca. Mas com um pouco mais de experiência, vi que são vários fatores em jogos e que inverter a ordem um pouquinho faz mais bem do que mal.

  • http://twitter.com/felipejcruz Felipe Cruz

    Grande post Luca..!

    Eu, pessoalmente, tento sempre ver as coisas de um ponto de vista diferente do padrão.. vou jogar mais algumas coisas pra se pensar..

    Em primeiro lugar.. acho que o TDD vale muito a pena pela questão de se pensar no design antes de qualquer coisa.. Se vamos criar uma API de manipulação de imagens, é óbvio que TDD pode ajudar muito.. apesar de pensar sempre que NADA deve ser obrigatório.. como você disse, cada desenvolvedor tem sua forma de ser produtivo.. uns usam VIM, outros Eclipse, outros Mysql, outros Postgre, uns usam TDD e outros preferem codificar e criar os testes depois.

    Em segundo lugar, eu queria saber, dos apaixonados evangelizadores do TDD qual o percentual de projetos onde temos tempo hábil pra desenvolver com TDD.. mal temos tempo pra codificar o que foi “pedido”.. vamos falar do mundo real.. não academico.. Que jogue a primeira pedra quem não cortou os testes porque o prazo do projeto era surreal…

    Outro ponto muito chato é questão de quem não tem testes, ser rotulado de “go horse”. Posso falar e quem quiser pode criticar, mas hoje estou desenvolvendo um SaaS pra clientes enormes que veio de um FREELA sem nenhum teste(mais de 1 ano em produção com pouquissimos bugs e muitas atualizações). Claro.. O freela custou apenas 4k. Quem aqui faz freela por 4k com TDD? Se eu tivesse imposto o preco do tempo gasto com testes, talvez o freela nao fosse feito comigo.. E digo mais.. esse freela de 4k foi base pra um sistema MUITO maior, feito em 2 meses.. SEM TESTES! Não tivemos verba pra cobrir o tempo que gastariamos com testes. Assumimos este risco com TOTAL consciência…. mas valeu porque conseguimos ir pra uma etapa seguinte..

    Somente semana passada, começamos o SaaS, agora com testes, porque finalmente conseguimos mais grana pra desenvolver o software e “arrumar a casa”..

    Resumo da ópera: saiba escolher o que for mais adequado.. se você está sendo pago pra fazer uma super api pra manipular ativos do mercado financeiro, e outros desenvolvedores irão usar o seu código, use TDD se quiser..

    Se uma oportunidade surgir “do nada”, não tenha vergonha de criar um software sem testes.. Os requisitos mudam tanto ao longo do caminho que as vezes é inviável criar testes em cima de requisitos completamente instaveis.. a cada alteração, tem que se atualizar codigo e testes.. e as vezes correr um risco com consciencia, pode ser muito mais interessante..

    Acho que as vezes as pessoas esquecem que bom código da menos problema.. tem gente que mal sabe programar e esta ai falando de TDD.. e o ultimo ponto.. Clientes compram um produto.. as vezes não ter uma suite completa de testes mas caprichar no resultado final, vale muito mais.. os testes PODEM vir depois também e não há NADA de errado nisso.

    Sim.. eu uso TDD em alguns projetos.. mas no geral eu sou adepto dos testes unitarios + teste de integração, principalmente quando são sistemas de informação via WEB, que é o que a grande maioria de nós fazemos.
    :)

  • http://twitter.com/dqo Daniel Quirino

    Grande Luca!
    Sobre a Conferência de Engenharia de Software da OTAN de 1968, em Garmisch, ela recebeu este nome propositalmente e foi a primeira vez em que o termo “engenharia de software” surgiu como uma tentativa de chacoalhar a comunidade de computação da época para a tal “crise do software”. Se não estiver enganado, o termo foi originalmente sugerido pelo Niklaus Wirth (o cara do Pascal) e razoavelmente criticado pelo Dijsktra na época.

    Neste link tem um resumo bem bacana sobre o que aconteceu naquele “QCon da década de 60″: http://homepages.cs.ncl.ac.uk/brian.randell/NATO/NATOReports/index.html

    (p.s.: nomes bem legais de se ouvir, como os próprios Dijsktra e Wirth, assim como Bauer e Naur).

  • http://twitter.com/renanreis renanreis

    @lucabastos tenho a mesma dificuldade: “sinto que fazendo testes bobos descartáveis só para começar pelos testes”.

    Fiz o curso com o aniche, o pm87, foi excelente, na apostila foi sugerido o conceito de Children steps, um passo pouco maior que o baby step, vou ler de novo a definição para conseguir explicar melhor. Essa técnica me ajudou bastante.

    Creio que para melhorarmos isso, a maneira mais rápida é fazer dojo com pessoas mais ninjas no assunto e simulando uma situação real.

    Caso haja algum dojo aberto por favor me convidem :-)

  • http://twitter.com/leandro_storol Leandro Storoli

    Caramba, muito legal ver a opinião de todos sobre o assunto! Aliás, parabéns pela iniciativa do Luca por blogar sobre!

    Lendo todos os comentários presumo que todos tenham opiniões parecidas sobre o uso de TDD em determinados projeto. O caso é que o TDD pode ser aplicado em qualquer projeto, a grande questão é o que realmente deve ser testado, para que o teste agregue valor ao produto que está sendo produzido e facilite o processo de manutenção e evolução do produto. Essa maturidade só é adquirida com tempo de testes e projetos com domínios diferentes. Acho que em alguns casos a decisão de não testar um código pode até ser assumida como débito técnico, pra quem quiser saber mais sobre o assunto (http://www.infoq.com/br/news/2009/10/dissecting-technical-debt)

    Como alguns também comentaram, acho que o TDD ajuda na criação de um bom design, na separação de responsabilidades e na refatoração. Acredito que um código produzido orientado a testes acaba ficando mais limpo, conciso e mais fácil de dar manutenção.

    Imaginando uma fábrica de software, um projeto que esteja sendo desenvolvido por uma equipe de 10 programadores acaba ficando desordenado se não houver alguma metodologia/técnica para testes. Testes Unitários, Testes de Integração e afins, facilitam o processo de integração do sistema como um todo. Com isso fica fácil da equipe adotar práticas como Integração Contínua e Deploy Contínuo.

    Acho que o BDD nesse caso facilita muito o processo de definição do que realmente deve ser testado, já que temos uma orientação em forma de texto da funcionalidade (User Story) que deve ser produzida, resultando em código (teste executável) que deve atender a uma etapa ou funcionalidade específica.

    É um tema muito interessante! Topo um dojo com Ruby (RSpec + Cucumber), Java (JBehave + Junit | JRuby + RSpec + Cucumber), Groovy (EasyB), Python e C#…. Só chamar!

  • Lucia

    Boa noite Luca,

    Nossa dessa vez o poema arrasou, Affonso Romano de Sant’anna, lembro de qdo vc postou ele em uma das nossas primeiras conversas no blog!! Mais uma vez parabens!!

  • Pingback: lida zayiflama

  • Pingback: lida zayiflama

  • Pingback: lida

  • Pingback: lida

  • Pingback: lida

  • Pingback: شات صوتي

  • Pingback: lida

  • Pingback: jfd98ayhcimg

  • Pingback: training management systems

  • Pingback: bodhicenter.net