GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Cadê os testes?


#61

Se for aplicação web: watir e selenium.

Se não for aí vc pode usar Junit para fazer teste funcional.


#62

Já usou Watir em páginas Applet? Será que funciona? Conhece algum que funcione? Pois o Selenium não funciona.


#63

Então você acredita na maioria que não desenvolve software que se preze, ao invés dos programadores produtivos (não necessariamente gênios) que prezam pela sua arte?

Interessante...


#64

Encontrei essa outra aqui para testes funcionais java swing:

http://code.google.com/p/fest/

Tive que corrigir bugs na uispec4j para funcionar no linux e mesmo assim ela quebrou em outros pontos. (Ver página anterior)


#65

andredecotia

No site desse projeto aqui informa que funciona, tem que faer o experimento pra ver.
http://code.google.com/p/fest/
http://fest.easytesting.org/


#66

Não, você é quem acredita neles, embora goste de pensar que acredita naqueles que "prezam pela sua arte". A maioria faz software ruim e a maioria não usa testes e é essa maioria que você está defendendo.

Ok, os grandes mestres não usam testes unitários, logo é possível criar grandes softwares sem testes unitários. Mas a regra geral é que a indústria de software é uma merda e a indústria de software no geral não usa testes unitários. Logo se conclui que o fato de não usar testes unitários não é o que faz com que os mestres construam grandes softwares. Então há outras coisas no que eles fazem que permitem que eles construam grandes softwares.

Se você sabe do que se tratam essas outras coisas, parabéns, você não precisa de testes unitários. Se você não sabe, mas quer continuar procurando, direito seu. Só cuidado ao dizer que testes unitários são ineficazes e não ajudam a escrever código de qualidade porque o único argumento que você trouxe para defender a sua teoria foi o Donald Knuth dizendo que não gosta de escrever testes unitários.

Repare que a opinião do Sérgio e do Hélio é: Teste unitários não garantem qualidade de código. Enquanto a sua é: Testes unitários são ineficazes e não auxiliam a construir um código bom.

Ligeiramente diferentes.


#67

Cara, realmente eu não sei, mas para mim escrever teste antes do código já é tão natural que eu escreveria os testes de qualquer forma.

Sérgio, alguns pontos em que eu discordo de você aqui e eu vou ter que escolher precisamente as palavras para que não pareça maluquice.

Eu não discordo exatamente do que você diz, mas discordo do enfoque. A questão do esforço necessário pelo bem do projeto. Eu duvido sim da eficácia do método da forma como você colocou. E devemos sim discutir se é custoso manter.

Devemos sim discutir se é custoso manter os testes porque existem muitas outras coisas que nos tentam enfiar goela abaixo num projeto de software em nome desse mesmo bem a que você se refere. Não seria ótimo se você sempre tivesse toda a documentação do seu sistema atualizada e você soubesse que assim que precisasse era só dar uma folhada e aquela funcionalidade maluca, cheia de poréns estaria bem desenhada na sua frente, detalhadamente e bem da forma que você precisa para simplesmente alterar o que for preciso sem se preocupar com mais nada?

Isso é impossível, isso não vai acontecer nunca, em lugar nenhum. Mas ainda há muita gente que insiste nessa tese, e culpa sempre e invariavelmente a preguiça e a falta de empenho necessários para se manter toda a documentação atualizada. Mas o fato é que a expressão sempre avaliará "true", porque se a documentação não está atualizada, você é preguiçoso, como a documentação nunca está atualizada, você sempre é preguiçoso.

Em nenhum momento o cara pensa que fazer isso é como enxugar gelo e que vai chegar a maldita hora, por mais esforço que se faça, que a documentação estará desatualizada. (E nessa ânsia de se documentar tudo em UML, MER e sei lá o que mais, não se documenta nem a regra de negócio no bom e velho português mesmo).

E o mesmo acontecerá com testes unitários se forem feitos da forma como você propõe. Testes criados depois do código, embora mais importantes, sofrerão do mesmo problema. Cedo ou tarde, algum código urgente será deixado sem teste, e depois outro e outro e outro. Mas a culpa cairá sempre na preguiça do quem devia ter escrito o teste e não no fato do teste não poder ser escrito depois do código.

E a você é a prova disso quando diz:

