Uma belíssima explicação porque teste unitários sucks!

http://www.contrariansoftware.com/2008/11/unit-testing-sucks.html

Concordo com tudo 100%.

Principalmente com isso:

O famosa arquitetura boneca russa… Só quem já sofreu na mão dessas bonecas sabe o que eu estou falando…

Yeahh…

Nice post… I agree at some points…
and, I don´t have much knowledge in TDD…

But one thing in sure: it´s better to write a code to test another,
than to test on the UI all the time.

I recently work on a Library software (actual, fisical library… books and stuff)…
Had ALOT of “merged” logics… JUnit and Mockito help me in a way that i can´t describle.

Well… keep it up

***Vou traduzir pra não ter problemas, apesar de não precisar (só quem sabe ingles poderia comentar o topico…)

Gostei cara,
mas na verdade é muito melhor escrever um código que testa outro, do que ir, rodar a aplicação e testar na unha…

Estava desenvolvendo um modulo para controle de bibliotecas…tinha mta logica unida com outra… JUnit
e Mockito me pouparam algumas horas de testes …

abraços

Primeiro, ele afirma que o programador tem uma intuição natural para perceber quais partes do código são mais sujeitas a erros e que dessa forma ele codificaria essas partes com mais cuidado, evitando assim os bugs. Isso é um absurdo. Se isso fosse verdade, não existiria bug em software…

Segundo, ele fala que a interface gráfica é a parte mais importante de um software e a mais buguenta. Isso é uma sandice tão grande que dá pena. A interface gráfica é importante pra cacete, mas o que mais importa é o domínio essencial da aplicação. A interface gráfica vai se entupir de bugs se você enfiar as regras de negócio dentro dela, como ele parece sugerir.

Terceiro, ele diz que testes unitários introduzem bugs por aumentarem a complexidade do código. Isso também é bizarro, porque testes unitários desenvolvidos em TDD tendem a diminuir a complexidade da interface pública e reduzir o número de dependências da classe. Isso aumenta a coesão da classe e reduz o acoplamento.

Quarto, ele diz que tornar uma classe testável por testes unitários exige que você use alguns design patterns complicando o design. Ele esquece de mencionar QUAIS design patterns. Será que ele sabe?

Bug existe com ou teste unitário.

Concordo com vc.

Com certeza ela não estava falando de TDD. Mas esse negócio de acoplamento pode ser um tiro no pé, as famosas milhares de camadas.

Ele tava falando do pattern DECORATOR.

Eu até tento, mas não consigo concordar com tudo.

Claro que é impossível testar todas as possibilidades. Mas isso não é razão para não escrever os testes. Além disso, o autor quer evitar empregar esforço escrevendo testes, mas ele não enxerga que no futuro terá que arcar com problemas no código que seus testes poderiam ter captado tranquilamente, se ele os tivesse escrito. A hora de pensar sobre o que pode dar errado com o seu código é o momento em que você o escreve, porque dois dias depois você mal lembra o que aquele código fazia.

Posso ter entendido errado, mas aqui o autor parte do princípio que ele nunca comete erros bobos de digitação de código, como escrever um método pra somar dois números e usar o sinal de multiplicação sem querer.

Aqui concordo com o autor - não se usa teste unitário pra testar interface.

Aqui é uma questão de opinião. Eu definitivamente não acho que escrever testes unitários seja “boring”, e muita gente que usa TDD também não acha. Mas se o autor não acha legal, aí não tem argumento que o convença.

Usar TDD pode nos ajudar a ver o que está errado com nosso código. Ter que criar muitos mocks para testar um código pode ser sinal de bad smell. E o autor generaliza quando ele diz que provavelmente os erros descobertos pelos testes unitários são provocados pelo próprio uso de TDD. Sobre as interfaces, elas são particularmente úteis em linguagens com tipagem estática, como Java, mas não o são por causa do TDD. Programar orientado a interfaces é um princípio de desacoplamento, e as pessoas o seguem mesmo quando não escrevem testes.

