Testes unitários / Mocks são realmente necessários?

[quote=Tchello][quote=jakefrog]Quando possível eu gosto de utilizar objeto real. Para teste de DAO por exemplo, eu gosto de utilizar HSQLD. O DAO irá se comportar como realmente deve.

Agora, se você tem uma classe que faz cobrança de cartão de crédito a um cliente… como você vai fazer se não tiver um mock? Ou algum simulador?

Acho necessário sim o mock, mas não para todas as situações.[/quote]

A operadora de cartão fornece simuladores.
Trabalhei em um sistema onde tínhamos que simular operações cartões de débito, bastava apontar pro servidor de testes e a operação era mockada pela operadora, não por nós, exatamente com o mesmo protocolo e toda a chatice.
Não sei dizer mais detalhes a respeito pq não fui eu quem desenvolveu isso, era manutenção apenas.[/quote]Maneiro. Vou pesquisar sobre isso. Valeu! =D

[quote=Adelar][quote=LucianoM86]Já usei muito mock em testes, mas hoje penso várias vezes antes de usar. Com o passar do tempo, a manutenção de testes com mock acaba ficando cada vez mais complicada e começo a duvidar da eficácia dos mesmos. Claro que existem casos (integração com sistemas de terceiros por exemplo) em que você acaba sendo obrigado a usar mocks, a não ser que possua um simulador do sistema.

Hoje prefiro que os testes sejam os mais reais e próximos da realidade possíveis, ou seja, de integração mesmo.[/quote]
Concordo. No início do projeto os mocks são mais produtivos, justamente pelo fato de poderem simular situações que ainda não estão totalmente implementadas. Já com o sistema implementado acho que o mais produtivo é realizar os testes das fases posteriores (sistema, aceitação, etc), que permitem verificar se o que deveria funcionar ainda está funcionando e o que devia ser feito realmente está sendo feito.[/quote]

Mocks nao sao produtivos nunca, eu acho. Eles sao necessarios em alguns pontos, mas nao se deve ter mocks espalhados para todo lado nos testes. Se voce tem ha algo errado (na maioria dos casos).

Esses tais testes de fases posteriores deixam passar coisas que os testes unitarios nao deixam (e vice-versa), pequenas alteracoes que causam efeitos colaterais em situacoes excepcionais, aquelas que raramente sao executadas e por tanto raramente testadas. Esses casos normalmente sao deixados de lado pelos testes tradicionais.

Testes de integracao tambem sao necessários, mas são pesados logo sao rodados com cada vez menos frequencia, o que demora cada vez mais para acusar um erro. E quando acusa, eles sao abrangentes demais e fazem com que voce precise debugar o codigo atras do erro. Testes unitarios e de integracao sao complementares, se voce tem um mas nao tem outro é bastante provavel que voce tenha um sistema propenso a falhas.

Interessante post que o Shoes fez em 2007 sobre testes: http://blog.fragmental.com.br/2007/10/31/programadores-profissionais-escrevem-testes-ponto-final/

Também ele fala sobre os testes nesta entrevista: http://www.revistawide.com.br/index.php/entrevista-phillip-calcado/

Testes são importantes, muitos erros você pega logo de cara, uma vez que você acostuma a programar testando dificilmente consegue voltar a velha forma de programar tudo e testar mais tarde.

Utilizo TDD atualmente em qualquer projeto que eu esteja, utilizo JUnit, Mockito, Selenium, também utilizo o Sonar para os padrões de qualidade do código e cobertura de teste, são ferramentas ideais e de grande auxílio quando estou desenvolvendo.

Quando comecei a utilizar TDD, notava que tinha dificuldade de começar pelos testes, era diferente do que eu estava acostumado, mas uma vez que você “pega a manha” de como faz, vc acostuma, vc sente falta quando não há testes, vc sente que aquilo não vai funcionar como vc quer.
Teste são importantes, fazem toda a diferença.
Com testes vem a refatoração, ou seja, você consegue melhorar a qualidade do seu código, torná-lo mais simples para futuras manutenções.