Repare que você se inclui aqui, entre aqueles que não sabem vender, como também já admitiu que os seus sistemas têm bem menos testes do que deveriam, ou do que você gostaria que tivessem. Mas logo você que escreveu um texto tão bonito sobre a importância deles? Será que você não está se iludindo com o seu test harness tanto quanto os pseudo-gerentinhos-adoradores-de-cmmi se iludem com um projeto bem documentado?

Eu não acredito nesse esforço heróico pelo bem do projeto e que aquele que não quiser se doar pelo maldito test harness tem que arcar com as consequências. Isso não funciona, nem para nós mesmos. Ainda que acreditemos na importância, nós não vamos fazer esse esforço, simplesmente porque há coisas mais importantes nas quais devemos nos concentrar antes de ficar preocupado em escrever código de testes para funcionalidade já implementada. E escrever mais funcionalidades é uma delas, assistir televisão outra, postar no GUJ, almoçar com a esposa, jogar bola com o filho, cortar coqueiro do quintal do sogro...

O ponto crucial é: Enquanto você não colocar os testes unitários na sua rotina de desenvolvimento você não escreverá testes e você nunca vai colocá-los na sua rotina se tentar escrevê-los depois do código pronto. Escrever um teste para uma classe antes mesmo dela existir, alem de te ajudar a definir a sua interface publica, é escrever o primeiro cliente da sua funcionalidade, é experimentar, avaliar, mudar, opinar, escrever e errar, e errar de novo e mudar a interface, melhorar até finalmente acertar. Isso faz parte da sua rotina de programação, faz parte do que você chama de programar, até chegar o dia em que programar sem isso é estranho.

Por isso eu tenho tanta dificuldade em discernir o que é teste unitário do que é test-first do que é TDD, pra mim é tudo a mesma coisa, para mim tudo isso é programar. Escrever testes não tem que ser custoso, ninguém tem que se conscientizar de nada, ninguém precisa ser acusado de preguiçoso, nem precisa realizar esforço hercúleo nenhum pelo bem do projeto. Não tem custo, não tem preço, não tem nada. Enquanto você está programando os testes vão surgindo e você gosta deles, eles não são um fardo que você tem que se lembrar de carregar, eles fazem parte da sua atividade natural de programar.

Esse seu post e a forma como você chamou a atenção para o peso dos testes unitários fortaleceram bastante em mim a teoria de quem sem Test-Driven Development não é possível ter testes unitários de qualidade.


#68

Falou bonito aqui :smiley:
A velha conversa de "o prazo é apertado, não vai dar tempo de ______". Aqui você completa com qualquer boa prática, desde o básico do OO, criar classes para isolar responsabilidades, reusar ao invés de dar Ctrl-C Crtl-V no código, etc.
As pessoas têm resistência de aceitar que esses 15 minutos a mais não serão a causa no atraso do projeto, pelo contrário, servem para ganhar tempo. E não é aquela coisa teórica tipo "Ahhh no futuro a manutenibilidade do código bla bla bla", os benefícios são imediatos, sua funcionalidade realmente vai estar pronta e funcionando mais rápido.


#69

O ponto é o seguinte : não pode se pode negar a importância de ter documentação ou testes. Você comparou os dois e acho que é isso mesmo. Se cometem os mesmos erros nas duas áreas. A documentação é necessária. Os testes são necessários. Negar isto , para mim, é insanidade e demonstra falta de experiencia e profissionalismo. Agora, que aceitamos que é importante, vamos analisar como fazer.

O como fazer é que vai ditar o custo. Mas seja como for que vc for fazer o custo nunca será zero. E o custo zero é o que vc tem quando não faz.
O que eu argumento é que o custo pode ser zero, mas o risco aumentou brutalmente. Portanto não compensa. Mais vale investir em teste e documentação do que aceitar o risco.

Agora, quando eu digo "investir" eu quero dizer "investir" e não gastar. Criar documentação antes do software estar pronto é bobagem e é gastar (desperdiçar) dinheiro. Fazer o manual do usuário depois que o software está pronto é mais barato , possível e útil. Todos os equipamentos que vc compra vêm com manual. Ok, pode ser muito simples quanto uma página ou complexo como uma bíblia, mas tem manual. Porquê ? Porque isso agrega valor ao produto. Seu produto não irá ficar famoso se ninguém usar. Mas o manual, como tudo o resto é um artefacto opcional. Em projetos on demand, tlv não seja necessário porque o cliente não pediu, e se pediu, ele pagou o custo.

