Testando classes Java com Groovy

Um dos maiores desafios de escrever testes unitários em Java é fazê-los fáceis de ler e de manter.
É frequente termos que consertar um teste alguns meses depois que o fizemos e não mais lembrarmos o que ele estava testando. Seja porque negligenciamos o javadoc ou porque fizemos um código complicado demais ou ainda porque nomeamos nosso teste de uma forma pouco legível.

Veja que o segundo exemplo, apesar de mais verboso, informa exatamente o que o teste faz; nenhum javadoc é necessário.

Como melhorar a manutenibilidade dos nossos testes?

Um dos maiores problemas dos testes que vemos aqui na Touch Health é a falta de legibilidade. É saber o que de fato o teste faz e que cenário ele usa. Para modificá-lo é preciso antes de tudo entendê-lo e isso costuma levar tempo se o teste é complexo e ilegível.
Um código legível é aquele que consegue executar uma ação com o menor número de instruções possíveis. Como estamos falando de legibilidade para um ser humano, é importante que tais instruções sejam claras para uma pessoa. Não adianta um código ser curto e ilegível. O exemplo abaixo — em Ruby — retorna a quantidade de caracteres em um arquivo. Ele possui apenas uma linha, mas não é legível.

Como melhorar testes Java usando Groovy?

Groovy é uma linguagem que roda em cima da JVM e possui uma sintaxe bem similar à do Java. Ela possui recursos nativos bem interessantes que podem tornar nossos testes mais simples de escrever e de entender. Veremos alguns desses recursos a seguir.

Menor Verbosidade

Veja o exemplo de uma classe escrita em Java:

Agora compare com a mesma classe escrita em Groovy:

É fato que quase todo o código Java acima é gerado automaticamente pela IDE, mas ele introduz um ruído — caracteres que não acrescentam significado ao código — que não ajuda na compreensão. Pelo contrário, precisamos de um tempo para separar a parte do código que nos é relevante.

Veja mais alguns exemplos que o Groovy nos oferece:

Mocks

Testes unitários necessitam de mocks. Em Java, usamos bibliotecas como o EasyMock ou Mockito para construí-los. Em Groovy podemos fazer isso nativamente usando a técnica Map Coercion:

Se a interface a ser “mockada” tiver apenas 1 método, podemos usar a técnica Closure Coercion

Fluência

Algumas bibliotecas como o Hamcrest fornecem meios de tornar nossos testes mais fluentes e legíveis:

Podemos simplificar e dizer que um código com boa fluência é aquele que um ser humano entende com mais naturalidade.

Compare os dois exemplos abaixo:

O segundo exemplo possui uma linguagem muito mais natural para uma pessoa. Ele se assemelha à forma como nos comunicamos. Nenhum javadoc é necessário nele, já que é bem claro o que ele faz. O problema é que em Java não é possível escrever desta forma. Não nativamente pelo menos. Já em Groovy conseguimos fazer isso sem a necessidade de nenhuma biblioteca.

Vamos mostrar como escrever a instrução abaixo em Groovy: verifica que exame glicose custa 30.reais, e demora 3.dias

Vamos explicar de uma forma simplificada, mas se quiser saber mais, consulte aqui, aqui e aqui.

Precisamos usar uma técnica conhecida como Method Chaining — encadeamento de métodos -, que foi muito popularizada pelo jQuery.

No nosso teste, vamos começar pela sintaxe completa, sem remover os ruídos:
verifica(que).exame(glicose).custa(30.getReais(), e).demora(3.getDias());

Para isso, criamos a classe ExameAsserter:

Perceba que os métodos retornam this, o que nos permite usar o encadeamento.
Já podemos escrever:

Para conseguirmos escrever

Usamos ExpandoMetaClass para adicionar novos métodos à classe Integer:

Em Groovy, podemos simplificar a chamada de um getter fazendo:

Por fim, precisamos da closure verifica, que deve devolver um ExameAsserter

Com isso, já podemos escrever:

Métodos que recebem pelo menos 1 argumento não necessitam de parênteses. Podemos remover os ruídos e simplificar nossa instrução para:

Lembrando que o ponto e vírgula também é opcional.

Percebam como é simples criar instruções fluentes usando apenas recursos nativos da linguagem.

Outro utilitários

Groovy ainda possui outras facilidades como:

Manipulação de arquivos

Veja mais.

Datas

Coleções

Veja mais.

GStrings

Em Groovy, é possível interpolar variáveis e textos literais em uma string:

Veja mais.

Configurando o ambiente

Para configurar o suporte a Groovy em seu projeto Maven, adicione a dependência ao groovy-all e configure o plugin groovy-eclipse para que compile seus arquivos .groovy em bytecodes.

Conclusão

Com Groovy podemos escrever testes menos verbosos e mais legíveis.
Além disso, ganhamos utilitários para manipulação de Datas, Arquivos e Listas e uma api de mocks nativa.
A curva de aprendizado para quem desenvolve em Java é baixa, já que sua sintaxe foi baseada na linguagem da Oracle.

É possível usar Groovy para escrever códigos do seu próprio sistema e não apenas para testes. A integração com Java é trivial: é possível importar classes de uma linguagem em outra nativamente.

No artigo, focamos no uso de Groovy para testes apenas, pois é uma forma de conhecer o poder da linguagem sem ter que acrescentar riscos ao desenvolvimento do seu projeto.
Aqui na Touch Health, no entanto, desenvolvemos sistemas em ambas as linguagens.

E você, como faz para tornar seus testes mais legíveis e fáceis de manter?

Gostou? Não se esqueça de Recomendar e Compartilhar!