Montei uma pequena apresentação para o FISL de 2011 sobre o assunto, para quem quiser ler: www.slideshare.net/eduardo.bregaida/refatorao-de-cdigo-com-capito-nascimento-verso-completa

Abraços

Eu já trabalhei num sistema que um dos mocks seria tão complexo de escrever, que constituiria um projeto à parte. Foi mais fácil usar o equipamento diretamente.

Por mim, essa é mais uma situação onde mocks foram vendidos como “bala de prata”. Creio que seja o caso de avaliar. Em muitos sistemas CRUD, eu particularmente acho mais fácil e rápido subir um BD de testes na máquina de cada desenvolvedor, do que usar mocks em memória. Sem falar que o teste acaba ficando mais confiável.

Por isso, no final das contas, a resposta acaba sendo a de sempre: “Depende”.

[quote=Eduardo Bregaida]Interessante post que o Shoes fez em 2007 sobre testes: http://blog.fragmental.com.br/2007/10/31/programadores-profissionais-escrevem-testes-ponto-final/

Também ele fala sobre os testes nesta entrevista: http://www.revistawide.com.br/index.php/entrevista-phillip-calcado/

Testes são importantes, muitos erros você pega logo de cara, uma vez que você acostuma a programar testando dificilmente consegue voltar a velha forma de programar tudo e testar mais tarde.

Utilizo TDD atualmente em qualquer projeto que eu esteja, utilizo JUnit, Mockito, Selenium, também utilizo o Sonar para os padrões de qualidade do código e cobertura de teste, são ferramentas ideais e de grande auxílio quando estou desenvolvendo.

Quando comecei a utilizar TDD, notava que tinha dificuldade de começar pelos testes, era diferente do que eu estava acostumado, mas uma vez que você “pega a manha” de como faz, vc acostuma, vc sente falta quando não há testes, vc sente que aquilo não vai funcionar como vc quer.
Teste são importantes, fazem toda a diferença.
Com testes vem a refatoração, ou seja, você consegue melhorar a qualidade do seu código, torná-lo mais simples para futuras manutenções.

Montei uma pequena apresentação para o FISL de 2011 sobre o assunto, para quem quiser ler: www.slideshare.net/eduardo.bregaida/refatorao-de-cdigo-com-capito-nascimento-verso-completa
[/quote]

Interessante… mas creio que ninguém questionou a importância dos testes.
O questionamento está num ponto específico: usar ou não mocks nesses testes.

Qual é a sua opinião sobre isso, em particular? Ajudam ou atrapalham?

[quote=ViniGodoy][quote=Eduardo Bregaida]Interessante post que o Shoes fez em 2007 sobre testes: http://blog.fragmental.com.br/2007/10/31/programadores-profissionais-escrevem-testes-ponto-final/

Também ele fala sobre os testes nesta entrevista: http://www.revistawide.com.br/index.php/entrevista-phillip-calcado/

Testes são importantes, muitos erros você pega logo de cara, uma vez que você acostuma a programar testando dificilmente consegue voltar a velha forma de programar tudo e testar mais tarde.

Utilizo TDD atualmente em qualquer projeto que eu esteja, utilizo JUnit, Mockito, Selenium, também utilizo o Sonar para os padrões de qualidade do código e cobertura de teste, são ferramentas ideais e de grande auxílio quando estou desenvolvendo.

Quando comecei a utilizar TDD, notava que tinha dificuldade de começar pelos testes, era diferente do que eu estava acostumado, mas uma vez que você “pega a manha” de como faz, vc acostuma, vc sente falta quando não há testes, vc sente que aquilo não vai funcionar como vc quer.
Teste são importantes, fazem toda a diferença.
Com testes vem a refatoração, ou seja, você consegue melhorar a qualidade do seu código, torná-lo mais simples para futuras manutenções.