Portanto, testes é importante. Criar testes demanda investir dinheiro. O investimento compensa quando bem feito.
Negar que algumas destas fases é verdade é irrealista.

É possível fazer um test harness errado e mais caro do que deveria? claro. Assim como é possível fazer qq software errado e mais caro do que necessário. Quem vai fazer a diferença é o desenvolvedor. Por isso falei da ética envolvida e da preguiça.

O fato de um sênior não conseguir fazer um test harness não prova que é impossível, nem muito menos prova que não é necessário ou que ele não deveria tentar.

Os testes, tal como a documentação, não precisam cobrir 100% das coisas no dia 1. A escrita é incremental. Vc começa com o caminho critico e vai evoluindo dai. O fato do seu objetivo ser cobertura 100% , e o fato de vc saber que é inalcançável, não deve impedir vc de tentar. Pois se isso fosse assim, vc não trabalha com software para começo de conversa (porque todo o software só está pronto 100% com todas as features possiveis e imagináveis em infinito tempo).

Para mim só é enxugar gelo quando é mal feito.
Poderíamos argumentar que refactorar é enxugar gelo. Mas quando é bem feito, vc refactora 1 vez, 2 no máximo e não todos os dias.

Como vc acha que eu proponho ? Porque eu não propôs nada sobre o "como". O meu ponto é que simplesmente não é profissional de esquivar deles dizendo que são desnecessários ou que é tudo um complô para vender livros e que a complexidade da empreitada ou o custo também não são desculpas.E que é responsabilidade do desenvolvedor diminuir o custo e a complexidade.

Exatamente. O fato de eu ser ruim de testes e o meu test harness ser fraco e eu não conseguir convencer meus chefes da sua importância não significa que não sejam importantes e que eu posso simplesmente abandonar a ideia sob o pretexto que "eu não preciso disso". Eu preciso, é fato. Não vale a pena argumentar o contrário. O que vale a pena argumentar é como eu poderia ser mais proficiente nos testes / diminuir custos / vender a ideia melhor.

Eu posso me iludir sobre a simplicidade da iniciativa, mas não sobre a sua importância. Para mim é tudo sobre diminuir risco. E no caso especifico dos testes é também sobre dar um colchão de segurança e remover o medo que os desenvolvedores têm de mudar o que existe.

Nem eu. Por isso que eu falo que os desenvolvedores têm que encontrar formas de diminuir o custo e a complexidade. Não é uma questão de heroismo. É uma questão de ferramentas e processos. Mas mais que isso é uma questão de entender que não se pode dizer que não aos testes.
Como falei antes, Tamanho e Proporção. É isto que vai ditar, quais, quantos, como e quando os testes são feitos. Mas nunca se eles são feitos ou não.

Concordo. Isso é o conceito de Test-First.

Também concordo. Isso é o conceito de TDD (Test Driven Development). O meu ponto é que é possível modelar , avaliar, opinar, etc.. sem usar os testes - vc pode usar o próprio cliente normal para isso ou outras técnicas como design patterns , por exemplo. Ou vc pode simplesmente usar a cabeça e pensar nas opções. Eu concordo que usar os testes para modelar é legal, mas não é a única forma. Ao contrario do Test-First que é única forma. Um nega o outro ? Talvez, afinal usar o Test-First para fazer um teste meia boca é contraproducente. Mas ficar produzindo testes adoidado também é. Ou seja, o Test-First significa que vc tem que ter testes antes, mas quantos ? Quais ? um é suficiente ?

O meu argumento é: Não importam esses detalhes, isso faz parte do "como". O que importa é saber que se vc não faz test-first ( seja qual a forma for) vc está fazendo menos do que poderia. É como modelar sem usar design patterns, é possível, mas é menos do que poderia fazer.

