44

Testes em aplicações JEE: Montando sua infra de testes automatizados

Embed Size (px)

DESCRIPTION

A 4Linux foi uma das patrocinadoras do Just Java 2012 que ocorreu nos dias 18 e 19/05/2012. Além do patrocínio, a equipe 4Linux foi responsável pela apresentação da palestra: Testes em aplicações Java EE: Montando sua infra de testes automatizados.

Citation preview

Page 1: Testes em aplicações JEE: Montando sua infra de testes automatizados
Page 2: Testes em aplicações JEE: Montando sua infra de testes automatizados

2 / 44www.4linux.com.br

Experiência em missão crítica de missão crítica

Pioneira no ensino de Linux à distância

Parceira de treinamento IBM

Primeira com LPI no Brasil

+ de 30.000 alunos satisfeitos

Reconhecimento internacional

Inovação com Hackerteen e Boteconet

Page 3: Testes em aplicações JEE: Montando sua infra de testes automatizados

Testes em aplicações JEE:Testes em aplicações JEE: Montando sua infra de testes automatizadosMontando sua infra de testes automatizados

Page 4: Testes em aplicações JEE: Montando sua infra de testes automatizados

4 / 44www.4linux.com.br

AgendaAgenda

● Porque testar?● Escrevendo testes com mais valor● Problemas testando componentes JEE● Como integrar containers aos testes.

Page 5: Testes em aplicações JEE: Montando sua infra de testes automatizados

5 / 44www.4linux.com.br

Porque automatizar testes?Porque automatizar testes?

● Modinha...● Eficiência dos testes de regressão

● Você pode melhorar/refatorar o sistema com tranquilidade, se estragar você sabe instantaneamente que estragou

● Integração contínua pode te tirar do apuro● Você tem uma espécie de auditoria “vigiando” o funcionamento do

seu código, se falhar você saberá exatamente onde e porque falhou

Page 6: Testes em aplicações JEE: Montando sua infra de testes automatizados

6 / 44www.4linux.com.br

Problemas na hora de testar?Problemas na hora de testar?

● Mas te ensinaram como usar em situações do cotidiano?● Até que ponto testar com objetos fake e mocks?

● Difícil montar ambientes onde os testes podem ser executados

● O quanto de esforço é necessário para executar testes em ferramentas de build e IDEs ao mesmo tempo.

Segundo Bill Burke, mocks te dão uma falsa sensação de segurança, pois permitem distorcer os testes para que seu código passe.

Page 7: Testes em aplicações JEE: Montando sua infra de testes automatizados

7 / 44www.4linux.com.br

Problemas em testes de Problemas em testes de componentes JEEcomponentes JEE

● Ciclo chato de desenvolvimento

● Isolar o que deve ser testado● Para um componente ser testado, ele dependente de um

outro componente ou um serviço oferecidos pelo container.

● Exemplos:– Filas de mensageria– Transacionalidade– Segurança– Data Sources

Implementação Deploy Test Implementação

Page 8: Testes em aplicações JEE: Montando sua infra de testes automatizados

8 / 44www.4linux.com.br

Mas eu utilizo Ant e o Maven para executar os testes pra mim, moleza!

Ciclo chato de desenvolvimento

Page 9: Testes em aplicações JEE: Montando sua infra de testes automatizados

9 / 44www.4linux.com.br

Utilizando ferramentas de Utilizando ferramentas de buildbuild

● Ant, Maven:● Vantagem:

– Fácil de executar testes: mvn test (unitários) / mvn verify (unitários e integração)

– Fácil integração com servidor de integração contínua como Jenkins.

● Desvantagem:– Executa todos os testes de um vez. – (Maven) Os erros são somente mostrados nos

relátorios gerados– (Maven) não integra as suas fases de teste com a

IDE

Page 10: Testes em aplicações JEE: Montando sua infra de testes automatizados

10 / 44www.4linux.com.br

Vei, na boa! Minha aplicação nem usa EJB

Page 11: Testes em aplicações JEE: Montando sua infra de testes automatizados

