Testes integrados com Arquillian e Java

As Ferramentas da itexto

Este post inicia uma nova série de posts aqui em nosso blog: "As Ferramentas da itexto", na qual iremos esporadicamente apresentar aqui ferramentas que podem fazer toda a diferença no dia a dia do desenvolvedor e que muitas vezes são ignoradas pelo público.

Todas as ferramentas aqui listadas são usadas em nosso dia a dia: sendo assim podemos contar a vocês as principais vantagens e, principalmente, desvantagens de cada uma delas.

Naturalmente estes posts irão gerar mais receitas para que vocês possam tirar máximo proveito das mesmas. Sendo assim vamos lá!

O problema: testar aplicações Java EE ou Servlet based - especialmente projetos pré-existentes

Se você desenvolve aplicações Java que são implantadas em servidores de aplicação ou servlet containers você tem um problema: como realizar seus testes de integração de uma forma que seja o mais próxima possível do ambiente no qual seu projeto será executado?

A solução mais comum consiste na implementação de mocks ou tirando máximo proveito das ferramentas oferecidas pelo seu framework (o Spring, por exemplo, oferece um suporte a testes que é muito rico). Outra alternativa interessante é o uso de bibliotecas como Mockito.

O problema das duas soluções é que elas se aproximam do ambiente no qual a aplicação será executada, mas não são este ambiente. Não raro em diversas aplicações o servidor de aplicações contém uma série de configurações que influenciam na execução do projeto:

  • Datasources configurados por JNDI.
  • Filas JMS.
  • Bibliotecas compartilhadas.
  • A configuração dos próprios.
  • Mecanismos de autenticação configurados por JAAS.
  • Configuração de clusters
  • E todos os recursos que seu servidor de aplicações pode oferecer.
  • Bundles no caso de containers OSGi.

Pra complicar um pouco mais a vida, talvez você tenha um produto que precise ser implantado em diferentes servidores de aplicação e containers e precise validar todas estas variações. Mocks ajudam, mas não testam a coisa em si ainda. Aliás, olha que interessante o que tá escrito no site oficial do Arquillian:

Projetos legados

Talvez você tenha pego um projeto pré-existente para evoluir. Não são raros os casos nos quais a execução encontra-se intrinsecamente dependente do servidor de aplicações nos quais o projeto é executado. Pra estes casos Arquillian é uma solução bem interessante a ser levada em consideração.

O Arquillian

Uma solução para os problemas que mencionei acima é o Arquillian: um projeto inicialmente desenvolvido pela JBoss (agora Red Hat). No site do projeto deixam bem claro seu objetivo: escrever testes integrados. E é exatamente isto que ele consegue fazer.

No caso do Arquillian os testes integrados necessariamente envolvem o carregamento do servidor de aplicações (daqui pra frente quando usar o termo servidor de aplicações entenda que ele embarca também servlet containers). Ele automatiza a execução dos seus testes usando toda (ou quase) a infraestrutura do servidor que executará seu projeto:

  • Os mesmos datasources.
  • As filas pré-configuradas.
  • Usará as mesmas bibliotecas compartilhadas.
  • Se quiser, pode executar inclusive a mesma versão da JVM.
  • Enfim: o mesmo ambiente.

O Arquillian cuidará das seguintes ações para você:

  • Inicialização e finalização do servidor de aplicações.
  • Inicialização dos frameworks necessários.
  • Enriquecer os testes permitindo a injeção de beans nos mesmos.
  • Execução do seu código como cliente (excelente pra testar endpoints JAX-RS, por exemplo)

Sua execução é bastante simples e pode ser resumida nos passos a seguir:

  • Inicie o container.
  • Empacote o código que será testado e, na sequência, implante-o no container.
  • Injete o que for necessário nos testes (os beans) e execute-os.

Pra melhor entender o Arquillian você precisa de alguns conceitos.

Conceitos essenciais

O conceito fundamental do Arquillian é que você escreva seus testes contra o ambiente no qual a aplicação é executada, ou seja, com a aplicação já implantada no container.

Sendo assim o que o Arquillian faz essencialmente é empacotar nosso projeto, implantá-lo neste servidor e, na sequência, executar nossos testes contra este ambiente.

ShrinkWrap

Este é o processo de empacotamento do nosso código. Um dos componentes do Arquillian é o ShrinkWrap, que é o módulo responsável por gerar o pacote que contém o código a ser verificado e o implanta no servidor. Todos os formatos padrão do Java EE são suportados: WAR, EAR e JAR.

O ShrinkWrap é muito rápido: a velocidade na geração deste pacote chega a ser surpreendente. Em nossos testes com sistemas legados costumamos gerar o pacote completo (todas as libs, classes, recursos) para os testes integrados e este processo não costuma levar mais que alguns (realmente alguns) segundos.

No entanto ele não é feito para que você crie um pacote completo, mas sim um que contenha apenas o que realmente é necessário para a execução dos seus testes. É possível gerar um pacote JAR, por exemplo, contendo um único bean (um único arquivo).

Container

Consiste no servidor de aplicações ou Servlet Container responsável por executar nossa aplicação. Por padrão o Arquillian não virá com um container pré-definido (ele não tem). Você terá de incluir o container necessário como uma dependência de testes em seu projeto.