[quote=tnaires]
Usar TDD pode nos ajudar a ver o que está errado com nosso código. Ter que criar muitos mocks para testar um código pode ser sinal de bad smell. E o autor generaliza quando ele diz que provavelmente os erros descobertos pelos testes unitários são provocados pelo próprio uso de TDD. Sobre as interfaces, elas são particularmente úteis em linguagens com tipagem estática, como Java, mas não o são por causa do TDD. Programar orientado a interfaces é um princípio de desacoplamento, e as pessoas o seguem mesmo quando não escrevem testes.[/quote]

Ele não criticou interface, que é fundamental e o que Java tem de melhor. Ele criticou o pattern DECORATOR (delegate) que busca desacoplar e isolar tudo nos sistemas a fim de facilitar os testes transformando o sistema numa zona incompreensível de bonecas russas. Eu já vi sistemas assim… é um pain-in-the-ass…

[quote=saoj][quote=tnaires]
Usar TDD pode nos ajudar a ver o que está errado com nosso código. Ter que criar muitos mocks para testar um código pode ser sinal de bad smell. E o autor generaliza quando ele diz que provavelmente os erros descobertos pelos testes unitários são provocados pelo próprio uso de TDD. Sobre as interfaces, elas são particularmente úteis em linguagens com tipagem estática, como Java, mas não o são por causa do TDD. Programar orientado a interfaces é um princípio de desacoplamento, e as pessoas o seguem mesmo quando não escrevem testes.[/quote]

Ele não criticou interface, que é fundamental e o que Java tem de melhor. Ele criticou o pattern DECORATOR (delegate) que busca desacoplar e isolar tudo nos sistemas a fim de facilitar os testes transformando o sistema numa zona incompreensível de bonecas russas. Eu já vi sistemas assim… é um pain-in-the-ass…[/quote]

Pois eh, Sergio, eu concordo plenamente com voce sobre a simplicidade de código e a complexidade que os design patterns trazem quando sao usados em lugares onde nao se precisa deles.

Eu ja vivi, na verdade ainda vivo (faltam muitos para remover), na pele o problema das bonecas russas, mas isso nao eh culpa da existencia dos patterns, mas do mau uso deles. O decorator, o template method, são exemplos classico do inferno que eles podem provocar, com camadas em cima de camadas, quando sao mal utilizados.

E os testes unitarios tem menos ainda a ver com essa desgraça toda. A unica coisa que eles exigem é codigo desacoplado. Mas qual eh o primeiro entendimento que os programadores tem quando se fala em código acoplado. Ah, vou desacoplar tudo, vou por mock e remover minhas dependencias.

Usar mock pra todo lado não eh desacoplar, eh sim uma confissao de que voce vai precisar viver com aquele acoplamento. Isso pode ou não ser verdade, principalmente em etapas transitorias de um refactoring em codigo legado. Por enquanto voce vai ter que viver com aquele acoplamento, entao o mock te ajuda. Mas voce não desacoplou porcaria nenhuma.

TDD nao precisa de design pattern “sofisticado”, eles não levam as bonecas russas de jeito nenhum e precisa de mock em pontos bem especificos o que não te torna dependente deles. TDD não é chato na minha opinião, bem pelo contrário e, uma vez que você tem os principios basicos OO bem definidos na sua cabeça é algo muito simples.

Mas se voce for fazer uma convergencia para ver para onde os problemas do testes que voce ja viu levam você vai identificar um mesmo ponto comum, a absoluta falta de conhecimento dos principios OO, só que aí o problema está em quem fez os testes, não nos testes em si.

Dont throw the baby with the bath water. Você está querendo culpar a chuteira porque o atacante do seu time não consegue fazer gol.

Eu acho muito justo e acho que voce tem todo o direito de não querer escrever testes, mas não é isso que vai fazer com que os testes sejam ruins.

Mais um cara que quer aumentar número de acessos e o pagerank do blog dele por fazer um crítica (bem fraquinha, na minha opinião) num conceito bem estabelecido.

Eu não entendo porque o pessoal gosta tanto de falar mal de testes automatizados… testes fazem parte do desenvolvimento, e se dá pra automatizar, por quê não? Vc vai ter que testar o código de qualquer jeito, se vc não escreve testes vai ter que testar na mão…

Você sabe que o erro existe e a solução, você pode consertar o erro e voltar a ser produtivo ou criar outro código com o único intuito de testar a solução que acabou de criar.