11 / 44www.4linux.com.br

Para recursos simples da WebPara recursos simples da Web

● Sua aplicação não usa EJB, JTA, JMS?● Você não precisa testar em um servidor de aplicações FULL. ● Utilize só um container web, mais leve e mais fácil de

configurar.● Opções como o Jetty, Tomcat. Ambos possuem versão

embutidas, que pode ser adicionada aos testes.● Jetty é dividido em módulos e permite especificar quais deles

seram iniciaram com os testes.● Possuem plugins para Maven.● Possuem APIs que podem ser usadas dentro dos testes.

Page 12: Testes em aplicações JEE: Montando sua infra de testes automatizados

12 / 44www.4linux.com.br

Embedded JettyEmbedded Jetty

● Container de servlets leve● Possui uma API para configurar e iniciar

uma instância do container.

Server server = new Server(8080);Context root = new Context(server,"/agenda",Context.SESSIONS);

root.addServlet(new ServletHolder(new ContatoServlet()), "contatos");server.start();

Page 13: Testes em aplicações JEE: Montando sua infra de testes automatizados

13 / 44www.4linux.com.br

API do JettyAPI do Jetty

private static WebAppContext gerandoContextoAplicacao() throws Exception {WebAppContext context = new WebAppContext();context.setWar(new File(URI_DO_WAR).getAbsolutePath());context.setContextPath(“/aplicacao-do-jjustjava/”);

context.setConfigurations(new Configuration[] {new AnnotationConfiguration(), new JettyWebXmlConfiguration(),new WebInfConfiguration(), new WebXmlConfiguration(),new TagLibConfiguration(), new MetaInfConfiguration(),new PlusConfiguration(), new FragmentConfiguration(),new EnvConfiguration() });

return context;}

@BeforeClasspublic static void inicializar() throws Exception {

server = new Server(SERVER_PORT);WebAppContext contexto = gerandoContextoAplicacao();

server.setHandler(contexto);server.start();

}

A API do Jetty permite que você especifique os módulos que são importantes para você, no caso, em seus testes.

Mais dependências para utilizar JSPs: ● ant-1.6.5.jar● core-3.1.1.jar● jsp-2.1.jar● jsp-api-2.1.jar

Page 14: Testes em aplicações JEE: Montando sua infra de testes automatizados

14 / 44www.4linux.com.br

Tomcat EmbeddedTomcat Embedded

● Mais fácil de iniciar que o Jetty por todos os módulos já virem configurados para iniciar.

// Configura container de servlet embutidoTomcat servidor = new Tomcat();

// Aponta o diretorio temporario para que o container necessitaservidor.setBaseDir("target/temp");

// Especifica a porta onde irá funcionarservidor.setPort(8081);

// Inicia servidorservidor.start();

<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>7.0.27</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>7.0.27</version> <scope>test</scope> </dependency>

Page 15: Testes em aplicações JEE: Montando sua infra de testes automatizados

15 / 44www.4linux.com.br

API do Tomcat : Adicionando API do Tomcat : Adicionando ConteúdoConteúdo

servidor.addWebapp("/carrinho", enderecoDoWar); Adiciona o WAR ao contexto /carrinho

File diretorioWebapp = new File("src/main/webapp");Context contexto = servidor.addWebapp("/", diretorioWebapp.getAbsolutePath());

servidor.addServlet("/", "LeilaoServlet", new LeilaoServlet());contexto.addServletMapping("/leilao", "LeilaoServlet");

Mapeando o Servlet adicionado

Você pode associar um WAR do file system a um contexto utilizando o método addWebapp

Também é possível tornar um diretório, o contexto da aplicação, adicionando servlets aoContainer e mapeando-os no contexto.

Page 16: Testes em aplicações JEE: Montando sua infra de testes automatizados

16 / 44www.4linux.com.br

Mas os como eu forneço pacotes com as classes para os containers dentro dos meus testes?

Page 17: Testes em aplicações JEE: Montando sua infra de testes automatizados