Montei uma pequena apresentação para o FISL de 2011 sobre o assunto, para quem quiser ler: www.slideshare.net/eduardo.bregaida/refatorao-de-cdigo-com-capito-nascimento-verso-completa
[/quote]

Interessante… mas creio que ninguém questionou a importância dos testes.
O questionamento está num ponto específico: usar ou não mocks nesses testes.

Qual é a sua opinião sobre isso, em particular? Ajudam ou atrapalham?[/quote]

Então Vini o próprio tópico tem a questão [quote]Testes unitários / Mocks são realmente necessários?[/quote]
O que eu tentei falar é que eu acho sim que ajudam, como eu falei acima e são muito importantes, depende da situação, apenas quis explicar melhor como me ajudou.
Mocks são muito interessantes, vejo mta gente reclamando que demora muito para fazer testes com Mock, mas temos que levar em consideração que um tempo maior de desenvolvimento acarretará em um tempo menor de manutenção.

Além disso os mocks nos ajudam a isolar as camadas, por exemplo camada de Negócio do projeto, eu quero testar algumas regras de negócio mas não quero que meu código acesse o banco de dados e etc, o mock serve exatamente aí.

Como vc msm disse, mocks não são “bala de prata”, não servem para todas as situações, tem isso também.

Bom espero que tenha ficado mais claro agora.

Abraços :smiley:

Ah bom, é verdade.
É que fui pelo artigo, não pelo título. :slight_smile:

[quote=ViniGodoy]Ah bom, é verdade.
É que fui pelo artigo, não pelo título. :)[/quote]

Entendi, eu respondi pq acabei dando uma geral na discussão aqui, dai achei interessante relembrar o post do Shoes rs.

Vlw Vini :smiley:

Esse assunto é mais polêmico que mamilos hehehe!

Mas vamos lá…

Pra mim os mocks são necessários sim desde que a sua implementação esteja correta. Existem casos de que quando um mock seja muito trabalhoso de se montar é por que sua classe(classe mockada) não foi corretamente implementada, ou se você tem vários mocks distintos para um método é hora de refatorar esse método fracionando para chegar o mais próximo do que o método deve (e só) realmente fazer.

No final das contas cabe ao desenvolvedor decidir usar o mock ou não.

Bom eu nunca usei mocks, na verdade trabalho em um ambiente sem cultura de testes, desatualizado, onde agilidade, boas práticas, inovação, passam longe. Até por isso, estou cumprindo meu aviso prévio lá e vou caçar uma vaga melhor no mercado.

Tenho estudado TDD por conta, estou lendo um livro e tenho mais 2 engatilhados para ler. EStou muito interessado por este assunto, o próprio conceito de mock, stubs, ainda não está 100% claro pra mim, mas está no pipeline de estudo.

Bom lá onde trabalho já integramos com diversos sistemas de terceiros. O que o pessoal costumava fazer era gerar uns retornos fakes no código mesmo para ter o que exibir nas telas, grids, etc…depois de bem adiantada a parte visual conforme o desenvolvimento ia andando eram gerados simuladores ou quando a integração era com banco ai o DAO buscava direto do banco mesmo, era gerada uma massa fake, etc…

Bom nessa experiência o que pude observar é que toda vez que o sistema ia pra homologação no cliente ou deploy em produção pipocavam erros que não aconteciam nos simuladores ou base fake pq assim como os mocks, e o cara disse lá na thread do Bill Burke:

“When you DO use mocks you are testing in an environment that is biased toward a passing test. An artificial environment will always make invalid assumptions about the behavior and stability of that environment.”

Bom eu acho que nesse ponto não tem muito o que fazer mesmo, é só testando a quente que a coisa vai ferver mesmo, é na base de produção que vai ter um cara lá com um nome escroto gigantesco truncado e o sistema não vai conseguir fazer o match em algum ponto. Ou vai ter um senhor lá com 103 anos de idade e algum infeliz fez alguma conta envolvendo idade pensando somente em 2 dígitos, etc…