Acho que isso responde porque muitos preferem não automatizar.

Vc vai ter que testar o código de qualquer jeito. A vantagem de automatizar é que quando precisar testar novamente vc já tem tudo pronto :).

Na minha opinião testes a mão tem q ser feitos com ou sem testes automatizados. Eu acho q um da uma mão p o outro.

Na minha opinião testes a mão tem q ser feitos com ou sem testes automatizados. Eu acho q um da uma mão p o outro.[/quote]

Com certeza, teste com o sistema sendo executado tem que ter independente de haver ou nao teste unitario. A diferenca é o quanto voce consegue testar com um e outro.

Na minha opinião testes a mão tem q ser feitos com ou sem testes automatizados. Eu acho q um da uma mão p o outro.[/quote]
Com certeza, não dá pra dispensar teste manual. O meu ponto é: se dá pra automatizar algumas coisas, porque não? :smiley:

Acho teste unitário importante pra manter regras de validação dentro do esperado. Já pra automatizar testes à vera contra bugs, só mesmo teste funcional, com Selenium por exemplo, pois a interface gráfica é mesmo mais sensível a bugs, considerando tecnologia web, linguagem com tipagem dinâmica como javascript é muito mais propensa a erros inesperados se a complexidade da página for alta, com várias interações gráficas, etc.

Acho legal teste FUNCIONAL automatizado via JUnit. Obviamente não é porque usa o JUnit que é teste unitário né?

Já testes unitários acho que não se pagam. Entrava o projeto inteiro, cria uma burocracia absurda, qualquer alteração no código implica alteração no teste unitário, não pega nenhum bug importante só e não garante nada, etc. Minha opinião pessoal apenas.

Já testes funcionais são mais big-picture, documentam a sua API e te dão uma tranquilidade para saber que pelo menos as funcionalidades core do seu sistema não foram quebradas.

Selenium como vc falou é uma ótima mesmo!

Acho legal teste FUNCIONAL automatizado via JUnit. Obviamente não é porque usa o JUnit que é teste unitário né?

Já testes unitários acho que não se pagam. Entrava o projeto inteiro, cria uma burocracia absurda, qualquer alteração no código implica alteração no teste unitário, não pega nenhum bug importante só e não garante nada, etc. Minha opinião pessoal apenas.

Já testes funcionais são mais big-picture, documentam a sua API e te dão uma tranquilidade para saber que pelo menos as funcionalidades core do seu sistema não foram quebradas.

Selenium como vc falou é uma ótima mesmo!
[/quote]
Manutenção de testes unitários é um inferno mesmo, é bom ter um gerador de cenário. O retorno disso depende da criticidade da aplicação, tendo proveito em regras muito críticas que não podem falhar, onde traria grandes prejuízos pra empresa, como grandes multas, perda de vida etc, mas não acho proveitoso mesmo fazer teste unitário de tudo só pra dizer que fez, claro que teria algum retorno, mas muito pequeno diante do grande esforço. E com Selenium realmente temos o “teste do sistema” automatizado pra valer, não adianta ter teste unitário se o jquery falhar por algum motivo. Exagero nunca é bem vindo, assim como usar e abusar de Hibernate pra tudo no sistema, ao invés de usar só onde ele traz bom retorno.

Posso estar enganado, mas o autor do artigo não sabe fazer testes unitário. Por exemplo nesse trecho:

Rapaz, nenhum tipo de teste vai testar todas as permutações do seu código. Esquece. O teste unitário servem para testar métodos e se ele não consegue testar todas as permutações dos métodos dele, bom, o método dele tá fazendo coisa demais.

Bom, os teste unitários pegam alguns bugs sim, com um feedback bem rápido. Mas não é nem de longe todos os bugs possíveis, por isso temos outros tipos de teste como o saoj falou teste funcionais e talz. A grande sacada do TDD é que te ajuda com o design do teu sistema. Por exemplo, no caso do autor, os testes unitários estão mostrando pra ele que os método deles estão fazendo muita coisa e ele ao invés de entender e arrumar, ele prefere meter pau no TDD. Basicamente se tá muito difícil de manter ou criar um teste unitário no teu sistema, o teu design deve estar bem errado. Design errado não quer dizer que o sistema não funciona, design errado quer dizer que muitas para vezes para dar manutenção no sistema você vai sofrer pra entender o que tá acontecendo.