17 / 44www.4linux.com.br

JBoss ShrinkWrapJBoss ShrinkWrap

● Projeto que ajuda automatizar e personalizar a criação de pacotes Java

● EAR, WAR, JAR ou também qualquer outro Zip.● A maioria dos container embutidos permitem especificar um

pacote para registrado inserido em um contexto.

WebArchive warAplicacao = ShrinkWrap.create(WebArchive.class, “livraria.war”).addClasses(Cliente.class, CartaoCreditoInfo.class).addPackage(“fourlinux.justjava.store.dao”);.setWebXML(“/src/test/resources/web.xml”);

Page 18: Testes em aplicações JEE: Montando sua infra de testes automatizados

18 / 44www.4linux.com.br

JBoss ShrinkWrapJBoss ShrinkWrap

<project> ... <dependencies> ... <dependency> <groupId>org.jboss.shrinkwrap</groupId> <artifactId>shrinkwrap-api</artifactId> </dependency> <dependency> <groupId>org.jboss.shrinkwrap</groupId> <artifactId>shrinkwrap-impl-base</artifactId> <scope>test</scope> </dependency> ... </dependencies> ... </project>

<repository> <id>jboss-public-repository-group</id> <name>JBoss Public Maven Repository Group</name> <url>https://repository.jboss.org/nexus/content/groups/public/</url> </repository>

Page 19: Testes em aplicações JEE: Montando sua infra de testes automatizados

19 / 44www.4linux.com.br

Usando o ShrinkWrapUsando o ShrinkWrap

// Exportando WAR:WebArchive war = ShrinkWrap.create(WebArchive.class);

war.addPackages(true, "fourlinux.justjava");

war.as(ZipExporter.class).exportTo(new File(“/target/shrinkwrap/aplicacao.war”));

Adiciona todas as classesdo seguinte pacote recursivamente

Cria um arquivo zip para o conteúdo indicado

// Embedded Jetty WebAppContext context = new WebAppContext();context.setWar(new File(uriDoWar).getAbsolutePath());;

Page 20: Testes em aplicações JEE: Montando sua infra de testes automatizados

20 / 44www.4linux.com.br

Usando ShrinkWrap + MavenUsando ShrinkWrap + Maven

● As vezes seu projeto está dividido em submódulos e um componente que está sendo testado depende de um módulo declarado no POM

● Ou você precisa adicionar um driver JDBC no pacote para testar

ShrinkWrap ResolverMavenDependencyResolver resolver = DependencyResolvers.use(

MavenDependencyResolver.class);

MavenDependencyBuilder dominio = resolver.artifact("soujava.justjava:livraria-dominio:1.0");

carrinho.addAsLibraries(dominio.resolveAs(GenericArchive.class));

Page 21: Testes em aplicações JEE: Montando sua infra de testes automatizados

21 / 44www.4linux.com.br

MAS MEU PROJETO POSSUI EJBs, COMO TESTO?

Page 22: Testes em aplicações JEE: Montando sua infra de testes automatizados

22 / 44www.4linux.com.br

Apache OpenEJBApache OpenEJB

● Container EJB● Desde 1999● Como pode ser utilizado nos testes?

● Diferencial: Leve e rápido● Pode ser iniciado dentro dos testes.● Suporta as versões 3.1, 3.0, 2.1, 2.0, 1.1● Simples configuração e inicialização.● Simplicica os ciclos de desenvolvimento e teste.

Page 23: Testes em aplicações JEE: Montando sua infra de testes automatizados

23 / 44www.4linux.com.br

Configurando OpenEJB com Configurando OpenEJB com MavenMaven

● É utilizado como uma simples dependência.<project>

...<dependency>

<groupId>org.apache.openejb</groupId><artifactId>javaee-api</artifactId><scope>provided</scope><version>6.0-3-SNAPSHOT</version>

</dependency><dependency>

<groupId>org.apache.openejb</groupId><artifactId>openejb-core</artifactId><scope>test</scope><version>4.0.0-beta-1</version>