Ótimo. E temos muito que aprender consigo. Isto não é ironia. O ponto é que quem não chegou nesse nível, não pode dizer que é irrelevante ou desnecessário só porque não domina a coisa. Mais que isso, deve entender que isso mesmo que deveria tentar atingir. É a mesma coisa do cara que não usa design patterns porque não sabe como e depois diz que é tudo baboseira e inútil.

Aqui que eu não concordo com vc. Sim é preciso conscientizar. Sim é preciso entender o curso, o risco, as vantagens. Sim é preciso deixar claro que o desenvolvedor não se pode esquivar do problema ignorando-o e se o fizer, isso é preguiça (profissional e pessoal).
Quanto ao esforço hercúleo , de fato, não tem que ser assim. Mas vc tem que estudar e entender das coisas para que seja e pareça fácil. Isso demanda esforço e muitos não querem pagar esse esforço.

Sim. É verdade. Sendo a palavra operacional "qualidade". Mas não o TDD dos livros. Esse é muito acadêmico, o TDD que vc falou de avaliar , modelar usando o código do teste e influenciando o design da unidade sob teste. Para mim o TDD é opcional porque existem outra formas de desenvolver, mas o test-first é vital. E se eu não faço isso no dia-a-dia é problema meu e a culpa é minha. A técnica é válida. Mas se eu não uso TDD isso é uma opção válida. Se eu não uso, não ha problema.

Resumindo: obrigar todo o mundo a fazer Test-First seria excelente (é a proposta do XP). Obrigar todo o mundo a fazer TDD é contra-producente.


#70

Desculpe, eu não havia entendido bem a sua ideia. Como eu disse, eu acho difícil não fazer a associação de test-firs com TDD. Nesse caso realmente concordamos em mais coisas que parecia.

Se voce fala em investimento no aprendizado eu concordo com você. Quando eu digo não tem custo, eu falo contra o frequente argumento de que para se escrever um software usando testes se leva mais tempo do que escrever sem ele. O feedback imediato que um teste unitário já pronto te dá eu acho pouco provável ser compensado por qualquer outra técnica. Escrever um método de teste é mais rápido que subir o servidor acessar a tela, navegar por entre os campos, entrar com os dados e só então verificar se funcionou ou não. Ok, técnicas e ferramentas, podem diminuir o tempo ou até eliminar a necessidade de alguns desses passos, mas dificilmente vai alcançar o tempo de escrever um método rapidamente e rodá-lo indefinidamente assim que desejar. São milésimos de segundos para cada execução.

Eu não sei exatamente o que você chama de TDD dos livros, ou se eu o pratico ou não. Mas eu não levo a regra de "não escrever uma linha de código antes que haja um teste pra ela ao pé da letra". Eu raramento testo por exemplo o meu controller (no caso do vraptor que uso, ou managed bean do jsf, ou o action do struts ou algo que o valha). Talvez eu esteja errado e alguém traga bons argumentos pra me desmentir, mas eu não ponho lógica neles a ponto de ser necessário testes. É um if-else aqui e ali, um try catch lá, coisa que para qual não acho valeria a pena mockar meio mundo só pra garantir que o catch está tratando a exceção corretamente.

Também não sei exatamente a que tipo de testes você se refere quando diz que test-first é importante. Se for quanto aos testes de aceitação, escritos antes código, eu concordo, são importantes, talvez até mais que TDD para definição de regras de negócio. A grande diferença deles para TDD é que eles não dão o mesmo feedback imediato e quando quebram, quebram em bloco o que muitas vezes não permite a identificação imediata do ponto que quebrou. Eu acho que testes de aceitação e TDD são complementares.

Se você fala de testes funcionais automatizados, quanto a esses eu confesso que ainda não achei um ponto ideal. Eu acho sensacional o Selenium e tudo que ele é capaz, mas ainda não encontrei a fórmula para trabalhar com este tipo de ferramenta. Os meus testes se quebram na menor alteração que eu faça, mesmo quando não deviam. Sim, eu sei, talvez seja falha minha e ainda pretendo me aprofundar mais nele, mas por enquanto tenho pouquíssimos testes com Selenium, justamente pelo altissimo custo de manutenção deles.