Esta "dependência" tem um nome: "container adapter". Você pode ver a lista completa de adaptadores neste link: mas já adiantando, há adaptadores para o Tomcat, Jetty, Websphere, Wildfly, Weblogic, JBoss, Glassfish e mais alguns outros.

O container no Arquillian se divide em três categorias:

  • Embarcado.
  • Gerenciado (managed).
  • Remoto.

Quando embarcado, o container será iniciado na mesma JVM que nossos testes. É o ideal para ambientes de integração contínua.

O gerenciado requer que a distribuição do container esteja no mesmo computador que o nosso código fonte. Será criado um novo processo para a JVM que será responsável por iniciar o container, implantar nosso código e, finalmente, executar nossos testes.

Externo ou remoto implica no container em execução em outra máquina (ou na mesma máquina, porém em um processo diferente). Todo o acesso a este container será feito a partir de chamadas de rede.

A diferença entre o gerenciado e o externo é sutil: o gerenciado é aquele que pode ser iniciado ou finalizado pelo nosso código de teste.

Executor

O Arquillian não é dependente de um framework de teste específico. Atualmente oferece suporte a JUnit e TestNG. Sendo assim você mantém todo o seu conhecimento na escrita dos seus testes usando seu framework favorito.

Requisitos para usar o Arquillian

Ok, você agora tem uma ideia sobre o que o Arquillian pode fazer e quais problemas ele resolve. Do que você precisa para adotá-lo em seus projetos?

Ferramenta de build

O Arquillian pode ser usado com qualquer ferramenta de build que tenha gestão de dependências. A documentação oficial está focada em Maven, mas você pode usar o Gradle também se quiser.

Se você estiver na situação em que precise testar sua aplicação contra diferentes containers, recomendo uma ferramenta de build que possua o recurso de perfis (profiles), tal como o Maven. Isto lhe permitirá carregar as dependências necessárias para cada situação de acordo com a configuração desejada.

JDK

Há suporte para a versão 1.6 ou posterior do Java. Lembra quando disse que é uma ferramenta excelente para se aplicar a sistemas legados? Na página de módulos do Arquillian que lista os container adapters você verá alguns containers bem antigos (Tomcat 5, por exemplo).

Framework de testes

Tal como mencionado acima, você pode usar tanto JUnit quanto TestNG.

O Container a ser gerenciado

Finalmente, você precisará ter acesso ao container que será o responsável pela execução dos seus testes. Caso não tenha acesso ao container em si, verifique as opções de container embarcados disponíveis no site oficial do projeto neste link.

Vantagens e desvantagens

Será que o Arquillian se aplica ao seu projeto? É importante primeiro entender a natureza do mesmo.

Vantagens

A principal vantagem do Arquillian é o fato de termos nossos testes executados contra o ambiente real no qual o sistema será implantado. Isto permite à equipe compreender muito melhor as entranhas destes ambientes de execução.

Outra vantagem muito interessante é o fato de não haver mudanças significativas no seu fluxo de trabalho: você continuará usando sua IDE de preferência tal como faz hoje. É possível depurar seus testes tal como faz hoje: não muda coisa alguma, a não ser algumas anotações que você aprenderá em posts futuros.

A velocidade na execução também é surpreendente: a primeira coisa que você pensa ao ser apresentado ao Arquillian é que consiste em uma ferramenta lenta pelo trabalho que realiza. Não é o caso.

No caso de projetos legados baseados em Java eu diria que seu uso no primeiro momento pode ser essencial, dado que o tempo que você gastaria levantando mocks pode ser proibitivo. Especialmente em casos nos quais exista o uso pesado de JNDI para obter recursos do sistema, tal como datasources e fontes externas de autenticação baseada em JAAS.

Desvantagens

Servidores de aplicação e Servlet Containers pouco a pouco estão perdendo a relevância no desenvolvimento de novos projetos. Cada vez usa-se menos os recursos disponibilizados por estas ferramentas, tais como os datasources obtidos por JNDI, por exemplo.

Sendo assim, se for para pensar em adotar o Arquillian, deve-se ter a certeza de que seu projeto será aplicado neste tipo de ambiente. Sinceramente não vemos muito sentido em sua adoção em projetos que fujam deste perfil neste momento.

Outro fator a ser levado em consideração é o fato do projeto ter perdido o gás nos últimos anos. No momento da escrita deste post o último post em seu blog é de junho de 2018 (estamos em maio de 2020).

Isto não quer dizer que o projeto esteja morto, apenas que não é mais tão vibrante quanto antes. Os últimos commits até a escrita deste blog no módulo Core, do projeto, por exemplo, são de 20 de abril no GitHub.

Sua aplicação em projetos também pode ser um pouco mais trabalhosa que o esperado. Isto em parte se deve à própria documentação do Arquillian.

Para saber mais

Este é o nosso primeiro post sobre o Arquillian aqui no site da itexto. Em breve publicaremos também algumas receitas ensinando a aplicá-lo em seus projetos e a como executar tarefas importantes com ele. Esperamos que este conhecimento lhes seja útil.

Mas enquanto isto, você pode aprender mais sobre o projeto nestes links:

Até os próximos posts!

12