</dependency></project>

API

Container

<dependency><groupId>org.apache.openejb</groupId><artifactId>openejb-core-hibernate</artifactId><version>4.0.0-beta-1</version><type>pom</type>

</dependency>

Preciso de suporte a JPA, o que faço?

OpenEJB com Hibernate

Page 24: Testes em aplicações JEE: Montando sua infra de testes automatizados

24 / 44www.4linux.com.br

Iniciando container Iniciando container

● O container pode ser iniciado dentro dos testes, seja a cada teste ou em um setup para todos os testes.

@Beforepublic void inicializacao() {

Properties props = new Properties();props.put(Context.INITIAL_CONTEXT_FACTORY,

"org.apache.openejb.client.LocalInitialContextFactory");Context context = new InitialContext(props);

}

@Beforepublic void inicializacao() {

EjbContainer container = EjbContainer.createEjbContainer();Context context = container.getContext();

}

<= EJB 3.0

>= EJB 3.1

Page 25: Testes em aplicações JEE: Montando sua infra de testes automatizados

25 / 44www.4linux.com.br

Testando SessionBeansTestando SessionBeans

@Statelesspublic class ServicoPagamento {

public void cobrar(double valor, CartaoCreditoInfo ccInfo) {...

}}@Testpublic class ServiceoPagamentoIT {

@Test(expected=IllegalArgumentException.class)public void valorNegativoLancaExcecao() {

Context contexto = EjbContainer.createEjbContainer().getContext();ServicoPagamento sp = (ServicoPagamento)

contexto.lookup(“java:global/projeto/ServicoPagamento”);sp.cobrar(-5, ccInfo);

}} Utilizando o JNDI para recuperar componentes

como session beans

Provê um JNDI padrãoque você pode customizá-lo.

O OpenEJB caça sua aplicação por componentes JavaEE que podem ser de sua responsabilidade.

Page 26: Testes em aplicações JEE: Montando sua infra de testes automatizados

26 / 44www.4linux.com.br

Configurando RecursosConfigurando Recursos