Mas até aí, acho que o cara que inventou o mock, ou o teste unitário, ou o que quer que seja, nunca pensou em cobrir todos esses cenários, na verdade o que percebo é que alguns acham que o teste unitário é a verdade, “ah, deu verde, blz tá funcionando”. Não é bem assim. Na verdade estudando TDD percebe-se (se eu estiver errado me corrijam) que o simples teste em si depois de pronto é o que gera menos valor no processo, é o menos “importante” digamos assim, como li no livro de DDD do Jimmy NIlson, ele cita um colega dele que fala que o verdadeiro valor do TDD está no vermelho e não no verde.

Os testes são importantes e é extremamente necessário ter essa cobertura de testes (sejam feitos antes via TDD ou não) principalmente para refactoring, mas o resultado de um teste ao meu ver não é nem nunca vai ser algo 100% confiável.

Então o problema as vezes é que o pessoal gerencia mal as expectativas.

Sobre o que usar, como disse ainda estou estudando essas coisas etc, mas sou mais um na onda do “depende”.

Minha conclusão baseado no que usei é que simuladores e bases fakes muitas vezes mais atrapalham do que ajudam até pelo tempo que se consome para construir (simulador de web service por exemplo é um saco, mainframe então…), gera mais código para manter (depois de 2 anos vai um outro cara que não participou daquele desenvolvimento mexer em uma rotina que precisa do simulador, não funciona nada e demora 1 dia para descobrir que a base que tava apontando nem existe mais ou o banco migrou de servidor) então nos últimos projetos minha ideia era ou atuar em um legado o mais próximo possível da realidade como uma cópia da base de produção mascarada ou então usar uma solução o mais simples possível e gastar o tempo outrora gasto em construir essas porcarias para revisar melhor o código, discutir as implementações com os programadores, fazer pareamento, etc…

abs

O que me deixa mais feliz nessa discussão é que em um fato todos nós concordamos… Temos SIM que automatizar os testes!

Uma das vantagens que eu vejo nos testes unitários que eu não vi nas discussões propostas pelos Bill, é que eles ajudam e muito no design da sua aplicação…
Principalmente quando falamos sobre baixo acoplamento (entre classes e até com o proprio framework)!

Com testes unitários, temos a tendência sempre em pensar nas classes usando muito de IoC, especialmente injeção de dependência… resultando em classes com pouca responsabilidade (SRP) e bem coesas (SoC)
Pensamos assim, pois se nao fizer dessa forma, vc não será capaz de testá-la! simples! (A não ser que vc tenha um container para te prover essas dependencias)

Outra vantagem é que hj em dia é mto mais facil vc fazer testes unitários do q de integração… talvez algum dia, com as facilidades que ferramentas como o Arquillian trazem, os testes unitarios tornaram-se um pouco inúteis…MMMMMMMMMMASSSSSS, eu nao vejo como os testes de integração ajudam no design!.. Bom, vc já tem um container que irá startar e lhe prover todas as dependencias… até mesmo se o seu objeto estiver muito acoplado e fazendo muita coisa (mesmo aquelas q ele nao deveria fazer)

Mas bom… vamos ver como vai ficar…

Pois é Raphael, isso também me deixa feliz, mas o que deixa triste é o fato de um grupo bem restrito de profissionais ter esse conhecimento, se preocupar com esse tipo de coisa, se atualizar, etc…

Como disseram, você fala de testes ai nas consultorias da vida nego torce o nariz, só pensam em cronograma e custo, quando nós que atuamos com desenvolvimento deveríamos pensar em software como uma arte.

É foda cara, você pergunta para um médico, advogado, engenheiro, todos sabem citar pelo menos um autor famoso da área deles, já na TI ninguém sabe, ninguém lê.