Quanto ao obrigar ou não é que é complicado. Eu estou trabalhando numa empresa há pouco mais de seis meses, quando eu cheguei não havia a cultura de testes unitários, eu fui por conta própria colocando testes nos pontos em que ia mexendo e incentivando os meus colegas a fazer o mesmo. Uns receberam bem, já conheciam a técnica de ler e ouvir falar, outros nem deram bola. Hoje um deles já programa usando testes, outros já estão bem adiantados e outros continuam não dando bola.

Mas a minha postura desde o início foi a seguinte: Eu escrevo testes, quem quiser também escreve, mas ninguém é obrigado a nada. E caso for mexer num ponto em que haja testes, pode deixar que eu cuido dos testes. Eu estou praticando TDD de forma absolutamente não intrusiva. O sistema hoje tem mais de 500 testes rodando todos os dias num servidor de integração contínua, a cada vez que alguem sobe código no repositorio os testes são executados, um build é gerado e colocado no servidor de homologação. 500 testes é pouco para um sistema daquele porte, mas é um começo, e o número cresce gradualmente, já que agora eu não sou o único que os escreve.

Mas o ponto que eu insisto com o pessoal lá de cima, que já percebeu os benefícios que os testes trouxeram é: eles tem que comprar a ideia, eles tem que gostar de fazer e incorporar a técnica ao dia-a-dia deles. Para isso acontecer a minha primeira preocupação é: não criar resistência. Não fazer com que os testes atrapalhem a equipe antes de começar a ajudá-la.

Por isso que eu acho complicado simplesmente chamar de preguiça uma posição mais cética dos programadores. Quantas idéias mirabolantes já surgiram e não deram certo? e só serviram como mais uma desculpa pra chamar programador de desinteressado, indiferente, preguiçoso, reacionário entre muitos outros elogios.

Quando você começa a deixar de se divertir com o seu trabalho a qualidade do que você está fazendo começa a cair. Levando isso em conta é que eu digo que ou você adora escrever os testes ou você não os vai escrever. Posso estar errado, mas é isso que me faz acreditar que só com TDD se pode escrever testes unitários. TDD é divertido.


#71

Essa foi a parte que mais gostei dessa quinta página.


#72

Po Amigo é assim que vc trata seu software?


#73

Este tópico me inspirou a voltar a escrever em portugues:

http://alemdocodigo.posterous.com/tdd-nao-aumenta-a-qualidade-do-codigo

Ao meu ver nenhuma prática garante qualidade de código diretamente. Porém existem muitas práticas (TDD, pair programming, peer reviews (ate pull request?), code conventions etc) que podem promover uma reflexão maior sobre o código e uma consequente melhoria na qualidade geral do software.


#74

Bom post !!!

Respondi lá:

"Esta reflexão sim é a chave para qualidade. XXXXXXX permite que eu reflita sobre cada comando, cada método, cada classe e escreva o melhor código que sou capaz de escrever hoje em dia."

No meu caso eu faço essa reflexão a cada tecla que pressiono de forma automática e contínua. No meu caso não é o TDD que me incentiva a fazer isso mas a IDE com easy refactory, o Java sendo uma strong typed language e o gosto pela programação.

Se não um computador poderia escrever código... :smile:

Substituia XXXXXX por qualquer coisa e seja feliz. :smile:


#75

Interessante o texto do Feathers. Sinceramente, é a primeira vez que eu vejo algum autor "condenando" o uso excessivo de mocks. Embora não me lembre de nenhum apoiando, os mocks sempre foram vistos como algo inerente ao TDD, quase que como vem junto.

E enquanto isso eu os evitava a todo custo. Só uso mock quando preciso simular acesso a recurso externo a aplicacao (diretorios, arquivos, bancos de dados), tento não criar mock de coisas que eu mesmo vou implementar.

É como eu disse láááá no começo do tópico: Não sei se isso é aplicável a todo mundo, não sei se quem programa um framework genérico tem essa possibilidade, mas eu uso mocks o mínimo possível.


#76

Aí é que está o ponto. De nada adianta fazer o TDD se os princípios de design OO não forem conhecidos pelo programador. Se você precisa de muitos mocks para escrever um único teste, isso significa que a classe testada possui muitas dependências e o acoplamento entre elas é alto. De fato, essa é a maior crítica que tenho lido e ouvido sobre TDD. É justamente o fato de que ela está sendo vendida e comprada como bala de prata, que basta escrever o teste antes e "puff", sai um bom design. Outro fato interessante: às vezes, para tentar vender testes automatizados como "divertidos" a impressão que tenho é que os autores escondem os testes de integração, que dependendo da situação, são mais apropriados como ferramenta de teste, mas são sempre mais difíceis de escrever e configurar.

