Como introduzir TDD à minha vida?

Gostei bastante deste screencast.

Me fez pensar numa coisa: quando a classe tem responsabilidades demais você faz tantos testes que acaba ficando cansado, e assim segue refatorando a classe em duas ou mais delas, refatora também os testes em mais classes e só para não ter que testar as mesmas coisas sempre.

Acho que o relato de uma pessoa de umas das equipes que estou colocando o conceito de qualidade/agilidade resume muito bem o que acontece com o desenvolvimendo com TDD, “se tem uma segurança muito grande de poder alterar qualquer coisa e saber exatamente onde os problemas vão refletir!”.

Quando se falam por exemplo em análise de riscos, nada mais prático de alterar o teste, executar e ver quais pontos podem ser atingidos por aquela alteração, isso realmente da uma segurança na hora de se fazer alterações, óbvio que um bom nível de cobertura é essencial para isso.

[quote=Luca]Olá

Este tópico está muito bom. Gostei muito dos links que passaram.[/quote]

Concordo. IMHO, tópicos desse tipo é que fazem com que bons desenvolvedores ainda estejam aqui no GUJ.

Os meus ainda tem bastante disso. Sem contar a quantidade de comentários existentes… é um terror.
O debugger entra nessa parte de testes? Porque vejo muitas pessoas falando (tá certo que é em RoR) que não usam mais o debugger. Provavelmente me enganei em alguma coisa.

[quote=Luca]
Encaro o TDD mais ou menos do mesmo jeito. É poder partir sabendo que o principal vai dar certo.

Vantagens? A principal, como o Paulo salientou, é que o sistema redundante fica naturalmente mais desacopladinho e para mim mais fácil de entender.[/quote]
Nessa parte eu já pude vivenciar algumas coisas. Nas férias passadas, quando estudava Java, eu notava que o desenvolvimento em geral era muito bem feito (mesmo eu não sabendo o que fazia direito). Eu sempre escrevia as classes de teste antes de terminar a classe “real” (dica do livro Head First).
O problema foi que, com as aulas da faculdade, 200 trabalhos pra implementar e escrever, é complicado. Como vocês lidam com o tempo, se ele for curto, de fazer os testes dessa forma? Eu concordo que é mais rápido do que testar depois da classe pronta (a isso sem dúvida alguma). Mas leva muito tempo?

Abraço.

Esse link discute estilos de TDD:

[quote=Bruno Laturner]Então Sérgio, por onde você começa um teste, como o faz no dia a dia? Como o caso de uso se transforma em testes?

Pergunto por que os casos podem ser muito gerais ou num nível muito alto, sendo que os testes mais unitários são aqueles que estão lá em baixo na cadeia, testando a base do sistema. Como você identifica as tuas unidades?

Disse que o desenvolvimento é de “dentro para fora”, mas é necessário ter uma boa visão de tudo antes de escrever teu primeiro teste.

Tem alguma macete/dica para começar com os testes ou é só com a experiência?[/quote]

Na realidade eu também ando à procura do mesmo que vc. Me custou muito tempo diferenciar entre TDD e Programação Orientada a Teste ( que nada mais é que boa OO + JUnit da vida) por isso fiz questão de explicar a diferença.

No projeto MiddleHeaven que tou conduzindo no tempo livre uso o TDD para implementar as features. Na realidade uso uma mistura. Eu tenho o modelo ± na cabeça e uso os testes para experimentar na prática. Não são testes exaustivos. (como falei, esse não é o objetivo do TDD). Eu acho bastante util porque força o desacoplamento quer vc queira ou não :slight_smile: As minhas unidades são normalmente conjuntos de classes (mini API) ligadas por herança ou delegação. (de novo, aqui eu estou preocupado com o desenvolvimento, não com cobertura) e esta “inspeção” de desacoplamento é muito importante quando se constrói um framework.

Cobertura tb acho um porre. Como o Luca tb irrealista na prática, embora na teoria seja excelente se for alcançado. É um excelente trabalho de voluntariado :wink: (ou para um equipa de testers. Se vc tiver uma)

No trabalho a política não é muito orientanda a TDD ou qq DD na realidade, então eu somo esses conceitos sempre que posso. É um work in progress na realidade. ja que como são filosofias, ha um trabalho de convencimento. Normalmente testamos as classes mais criticas ou as que são mais complexas ou mais centrais ( normalmente classes do tipo Services do DDD). Mas não todas e não ha uma procura real de cobertura 100%.

Eu acho POT e TDD muito util, mas dificil , custosa e demorada. Os resultados são otimos, mas ha muito tempo sendo investido. Não sei se, na balança, realmente compensa…

Aí que eu queria chegar. Eu posso não usar mocks o tempo todo como eles são do lado do teste (mocks de biblioteca, como jMock), mas de alguma forma e em algum momento eu preciso simular meus recursos externos (como BD), e isso não é raro.

