Executando testes de unidade continuamente com Infinitest

Testes automatizados são muito importantes. Quando bem feitos e em número suficiente, passamos a ter uma garantia de que nosso código faz o que deve (e continua fazendo depois de alterações).

Além disso, há uma forte influência na direção de uma boa modelagem, ainda mais quando usamos TDD. Ao aplicarmos o ciclo de Falhar-Passar-Refatorar do TDD, passamos menos tempo debugando e encontramos bugs o mais cedo o possível.

Porém, para colhermos as vantagens dessas técnicas, precisamos lembrar de executar nossa suíte de testes DEPOIS DE QUALQUER ALTERAÇÃO. Esperarmos até o servidor de integração contínua avisar-nos é tarde demais. E como costumamos dizer aqui na Caelum: se o programador precisar de lembrar, pode ter certeza que ele vai esquecer.

Quando demoramos para executar nossos testes, mais erros podem acumular-se. Ao descobrirmos as falhas nos testes, o contexto do que estávamos fazendo não estará mais tão claro. É provável que passemos mais tempo debugando e “caçando” a raiz dos defeitos.

Testando a cada alteração

Para evitar que o programador precise lembrar de executar a suíte de testes sempre que alterar algum código, foram criadas as ferramentas de teste contínuo. Apenas aqueles testes que foram afetados pelo código modificado serão executados, de maneira a minimizar o tempo de execução dos testes. Em Ruby há ferramentas como o watchr, em Python temos o sniffer e em Java temos o Infinitest.

O Infinitest tem plugins para o Eclipse e IntelliJ. Observe a execução em um projeto no Eclipse:

Infinitest executa testes automaticamente

Perceba que ao alterar a classe GeradorDeRecibo, somando 1 ao total, o canto inferior da tela passa a ficar vermelho, sinalizando que algum teste quebrou. É exibido também o número de testes executados (1 test cases ran). Só um teste foi executado, apesar de existirem outros no projeto.

A classe GeradorDeReciboTest é marcada com um erro exatamente na linha onde ocorreu a falha no teste. O detalhe do erro mostra que era esperado um 2.0 como total, mas veio 3.0.

Dica: execute apenas os testes de unidade com o Infinitest

Logo a recompilação do código pelo Eclipse, o Infinitest analisa as mudanças e executa apenas os testes afetados. Porém, existem diferentes níveis de testes: unidade, integração e sistema. Testes de unidade são rápidos: uma suíte completa é executada em alguns segundos. Já os de integração e sistema são mais lentos, porque acabam testando mais coisas.

Por isso, é ideal configurar o Infinitest para executar apenas os testes de unidade. Para isso, crie um arquivo infinitest.filters na raiz do seu projeto e coloque expressões regulares que peguem o nome das classes que você quer excluir.

Por exemplo, se você quiser excluir todos os testes de DAOs, exclua o pacote com:
br\.com\.caelum\.dao\..*.

Se desejar excluir todas as classes terminadas com ITest (padrão usado pelo plugin failsafe do Maven), coloque:
.*ITest.

Dica: é bom mesmo ao refatorar

Ao criar novos testes (e novas funcionalidades), tenho a tendência a ignorar os testes vermelhos. Talvez o ideal seja deixar seus testes quebrados o mínimo possível. Mas confesso que não tenho essa disciplina.

Agora, ao refatorar, seus testes nunca deveriam quebrar. Tudo deve ficar sempre verde. Nesses casos, executar continuamente seus testes de unidade vale muito a pena!

Tags: ,

8 Comentários

  1. Raphael Almeida 25/07/2016 at 09:58 #

    Esse plugin é bacana mesmo, já usei bastante em dojos.

  2. André Thiago 25/07/2016 at 21:35 #

    Muito bom o post. Não conhecia o Infinitest. Vou começar a usá-lo.

  3. Rafael Ponte 26/07/2016 at 01:36 #

    Opa, muito bacana o post, Alexandre. Realmente não conhecia este plugin, embora conheça os “watchers” do Ruby usado em DOJOs da vida.

    O que fiquei mais curioso é que mesmo em projetos Maven eu nunca usei o plugin Failsafe. Sempre rodei meus testes de integração logo após os testes de unidade, no entanto sempre separo os tipos de testes (unit e integration) em diferentes source-folders em vez de mudar o sufixo da classe de testes para “ITest”. Requer uma configuração a mais no Maven mas funciona de boas.

    Você tem usado o Failsafe em seus projetos? Ver alguma grande vantagem na abordagem dele?

  4. Alexandre Aquiles 26/07/2016 at 07:25 #

    Fala, Rafael!

    Acho que a vantagem do Failsafe é que it just works. Só mudar os nomes dos testes.

    E, acho que você viu, rodam numa fase posterior do Maven, a verify, depois das fases de integration-test e também de package.

    Apesar do nome das fases, seria mais pra testes de sistema, que precisam do war (ou jar) pronto, deployado em um app server com BD num estado conhecido.

    Dito isso, acho que o que você faz é melhor: source folder separado deixa mais fácil executar os testes pelas IDEs. Só tem que configurar…

    Ah, já vi um pessoal colocar os testes de sistema como um outro projeto, outro sub módulo do Maven. Acho que fica legal e explicita que é um cliente do código de produção. Mas requer mais configurações ainda…

    A prática mais comum que vejo nos projetos que tenho acesso é deixar testes de unidade e integração juntos e de sistema em source folder separado.

  5. Raphael Lacerda 26/07/2016 at 13:40 #

    Deixar o teste de sistema no mesmo projeto é overkill demais.

    Imagina o seguinte, vc está com o projeto deployado, rodando no servidor e vai fazer um teste de sistema. Quando vc mexe na classe de teste, o servidor vai restartar pq houve alteração de algum .class no projeto. Mas é um .class que não necessariamente tem a ver com o projeto, pois é teste.

    Também vc tem que configurar o jetty embarcado para deployar sua aplicação em tempo de execução no servidor de integração para rodar os testes. Isso não é fácil, aliás, não constuma funcionar fácil.
    Além disso, vários casos de testes que funcionam em servidor de interface gráfica mas não funcionam com o xvfb em servidor headless. Mas nesse caso, afeta as duas opções.

    Por fim, esses testes são demorados demais, aumentam demais o tempo de build e além disso, quebram fácil. Ficar esperando um bom tempo e ver seu build quebrar por algo não relevante é tenso.

    Eu costumo separar os testes de sistema em um outro projeto, pra mim há mais vantagens.

    Quanto a separar os testes de integração, eu também constumo fazer igual o Ponte, separo em source folders diferentes e adiciono a configuração no pom.xml

    Mas nesse caso, não consigo analisar pros e contras, talvez fique melhor separado, você pode fazer customizações específicas para o teste de integração

  6. Raphael Lacerda 26/07/2016 at 13:42 #

    Alexandre, vc que apresentou o infinitest e eu desinstalei por algum bug chato que ele tinha na integração com o Eclipse.

    Agora vou ter que instalá-lo novamente para lembrar! hehehe

  7. Felipe Romani 28/07/2016 at 10:59 #

    Galera alguém conheça uma solução para PHP?

Deixe uma resposta