Por isso que dou muito valor ao GUJ, aprendi muito aqui e continuo aprendendo, os assuntos vêm a tona em uma thread e aí dá para ir buscar informação na net, em outros sites, mas se nem o assunto surgisse, talvez eu fosse mais um desses caras que estão ai no mercado que por exemplo nunca ouviram falar em pattern por exemplo.

  • 1

Um dia desses escrevi algo aqui sobre como os desenvolvedores deviam procurar se esforcar mais em absorver a cultura de modelagem com TDD.

Entao, eu acho que eh justamente ai que esta o problema do mock. Quando o acoplamento eh alto o uso de mock eh bem mais frequente, o que torna os testes dificeis e chatos.

O problema eh que eh dificil reconhecer o problema no meu codigo e bem mais facil dizer que teste eh perda de tempo.

Sou a favor do teste unitário, desenvolver com TDD melhora o código, “expande horizontes” e evita erros.

Um fato indiscutivel é: se não é uma cultura da equipe… se os testes são “impostos” ao desenvolvedor… o teste é perda de tempo.

“pior do que uma aplicação sem teste, é uma aplicação com testes viciados ou desatualizados”. (não lembro o autor, não é conhecido mas eu concordo)

[quote=YvGa]
Entao, eu acho que eh justamente ai que esta o problema do mock. Quando o acoplamento eh alto o uso de mock eh bem mais frequente, o que torna os testes dificeis e chatos.

O problema eh que eh dificil reconhecer o problema no meu codigo e bem mais facil dizer que teste eh perda de tempo.[/quote]

Então… bacana o seu pensamento… mas em minha opinião isso não é culpa do mock… mas sim do seu objeto.

Se vc está tendo q mocar muita coisa, entra no q vc disse… está com acoplamento muito alto…

Só discordo com vc qndo vc diz q é dificil reconhecer o problema… em minha opinião não é…
aliás, o problema está mto bem descrito no setUp inicial dos seus testes

Testes unitários deveriam ser fáceis e divertidos de se fazer… se no setUp inicial dos seus testes vc esta tendo q mocar muita coisa, recebendo muitas dependencias no constructor do seu objeto, isso pode ser sinal de q vc nao esteja seguindo o SRP e SoC
Bom, mais um vez… teste unitário te ajudando no seu design

Mas como eu disse, a culpa não é do mock… ele é apenas um facilitador… resta agora nós sabermos utilizá-lo corretamente

Sou contra testes unitários. Na verdade entendi recentemente porque eu sou contra os testes unitários. Como tudo na vida, existem duas correntes diametralmente opostas no desenvolvimento de software:

1 - Teórica, que acha que complexidade indica que o programador é foda, que quanto mais classes e interfaces melhor, que as classes precisam ser isoladas e cheio de padrões GOF para serem bonitas, que bonecas russas é a melhor maneira de fazer software, etc.

2 - Prática, que acredita no princípio KISS, que não admite complexidade, que entende que deve ser fácil olhar apara um sistema e entendê-lo sem ter que fazer um esforço cerebral muito grande, que entende que o número de classes, entidades e interfaces de um sistema deve ser minimizado, que prefere uma hierarquia simples de heranca a bonecas-russas, etc.

Para o 1, teste unitário dá um alívio, do tipo: eu fiz um sistema gigantesco e complexo que nem eu mesmo entendo, mas pelo menos tenho um coverage de testes unitários em 90%. Na prática o quanto esses testes vão evitar bugs? Pouco. Na prática os testes unitários garantem a qualidade do sistema? Não.

Para o 2, testes unitários são totalmente desnecessários e um pé no saco. Como falaram aí em cima, é porque “esse grupo não entende nada de desenvolvimento de software”, UML, padrões GOF, bonecas-russas, etc.

[quote=Raphael Lacerda][quote=YvGa]
Entao, eu acho que eh justamente ai que esta o problema do mock. Quando o acoplamento eh alto o uso de mock eh bem mais frequente, o que torna os testes dificeis e chatos.

O problema eh que eh dificil reconhecer o problema no meu codigo e bem mais facil dizer que teste eh perda de tempo.[/quote]