public class OrderProcessorIT {@Testpublic void processOrderAddItensToDatabase() {

Properties props = new Properties(); props.put("shopDatabase", "new://Resource?type=DataSource"); props.put("shopDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); props.put("shopDatabase.JdbcUrl", "jdbc:hsqldb:mem:shopdb");

Context contexto = EjbContainer.createEjbContainer(props).getContext();OrderProcessor orders = (OrderProcessor)

contexto.lookup(“java:global/projeto/OrderProcessor”);}

}

@Statelesspublic class OrderProcessor {

@ResourceDataSource dataSource;

...}

Configurando recursos como DataSource, filas, tópicos, fábricas de conexões...

Page 27: Testes em aplicações JEE: Montando sua infra de testes automatizados

27 / 44www.4linux.com.br

Ligando o teste no containerLigando o teste no container

● Há momentos onde é mais pratico permitir que o teste tenha acesso aos recursos através de injeção de dependência.public class GameContextIT {

@PersistenceContext(unitName=”gameunit”)private EntityManager em;

@Resourceprivate Queue filaJogadores;

@EJBGameController controller;…public SetUp() throws Exception {

EJBContainer container = EJBContainer.createEJBContainer();container.getContext().bind(“inject”, this);

}}

Acesso a todos os recursos do Container, como filas, datasources, ejbs e ao contexto cdi

Page 28: Testes em aplicações JEE: Montando sua infra de testes automatizados

28 / 44www.4linux.com.br

Mais eu quero testar em um servidor de aplicação

completo, inútil!

Page 29: Testes em aplicações JEE: Montando sua infra de testes automatizados

29 / 44www.4linux.com.br

Testando na real com Testando na real com JBoss ArquillianJBoss Arquillian

● Facilmente extensível.● Ajuda a diminui o esforço para fazer testes em qualquer

tipo de container, seja remoto ou embutido.● Gerencia todo o ciclo de vida do container e da aplicação

sendo executada nele.● Com ajuda do ShrinkWrap, permite montar pacotes

personalizados para deploy.● Permite executar testes dentro e fora do container.

Page 30: Testes em aplicações JEE: Montando sua infra de testes automatizados

30 / 44www.4linux.com.br

Arquillian + MavenArquillian + Maven

Novamente adicionar repositório Jboss:http://repository.jboss.org/nexus/content/groups/public

<dependency><groupId>org.jboss.arquillian</groupId><artifactId>arquillian-bom</artifactId><version>1.0.0.Final</version><scope>import</scope><type>pom</type>

</dependency>

Importando dependências do Arquillian

<dependency><groupId>org.jboss.arquillian.junit</groupId><artifactId>arquillian-junit-container</artifactId><version>1.0.0.Final</version>

</dependency>

Integração com Junit ou TestNG

Falta a extensão do container...

Page 31: Testes em aplicações JEE: Montando sua infra de testes automatizados

31 / 44www.4linux.com.br

Arquillian + MavenArquillian + Maven

Extensões para

● JBoss● Tomcat● Glassfish● Resin● Weld● OSGI● CloudBees● OpenEJB● Jetty● Google AppEngine● Spring

Arquillian com Glassfish<dependency>

<groupId>org.jboss.arquillian.container</groupId><artifactId>arquillian-glassfish-embedded-3.1</artifactId><version>1.0.0.CR3</version><scope>test</scope>

</dependency><dependency>

<groupId>org.glassfish.main.extras</groupId><artifactId>glassfish-embedded-all</artifactId><version>3.1.2</version><scope>test</scope>

</dependency>

Glassfish Embutido

Extensão para glassfish

Page 32: Testes em aplicações JEE: Montando sua infra de testes automatizados

32 / 44www.4linux.com.br

JBoss ArquillianJBoss Arquillian

● Do que o Arquillian precisa?● Os testes devem funcionar com

@RunWith(Arquillian.class)● Pelo menos um método anotado com

@Test● Um método estático que entregue um pacote Java montado

pelo ShrinkWrap● Um container onde ele irá instalar o pacote.

Page 33: Testes em aplicações JEE: Montando sua infra de testes automatizados

33 / 44www.4linux.com.br

Teste com CDI usando Teste com CDI usando ArquillianArquillian@RunWith(Arquillian.class)public class GerenciadorReservasTest {

@Injectprivate GerenciadorReservas reservas;

@Deploymentpublic static JavaArchive gerandoArquivoDeploy() {

JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class);arquivo.addPackages(true, “fourlinux.justjava”);arquivo.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");return arquivo;

}

@Testpublic void reservaDeveGerarCobranca() throws Exception {

Cabine cabine = new Cabine(“Titanic”, “A12”, Tipo.LUXO, 340.00f);Usuario usuario = new Usuario("[email protected]", "Gabriel Ozeas");

Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario);assertEquals(new Float(340), new Float(cobranca.getValor()));

}}

Page 34: Testes em aplicações JEE: Montando sua infra de testes automatizados

34 / 44www.4linux.com.br

Testando em Containers Testando em Containers RemotosRemotos

<dependency><groupId>org.jboss.as</groupId><artifactId>jboss-as-arquillian-container-remote</artifactId><version>7.1.1.Final</version><scope>test</scope>

</dependency><dependency>

<groupId>org.jboss.as</groupId><artifactId>jboss-as-controller-client</artifactId><version>7.1.1.Final</version><scope>test</scope>

</dependency>

Cliente JBoss Remoto

Utilizando containers remotos e gerenciados, faz com que eles iniciem em outra JVM, ou seja os logs e debug não estão disponiveis na JVM que iniciou os testes.

Page 35: Testes em aplicações JEE: Montando sua infra de testes automatizados

35 / 44www.4linux.com.br

Arquillian como ClienteArquillian como Cliente