E uma classe que simula o real, no meu entendimento, não deixa de ser um mock também!

[/quote]

Ai é que está. Eu acho que deixa. O objeto mock é especificamente artilhado para o teste. Quando vc usa uma implementação diferente isso não é um mock. Por exemplo, usar um repositorio que guarda em memoria em vez de um que grava no banco não é usar um mock.
Vc usa o mock quando ele está vinculado ao teste. Por exemplo, ele contem atributos, que será alterado espeficicamente pelo/para o teste e depois vc vai lá , ler esse campo e ver se tem o valor certo.

então, enquanto o uso de implementações diferentes dos mesmos serviços é comum, o uso de mocks (objetos especiais destinados explicitamente ao ambiente de teste e nunca ao de produção) são raros.

[quote]Andre Brito
Concordo. IMHO, tópicos desse tipo é que fazem com que bons desenvolvedores ainda estejam aqui no GUJ. ++[/quote]

Concordo plenamente estou acompanhando e colocando os blogs indicados no meu favoritos.

Paulo, vi que a última postagem no blog da Caelum foi sobre Integração Contínua, que cai bem no tema que temos aqui.

Como vocês fazem aí na Caelum para transformar idéias ou casos de uso em testes? Qual o pontapé inicial? Fazem uso de BDD?

Sobre a entrevista do Knuth, acho que às vezes os testes podem mascarar maus programadores…tipo, o cara programa se preocupando apenas em fazer o código passar no teste, e acha que a barra verde do JUnit é por si só sinônimo de código de qualidade…

Acho que existe um certo exagero de pessoas que vendem o uso de testes como algo incrível, como se isso fosse redimir os maus programares, e a questão da qualidade do código fica meio de lado…

[quote=renato3110]Sobre a entrevista do Knuth, acho que às vezes os testes podem mascarar maus programadores…tipo, o cara programa se preocupando apenas em fazer o código passar no teste, e acha que a barra verde do JUnit é por si só sinônimo de código de qualidade…

Acho que existe um certo exagero de pessoas que vendem o uso de testes como algo incrível, como se isso fosse redimir os maus programares, e a questão da qualidade do código fica meio de lado…
[/quote]

Ao meu ver a qualidade do código melhora por que melhorar é a maneira que dá menos trabalho. Testes forçam a melhora.

[quote=Bruno Laturner]É, caio no mesmo caso do Victor, o código que pego é quase sempre de manutenção. Apesar disso não acho que esse é o maior problema.

Por aqui a arquitetura é o famoso BOLOVO, orientado ao banco de dados. O problema é que não sei testar algo onde o endpoint é sempre o BD, onde as operações são sempre “… do/no banco”, verificar se tal dado existe no banco, trazer várias coisas do banco, associá-las, e mostrar na tela, inserir, alterar… Os dados sempre vem e vão para algum lugar.
[/quote]

Quem bom que vocês estão olhando para TDD porque este é um dos problemas que a técnica evita. Quando você precisa de um mock de DAO (ou equivalente) para testar sua classe Usuario você percebe que tem algo errado nas suas responsabilidades.

Para introduzir testes num sistema deste tipo (o que é diferente de introduzir testes ao time, como o Paulo falou) ter um ambiente que faça isso automaticamente é crucial. Geralmente ao testar código que não foi escrito com TDD começa-se por fora, com testes de alto nível (funcionais) para depois cair na integração e unidade.

No dia a dia de um profissional acostumado com testes o que você faz geralmente é criar os testes de alto nível primeiro. Eles vão falhar e para que passem você vai ter que identificar os colaboradores. Você não acha os testes, acha as classes (no caso de Java) então o processo é o mesmo.


[quote=cmoscoso]
Em se tratando do ambiente, eu concordo quando o sergiotaborda diz “TDD é um processo moroso e pouco ágil…” mas ao mesmo tempo é a estrategia mais eficaz que conheco pra desenvolvimento que envolva mais de 1 programador. Isso inclui code ownership, CI e tudo aquilo que TDD compreende alem de testes do desenvolvedor. Este ultimo principalmente acho util no modo solo mas TDD como todo nao oferece tantos beneficios evidentes.[/quote]

Essa é uma afirmação curiosa, imho. Se eu uso Test-Driven Development eu crio um mínimo de confiança no código que estou escrevendo imediatamente, se eu não uso TDD eu ainda vou precisar ter este mínimo de confiança. Como vou obtê-lo? Será que no final eu não vou acabar tendo que testar manualmente o sistema toda vez que fizer qualquer alteração? Será que eu não vou acabar não testando boa parte das alterações?


Acho que está faltando um conceito importante aqui: você não cria mocks de código que não é seu. Não se cria mock de JMS, não se cria mock de JDBC nem de Hibernate. Você isola a dependência em classes que agem “na fronteira” e usa testes de integração nelas.