Então… bacana o seu pensamento… mas em minha opinião isso não é culpa do mock… mas sim do seu objeto.

Se vc está tendo q mocar muita coisa, entra no q vc disse… está com acoplamento muito alto…

Só discordo com vc qndo vc diz q é dificil reconhecer o problema… em minha opinião não é…
aliás, o problema está mto bem descrito no setUp inicial dos seus testes

Testes unitários deveriam ser fáceis e divertidos de se fazer… se no setUp inicial dos seus testes vc esta tendo q mocar muita coisa, recebendo muitas dependencias no constructor do seu objeto, isso pode ser sinal de q vc nao esteja seguindo o SRP e SoC
Bom, mais um vez… teste unitário te ajudando no seu design

Mas como eu disse, a culpa não é do mock… ele é apenas um facilitador… resta agora nós sabermos utilizá-lo corretamente[/quote]

Quando eu disse que eh dificil reconhecer que o problema esta no codigo, eu estava me referindo aos que nao procuram melhorar as praticas, e com isso melhorar seu codigo. Acham mais facil apontar a hipotetica dificuldade de algumas tecnicas, nao reconhecendo que esta dificuldade vem justamente do seu codigo mal escrito, nao da tecnica em si.

No mais, concordo plenamente com voce.

Cara, eu concordo plenamente com voce sobre os seus dois casos, nao teria como concordar mais. Complexidade deve ser removida do codigo a todo custo, classes e interfaces tem que ter razao para existir, nao se deve utilizar padroes a nao ser que simplifique o codigo (que diminua a complexidade).

Resumindo, e abusando do seu exemplo para concluir meu raciocinio. Tudo que for feito no caso 1, deve ir até, e somente até, um ponto que nao comprometa o caso 2.

Agora a parte que eu discordo. Testes unitarios nao sao um pé no saco (pelo menos pra mim, eu acho mais facil e mais rapido desenvolver com testes) e muito menos desnecessarios, eles ajudam, e muito, a manter as coisas simples, varrem a complexidade, geram documentacao executavel e ainda dao confianca para ir em frente.

Testes unitarios garantem qualidade? Logico que nao, o que garante qualidade é a experiencia do programador, nada mais. Teste unitario é uma entre muitas ferramentas que estao disponiveis para escrever codigo de qualidade. Voce pode usá-la ou nao. Eu prefiro usar e insisto em dizer que quem nao gosta, normalmente nao gosta porque ainda nao se deu ao trabalho de estuda-la a fundo.

Em uma opiniao é uma das partes mais importantes ter os testes unitarios na aplicação, porque no dia que houver um problema ter-se-a uma base por onde comecar a verificar o erro.
Quanto aos mocks não sou a favor, mas deve-se fazer quando realmente for necessário.

Saoj, concordo com você em quase tudo…
Só acho que as vezes, por algum motivo, realmente precisamos criar a tal boneca-russa…
E em muitos casos os testes unitários realmente ajudam a ganhar mais qualidade.

Adotamos aqui da seguinte maneira:
Precisa desacoplar, o teste unitário será benéfico: Fazemos
É simplesmente um CRUD: Não fazemos

Já vi sistema que tinha mais classe de teste do que do sistema em si… e o sistema era buguento ao extremo…
Os testes passavam bem… o problema eram os bugs que ocorriam devido a sequência de interações feitas… Tinha-se muitos testes integrados também com Selenium, mas era praticamente impossivel prever todas as situações e no fim das contas a conclusão que cheguei é: Testes não fazem magica e pioram sua produtividade!

Hoje não concordo com processos tão engessados… tem de passar por 200 camadas para um print na tela… tem de fazer teste unitário para todas as classes… tem que usar DI e IoC em tudo… não pode ter herança… tudo tem que ser feito através de interface… acho que no final das contas o resultado é: o software demora mais para ficar pronto e a qualidade não é tão melhor assim! Tento achar o meio termo das coisas!