E enquanto isso eu os evitava a todo custo. Só uso mock quando preciso simular acesso a recurso externo a aplicacao (diretorios, arquivos, bancos de dados), tento não criar mock de coisas que eu mesmo vou implementar

Interessante, pois a recomendação do Growing-Object-Oriented-Software-Guided-Tests é justamente mockar objetos de sua autoria somente, justamente, porque ao mockar APIs de terceiros, você não pode garantir o ccomportamento das mesmas. O mesmo vale para recursos como sistemas de arquivos, bancos etc. Ou seja, é o típico caso em que testes de integração podem funcionar melhor.


#77

Veja, eu posso estar errado, mas qual o sentido de eu mockar minhas proprias implementacoes se eu posso simplesmente instancia-las e ter testes integrados? Claro, uma requisicao http quando estiver testando um controller ou um dao quando estiver testando um servido que obrigatoriamente usa acesso a banco voce mocka (ou o próprio servico quando for algo um pouco mais complexo), mas mockar minhas próprias implementacoes?

De qualquer forma eu não li o livro que voce citou como exemplo, então podemos estar usando exemplos em contextos diferentes. Já anotei aqui o nome do livro, já está na lista para ser lido.

Talvez o que o autor seja algo como foi postado neste http://www.guj.com.br/java/278717-tdd-x-baixo-acoplamento tópico em que o teste não testa nada alem do mockito.


#78

Por exemplo, você tem uma classe X que representa um serviço, e quer testá-la unitariamente. A classe X por sua vez depende de um EntityDAO, porém, esse EntityDAO é uma interface (ou classe abstrata) com duas implementação JdbcEntityDAO e JpaEntityDAO. Você não quer usar as implementações reais pois o testes é unitário, você não quer conectar em um banco de dados. Nesse caso, você mocka o seu EntityDAO. Por sua vez, para testar as implementações do DAO você faz os testes de integração em separado, com um banco de dados reais, drivers reais, etc.

Nesse caso, você pode mockar seu EntityDAO tranquilamente, pois você pode garantir que todas as suas implementações cumprirão com o contrato declarado na interface, diferentemente de um EntityManager por exemplo, que pode apresentar diferenças de comportamento entre implementações diferentes ou mesm entre versões diferentes de provider.


#79

Entendi, e concordo com isso. Apesar de muitas vezes, principalmente quando estou lidando com codigo legado sem testes, eu mockar diretamente um entityManager ou outras interfaces externas.

Mas o que eu quis dizer é que só uso mock quando preciso acessar recursos externos. Normalmente eu tambem prefiro simplificá-los com interfaces minhas.

O problema clássico que vejo no uso de mocks e usá-los onde não deviam estar. Por exemplo, suponha eu eu tenho um processo que lê diversos arquivo de um diretorio, os processa transformando em determinadas informacoes, com validações, processamento de regras de negocio e etc... e depois guarda o resultado do processamento em um banco de dados. O que já vi muito acontecer é a cada passo do processamento, o código acessa o sistema de arquivos, aplica as regras de negócio, e atualiza o banco de dados. E repete o clico n vezes.

E quando se vai por testes não há a preocupação em separar as responsabilidades, fica tudo emaranhado, com chamadas a daos e acesso a arquivos junto com chamadas a regras de negócio. E quando vão testar não separam nada, simplesmente mockam tudo e a salada continua.

Repare que em alguns casos como este, eu sequer precisaria de mock, porque o que eu preciso de fato testar são as regras de negócio que irão "incidir" sobre os dados que vem do arquivo e vão para o banco. Se eu quero testar as regras pouco me importa de onde vem e pra onde vao, o que me importa é que chegando ali vão obedecer o que está determinado pelo meu código. E é isso que eu preciso testar, se eu conseguir isolar este ponto num subsistema a parte eu não preciso de mocks.


#80

É justamente esse o ponto da questão. Usar TDD/Mocks não exclui a necessidade de se conhecer os princípios de design OO.