Não quis falar nada, mas pensei na mesma coisa. Comparado com outros tipos de testes, TDD parece ágil (ou menos lento, sei lá o termo).
Sem contar que, se testar do jeito que o shoes falou (do jeito em quotes), imagina a quantidade de erros que podem surgir e o tempo necessário pra corrigir cada erro…

Abraço.

Phillip,

Se nao tem outras pessoas pra compartilhar, comunicar e integrar codigo sobra TDD pelo fato de escrever o teste antes do codigo. Mas esse isolado é o aspecto menos importante do TDD na minha opiniao. O mais importante é encorajar as melhorias no codigo sendo desenvolvido. E a confianca necessaria pra esse “pitstop em movimento” vem da cobertura de testes, independente de ter sido obtida escrevendo teste antes ou depois do codigo testado.

Não quis falar nada, mas pensei na mesma coisa. Comparado com outros tipos de testes, TDD parece ágil (ou menos lento, sei lá o termo).
Sem contar que, se testar do jeito que o shoes falou (do jeito em quotes), imagina a quantidade de erros que podem surgir e o tempo necessário pra corrigir cada erro…

Abraço.[/quote]

Achei que isso ja tivesse ficado claro mas TDD != de se ter testes unitarios.

Eu nao diria que TDD é agil mas continuo achando que ele compensa no medio/longo prazo e na maioria dos projetos profissionais.

Não entendi sua resposta. Tentando colocar meu comentário em outras palavras:

Seja com 1 ou 100 desenvolvedores você tem que testar o que está fazendo. Se você não fizer TDD vai ter que ter testes da mesma maneira, só que provavelmente de uma maneira menos eficiente. Supondo que você concorde com isso, qual a opção à ‘morosidade’ e ‘baixa agilidade’ de TDD?

Acho que ninguém que contestou sem comentário implicou que TDD é sbre testes unitários. A questão é: a parte ‘morosa’ que você tem com TDD vai ter que ser feito de qualquer modo, então será que é TDD que é ‘pouco ágil’?

Reendo, acho que entendi a primeira parte, apesar de não responder minha questão (por isso não apago minha mensagem anterior).

Isso não é verdade. TDD, seja praticado por um time de uma ou trezentas pessoas, afeta o design do código. Como você mesmo notou TDD não é sobre testes e-seja aplicado solo ou em equipe- é uma técnica de design.

Como eu falei se vc tem 1 desenvolvedor fazer TDD se resume a nao haver codigo sem um teste falho. Querendo ou nao isso é uma restricao e considerando que meu objetivo final é entregar software funcionando, nao consigo imaginar como isso poderia resultar em um processo mais eficiente. Deve ter algo que nao estou vendo.

[quote=pcalcado]Reendo, acho que entendi a primeira parte, apesar de não responder minha questão (por isso não apago minha mensagem anterior).

Isso não é verdade. TDD, seja praticado por um time de uma ou trezentas pessoas, afeta o design do código. Como você mesmo notou TDD não é sobre testes e-seja aplicado solo ou em equipe- é uma técnica de design.[/quote]

Por esse lado vc tem razao. TDD é uma forma de levar o programador a criar um bom design, principalmente com baixo acoplamento entre os objetos.

Entendo, mas nas pesquisas que eu fiz sobre TDD achei esse link da ImproveIT de testes de unidade com Mock Objects, e um dos exemplos do EasyMock ele faz um mock de um HttpServletRequest

private HttpServletRequest requestMock() { HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getParameter("login")).andReturn("patricia"); expect(requestMock.getParameter("senha")).andReturn("floresta"); expect(requestMock.getRequestDispatcher("bem-vindo.jsp")). andReturn(requestDispatcher()); replay(requestMock); return requestMock; }

Decididamente, HttpServletRequest não é um código meu. O exemplo está errado OU falta alguma coisa a esse conceito?

Obrigado.

Vou tentar argumentar com um exemplo. Suponha que você esteja implementando uma mudança numa classe que conecta com um servidor qualquer, antes ela conectava em http://123.com e agora vai conectar em http://321.com

  1. O ciclo com testes é:
  • Crie o teste
  • Escreva o Código
  • Teste Manual de Sistema
  1. O ciclo com testes e sem TDD é:
  • Escreva o código
  • Crie o teste
  • Teste Manual de Sistema
  1. O ciclo sem testes é:
  • Escreva o códio
  • Teste Manual de Sistema

Então, a menos que você escolha a opção #3, onde não existem testes de unidade, você vai ter o ciclo “moroso” da mesma forma, seja acotnecendo antes ou depois e com qualquer número de pessoas no time.

Supondo que concordemos que #1 e #2 são as únicas opções de processo com qualidade minimamente aceitável (i.e. precisamos de testes unitários) então onde TDD seria menos ágil que a opção 2? Se a opção 3 for usada estamos discutindo o valor de testes unitários, e não de TDD.