@RunWith(Arquillian.class)public class GerenciadorReservasTest {

@Deployment(testable = false)public static JavaArchive gerandoArquivoDeploy() {

JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class);arquivo.addPackages(true, “fourlinux.justjava”);arquivo.setWebXML(“src/main/webapp/WEB-INF/web.xml”);return arquivo;

}

@Testpublic void verificandoTotalItensInicial() throws Exception {

WebDriver navegador = new HtmlUnitDriver();navegador.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

navegador.get("http://localhost:8081/leilao");WebElement body = navegador.findElement(By.tagName("h1"));assertEquals("Histórico do item", body.getText());

}}

Testando UI com Selenium

Deploy no container, mas testa no cliente

Teste OUT Container

Page 36: Testes em aplicações JEE: Montando sua infra de testes automatizados

36 / 44www.4linux.com.br

Misturando In e Out ContainerMisturando In e Out Container

@RunWith(Arquillian.class)public class GerenciadorReservasTest {

@Injectprivate GerenciadorReservas reservas;

@Deploymentpublic static JavaArchive gerandoArquivoDeploy() {

JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class);arquivo.addClasses(...);...

}

@Testpublic void reservaDeveGerarCobranca() throws Exception {

….Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario);assertEquals(new Float(340), new Float(cobranca.getValor()));

}

@Test@RunAsClientpublic void verificandoTotalItensInicial() throws Exception {

WebDriver navegador = new HtmlUnitDriver();navegador.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);...

}}

Teste será executado na JVM que inicou os testes

Teste será executado na JVM do container

Page 37: Testes em aplicações JEE: Montando sua infra de testes automatizados

37 / 44www.4linux.com.br

PLUS: InfinitestPLUS: Infinitest

● Customizando a IDE:● Teste continuo com Infinitest

– Ajuda a executar os testes dentro do Eclipse automaticamente– Verde, passou, Vermelho Falhou.– Permite criar filtros para escolher quais testes serão sempre

executados.– Recomendado para executar em testes de unidade, pois são

normalmente executados em millisegundos.

Testes que falharam

Page 38: Testes em aplicações JEE: Montando sua infra de testes automatizados

38 / 44www.4linux.com.br

Filtrando testes no InfinitestFiltrando testes no Infinitest

● O Infinitest permite que você filtre os testes que serão executados continuamente.

● Arquivo infinitest.filtersBloqueia todos os testes de integração:.*ITest

Bloqueia todos os testes de um pacote:org\.soujava\.justjava\..*

Bloqueia todos os teste do projeto:.*

Page 39: Testes em aplicações JEE: Montando sua infra de testes automatizados

39 / 44www.4linux.com.br

EmmaEmma

Page 40: Testes em aplicações JEE: Montando sua infra de testes automatizados

40 / 44www.4linux.com.br

EmmaEmma

Page 41: Testes em aplicações JEE: Montando sua infra de testes automatizados

41 / 44www.4linux.com.br

Cobertura dos TestesCobertura dos Testes

Page 42: Testes em aplicações JEE: Montando sua infra de testes automatizados

42 / 44www.4linux.com.br

Cobertura dos TestesCobertura dos Testes

Page 43: Testes em aplicações JEE: Montando sua infra de testes automatizados

43 / 44www.4linux.com.br

Chegaremos a 100% ???Chegaremos a 100% ???

➢ Nem tudo será testado➢ Ex: Gets e Setters!➢ Classes sem lógica de negócio /

domínio➢ O aumento do esforço para se chegar

a 100% pode não valer a pena!

Page 44: Testes em aplicações JEE: Montando sua infra de testes automatizados

44 / 44www.4linux.com.br

O que acontece na realidade?O que acontece na realidade?

➢ A maioria das empresas estabelece um patamar mínimo aceitável:➢ Ex. 80% de cobertura (somente um exemplo)!

➢ Os testes unitários e a verificação de cobertura são feitos automaticamente;➢ A verificação de cobertura pode ser configurada

para analisar apenas algumas classes ou pacotes ➢ Utilizar patamares diferentes para recusar o build

em cada classe ou pacote.