Isso aqui é parte da verdade. Se for um sistema Web, tu pode fazer testes unitários de javascript. Mas com certeza, tem outras ferramentas também, como o Selenium.

De novo, acho que isso é baseado na má experiência dele com testes unitários. O objetivo do TDD é deixar o teu código simples e de fácil manutenção e quando você precisa refatorar, você tem vários testes que garantem que você não quebrou nada (ao menos garante que o resultado que um determinado método esperava continua sendo o mesmo). Se ele acha perda de tempo, boring e complicado ele não está fazendo direito.

Para concluir deixar o Selenium testar tudo na sua aplicação é a pior coisa que você pode fazer. Os testes de Selenium não são muito confiáveis e explico o porque. Como o teste vai rodar na tua aplicação como um todo, ele vai acessar todos os pontos de integração do teu sistema. Banco de dados, Web Services e etc. Se algum desses serviços não funcionar direito, pode quebrar teus testes e confundir os desenvolvedores achando que foi o código deles que quebrou. Outra coisa, testes de Selenium demoram para rodar, afinal é como se fosse um usuário acessando o teu sistema. É muito fácil você ter teste de Selenium que demoram HORAS para rodar. Num projeto onde você tenha CI em que rodam os teus testes, o feedback para o desenvolvedor saber se o código dele tá certo ou não seria imenso. Somando isso a demora com teste não tão confiáveis é muito fácil pra equipe não ligar mais para esse tipo de teste. Já visso acontecer algumas vezes :frowning:

Selenium é uma ferramenta boa, mas para ser usada com cuidado. Tem que ser a última saída. Existem outros tipos de testes como teste unitários e de serviço. Aliás tem um artigo interessante do Martin Fowler falado sobre a pirâmide de testes. Pode dar uma olhada aqui

Sim tudo tem ser usado com cuidado conforme a real necessidade. Rodar testes no Selenium é naturalmente lento, mas não é algo pra ser rodado toda hora em checkins, mas sim no final de uma sprint, antes do deploy pra homologação, afim de pegar erros onde “não foi mexido”, já o que foi mexido e previsto de impacto teve seu teste feito e rodado individualmente após sua implementação finalizada por cada um da equipe, embora por garantia também serão rodados no final de tudo. Sobre algum serviço não funcionar, aí já é problema da infraestrutura manter a coisa funcionando com a mesma importância de um ambiente de produção. Se algo de ambiente falhar faz parte mesmo, mas o teste em si é confiável se houver tempo investido pra mantê-lo certo. Enfim, é tudo questão de usar ao nosso favor e não usar tudo por etiqueta.

[quote=javaflex]
Sim tudo tem ser usado com cuidado conforme a real necessidade. Rodar testes no Selenium é naturalmente lento, mas não é algo pra ser rodado toda hora em checkins, mas sim no final de uma sprint, antes do deploy pra homologação, afim de pegar erros onde “não foi mexido”, já o que foi mexido e previsto de impacto teve seu teste feito e rodado individualmente após sua implementação finalizada. Sobre algum serviço não funcionar, aí já é problema da infraestrutura manter a coisa funcionando com a mesma importância de um ambiente de produção, se algo não rodar faz parte mesmo… É tudo questão de usar ao nosso favor e não usar tudo por etiqueta.[/quote]

Você diz para executar só no final do sprint? Então o feedback tu só vai ter de duas em duas semanas? Acho um feedback looongo de mais. Tu só vai achar o bug no final do sprint e no outro sprint provavelmente vai ficar arrumando os bugs do sprint anterior.

E em relação a infra, tu não consegue controlar a infra de Web Service de terceiros, por exemplo. Outra coisa é que dependendo do porte do teu software não tem como tu manter um ambiente igual ao de produção no teu de testes. É simplesmente muito caro e complicado demais para fazer. Em software pequenos isso é plenamente acessível, mas em softwares muto grandes, muitas vezes, não é não.