   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


                            www.4linux.com.br         2 / 44
Testes em aplicações JEE:
Montando sua infra de testes automatizados
Agenda

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




                       www.4linux.com.br   4 / 44
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




                            www.4linux.com.br                     5 / 44
Problemas na hora de testar?

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

    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.

●    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.



                         www.4linux.com.br               6 / 44
Problemas em testes de
componentes JEE
●   Ciclo chato de desenvolvimento
Implementação          Deploy           Test    Implementação

●   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
                            www.4linux.com.br             7 / 44
Ciclo chato de desenvolvimento

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




  www.4linux.com.br               8 / 44
Utilizando ferramentas de
    build

●   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
                           www.4linux.com.br                9 / 44
Vei, na boa! Minha aplicação nem usa EJB




             www.4linux.com.br             10 / 44
Para 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.



                          www.4linux.com.br                  11 / 44
Embedded 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();




                             www.4linux.com.br                    12 / 44
API do Jetty

    A API do Jetty permite que você especifique os módulos
    que são importantes para você, no caso, em seus testes.
        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;
        }




                                                       @BeforeClass
                                                       public static void inicializar() throws Exception {
Mais dependências para utilizar JSPs:                        server = new Server(SERVER_PORT);
 ● ant-1.6.5.jar
                                                             WebAppContext contexto = gerandoContextoAplicacao();
 ● core-3.1.1.jar

 ● jsp-2.1.jar                                               server.setHandler(contexto);
 ● jsp-api-2.1.jar
                                                             server.start();
                                                       }


                                           www.4linux.com.br                                       13 / 44
Tomcat Embedded

●   Mais fácil de iniciar que o Jetty por todos os módulos já
    virem configurados para iniciar.
// Configura container de servlet embutido
Tomcat servidor = new Tomcat();

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

// Especifica a porta onde irá funcionar     <dependency>
servidor.setPort(8081);                          <groupId>org.apache.tomcat.embed</groupId>
                                                 <artifactId>tomcat-embed-core</artifactId>
// Inicia servidor                               <version>7.0.27</version>
                                                 <scope>test</scope>
servidor.start();                            </dependency>
                                             <dependency>
                                                 <groupId>org.apache.tomcat.embed</groupId>
                                                 <artifactId>tomcat-embed-jasper</artifactId>
                                                 <version>7.0.27</version>
                                                 <scope>test</scope>
                                             </dependency>


                                  www.4linux.com.br                                14 / 44
API do Tomcat : Adicionando
 Conteúdo
Você pode associar um WAR do file system a um contexto
utilizando o método addWebapp
servidor.addWebapp("/carrinho", enderecoDoWar);
                                                                  Adiciona o WAR ao
                                                                  contexto /carrinho


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

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


                                      www.4linux.com.br                                15 / 44
Mas os como eu forneço pacotes com
      as classes para os containers dentro
      dos meus testes?




www.4linux.com.br                16 / 44
JBoss 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”);




                                www.4linux.com.br                           17 / 44
JBoss ShrinkWrap



                       <repository>
<project>                   <id>jboss-public-repository-group</id>
  ...                       <name>JBoss Public Maven Repository Group</name>
  <dependencies>            <url>https://repository.jboss.org/nexus/content/groups/public/</url>
  ...                  </repository>
    <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>
                                     www.4linux.com.br                             18 / 44
Usando o ShrinkWrap




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

 war.addPackages(true, "fourlinux.justjava");          Adiciona todas as classes
                                                       do seguinte pacote recursivamente

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

                                        Cria um arquivo zip para o conteúdo indicado


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



                                 www.4linux.com.br                           19 / 44
Usando 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 Resolver
MavenDependencyResolver resolver = DependencyResolvers.use(
   MavenDependencyResolver.class);

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

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




                                     www.4linux.com.br                             20 / 44
MAS MEU PROJETO POSSUI EJBs,
COMO TESTO?




www.4linux.com.br    21 / 44
Apache 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.




                            www.4linux.com.br              22 / 44
Configurando OpenEJB com
Maven
●    É utilizado como uma simples dependência.
    <project>
         ...                                         API
         <dependency>
               <groupId>org.apache.openejb</groupId>
               <artifactId>javaee-api</artifactId>
               <scope>provided</scope>
               <version>6.0-3-SNAPSHOT</version>
         </dependency>                                Container
         <dependency>
                     <groupId>org.apache.openejb</groupId>
                     <artifactId>openejb-core</artifactId>
                     <scope>test</scope>
                     <version>4.0.0-beta-1</version>
         </dependency>
    </project>


    Preciso de suporte a JPA, o que faço?                  <dependency>
                                                                <groupId>org.apache.openejb</groupId>
                   OpenEJB com Hibernate                        <artifactId>openejb-core-hibernate</artifactId>
                                                                <version>4.0.0-beta-1</version>
                                                                <type>pom</type>
                                                           </dependency>
                                         www.4linux.com.br                                     23 / 44
Iniciando container

    ●   O container pode ser iniciado dentro dos testes, seja a
        cada teste ou em um setup para todos os testes.
@Before                                                                <= EJB 3.0
public void inicializacao() {

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

}
                                                                       >= EJB 3.1
@Before
public void inicializacao() {

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

}
                                      www.4linux.com.br                      24 / 44
Testando SessionBeans

@Stateless
public class ServicoPagamento {
     public void cobrar(double valor, CartaoCreditoInfo ccInfo) {
          ...
     }
}                                                                 Provê um JNDI padrão
                                                                  que você pode customizá-lo.
@Test
public 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


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

                                    www.4linux.com.br                            25 / 44
Configurando Recursos
 @Stateless
 public class OrderProcessor {                        Configurando recursos como
      @Resource                                       DataSource, filas, tópicos,
      DataSource dataSource;                          fábricas de conexões...

     ...
 }


 public class OrderProcessorIT {
      @Test
      public 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”);
     }
 }
                                 www.4linux.com.br                           26 / 44
Ligando 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;

        @Resource
        private Queue filaJogadores;                          Acesso a todos os recursos
                                                              do Container, como filas,
        @EJB                                                  datasources, ejbs e ao
        GameController controller;                            contexto cdi
        …
        public SetUp() throws Exception {
             EJBContainer container = EJBContainer.createEJBContainer();
             container.getContext().bind(“inject”, this);
        }
    }

                                www.4linux.com.br                          27 / 44
Mais eu quero testar em um
        servidor de aplicação
            completo, inútil!




www.4linux.com.br                  28 / 44
Testando na real com
JBoss 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.



                         www.4linux.com.br                29 / 44
Arquillian + 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>
                                            Importando dependências
    <scope>import</scope>
                                            do Arquillian
    <type>pom</type>
</dependency>                                               Integração com
                                                                Junit ou TestNG
 <dependency>
     <groupId>org.jboss.arquillian.junit</groupId>
     <artifactId>arquillian-junit-container</artifactId>
     <version>1.0.0.Final</version>
 </dependency>



                 Falta a extensão do container...

                                   www.4linux.com.br                              30 / 44
Arquillian + Maven

Arquillian com Glassfish                                         Extensões para
<dependency>                                                     ● JBoss
    <groupId>org.jboss.arquillian.container</groupId>            ● Tomcat
    <artifactId>arquillian-glassfish-embedded-3.1</artifactId>   ● Glassfish
    <version>1.0.0.CR3</version>
                                                                 ● Resin
    <scope>test</scope>
</dependency>                         Extensão para glassfish    ● Weld

                                                                 ● OSGI
<dependency>
    <groupId>org.glassfish.main.extras</groupId>                 ● CloudBees

    <artifactId>glassfish-embedded-all</artifactId>              ● OpenEJB

    <version>3.1.2</version>                                     ● Jetty

    <scope>test</scope>                                          ● Google AppEngine
</dependency>                                                    ● Spring




                    Glassfish Embutido



                                www.4linux.com.br                         31 / 44
JBoss 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.




                           www.4linux.com.br            32 / 44
Teste com CDI usando
Arquillian
@RunWith(Arquillian.class)
public class GerenciadorReservasTest {
     @Inject
     private GerenciadorReservas reservas;

    @Deployment
    public static JavaArchive gerandoArquivoDeploy() {
         JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class);
         arquivo.addPackages(true, “fourlinux.justjava”);
         arquivo.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
         return arquivo;
    }

    @Test
    public void reservaDeveGerarCobranca() throws Exception {
         Cabine cabine = new Cabine(“Titanic”, “A12”, Tipo.LUXO, 340.00f);
         Usuario usuario = new Usuario("gabriel.ozeas1@gmail.com", "Gabriel Ozeas");

        Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario);
        assertEquals(new Float(340), new Float(cobranca.getValor()));
    }
}
                                www.4linux.com.br                           33 / 44
Testando em Containers
   Remotos
<dependency>
     <groupId>org.jboss.as</groupId>
     <artifactId>jboss-as-arquillian-container-remote</artifactId>
     <version>7.1.1.Final</version>
     <scope>test</scope>
</dependency>
                               Cliente JBoss Remoto
<dependency>
     <groupId>org.jboss.as</groupId>
     <artifactId>jboss-as-controller-client</artifactId>
     <version>7.1.1.Final</version>
     <scope>test</scope>
</dependency>




 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.

                                            www.4linux.com.br              34 / 44
Arquillian como Cliente

                                                      Teste OUT Container
@RunWith(Arquillian.class)
public class GerenciadorReservasTest {
                                            Deploy no container, mas testa no cliente
    @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;
    }
                                                                       Testando UI
                                                                       com Selenium
    @Test
    public 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());
    }
}
                               www.4linux.com.br                            35 / 44
Misturando In e Out Container

@RunWith(Arquillian.class)
public class GerenciadorReservasTest {
     @Inject
     private GerenciadorReservas reservas;

    @Deployment
    public static JavaArchive gerandoArquivoDeploy() {
         JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class);
         arquivo.addClasses(...);
         ...
    }
                  Teste será executado na JVM do container
    @Test
    public void reservaDeveGerarCobranca() throws Exception {
         ….
         Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario);
         assertEquals(new Float(340), new Float(cobranca.getValor()));
    }

    @Test                  Teste será executado na JVM que inicou os testes
    @RunAsClient
    public void verificandoTotalItensInicial() throws Exception {
         WebDriver navegador = new HtmlUnitDriver();
         navegador.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
         ...
    }                                     www.4linux.com.br                            36 / 44
PLUS: 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



                                www.4linux.com.br                  37 / 44
Filtrando testes no Infinitest

●    O Infinitest permite que você filtre os testes que serão
     executados continuamente.
●    Arquivo infinitest.filters
Bloqueia todos os testes de integração:
.*ITest

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

Bloqueia todos os teste do projeto:
.*




                                 www.4linux.com.br          38 / 44
Emma




  www.4linux.com.br   39 / 44
Emma




  www.4linux.com.br   40 / 44
Cobertura dos Testes




           www.4linux.com.br   41 / 44
Cobertura dos Testes




           www.4linux.com.br   42 / 44
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!


               www.4linux.com.br   43 / 44
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.


                        www.4linux.com.br         44 / 44

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

  • 2.
    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 www.4linux.com.br 2 / 44
  • 3.
    Testes em aplicaçõesJEE: Montando sua infra de testes automatizados
  • 4.
    Agenda ● Porque testar? ● Escrevendo testes com mais valor ● Problemas testando componentes JEE ● Como integrar containers aos testes. www.4linux.com.br 4 / 44
  • 5.
    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 www.4linux.com.br 5 / 44
  • 6.
    Problemas na horade testar? ● Mas te ensinaram como usar em situações do cotidiano? ● Até que ponto testar com objetos fake e mocks? 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. ● 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. www.4linux.com.br 6 / 44
  • 7.
    Problemas em testesde componentes JEE ● Ciclo chato de desenvolvimento Implementação Deploy Test Implementação ● 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 www.4linux.com.br 7 / 44
  • 8.
    Ciclo chato dedesenvolvimento Mas eu utilizo Ant e o Maven para executar os testes pra mim, moleza! www.4linux.com.br 8 / 44
  • 9.
    Utilizando ferramentas de build ● 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 www.4linux.com.br 9 / 44
  • 10.
    Vei, na boa!Minha aplicação nem usa EJB www.4linux.com.br 10 / 44
  • 11.
    Para recursos simplesda 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. www.4linux.com.br 11 / 44
  • 12.
    Embedded 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(); www.4linux.com.br 12 / 44
  • 13.
    API do Jetty A API do Jetty permite que você especifique os módulos que são importantes para você, no caso, em seus testes. 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; } @BeforeClass public static void inicializar() throws Exception { Mais dependências para utilizar JSPs: server = new Server(SERVER_PORT); ● ant-1.6.5.jar WebAppContext contexto = gerandoContextoAplicacao(); ● core-3.1.1.jar ● jsp-2.1.jar server.setHandler(contexto); ● jsp-api-2.1.jar server.start(); } www.4linux.com.br 13 / 44
  • 14.
    Tomcat Embedded ● Mais fácil de iniciar que o Jetty por todos os módulos já virem configurados para iniciar. // Configura container de servlet embutido Tomcat servidor = new Tomcat(); // Aponta o diretorio temporario para que o container necessita servidor.setBaseDir("target/temp"); // Especifica a porta onde irá funcionar <dependency> servidor.setPort(8081); <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> // Inicia servidor <version>7.0.27</version> <scope>test</scope> servidor.start(); </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>7.0.27</version> <scope>test</scope> </dependency> www.4linux.com.br 14 / 44
  • 15.
    API do Tomcat: Adicionando Conteúdo Você pode associar um WAR do file system a um contexto utilizando o método addWebapp servidor.addWebapp("/carrinho", enderecoDoWar); Adiciona o WAR ao contexto /carrinho Também é possível tornar um diretório, o contexto da aplicação, adicionando servlets ao Container e mapeando-os no contexto. 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 www.4linux.com.br 15 / 44
  • 16.
    Mas os comoeu forneço pacotes com as classes para os containers dentro dos meus testes? www.4linux.com.br 16 / 44
  • 17.
    JBoss 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”); www.4linux.com.br 17 / 44
  • 18.
    JBoss ShrinkWrap <repository> <project> <id>jboss-public-repository-group</id> ... <name>JBoss Public Maven Repository Group</name> <dependencies> <url>https://repository.jboss.org/nexus/content/groups/public/</url> ... </repository> <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> www.4linux.com.br 18 / 44
  • 19.
    Usando o ShrinkWrap // Exportando WAR: WebArchive war = ShrinkWrap.create(WebArchive.class); war.addPackages(true, "fourlinux.justjava"); Adiciona todas as classes do seguinte pacote recursivamente war.as(ZipExporter.class).exportTo(new File(“/target/shrinkwrap/aplicacao.war”)); Cria um arquivo zip para o conteúdo indicado // Embedded Jetty WebAppContext context = new WebAppContext(); context.setWar(new File(uriDoWar).getAbsolutePath());; www.4linux.com.br 19 / 44
  • 20.
    Usando 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 Resolver MavenDependencyResolver resolver = DependencyResolvers.use( MavenDependencyResolver.class); MavenDependencyBuilder dominio = resolver.artifact("soujava.justjava:livraria-dominio:1.0"); carrinho.addAsLibraries(dominio.resolveAs(GenericArchive.class)); www.4linux.com.br 20 / 44
  • 21.
    MAS MEU PROJETOPOSSUI EJBs, COMO TESTO? www.4linux.com.br 21 / 44
  • 22.
    Apache 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. www.4linux.com.br 22 / 44
  • 23.
    Configurando OpenEJB com Maven ● É utilizado como uma simples dependência. <project> ... API <dependency> <groupId>org.apache.openejb</groupId> <artifactId>javaee-api</artifactId> <scope>provided</scope> <version>6.0-3-SNAPSHOT</version> </dependency> Container <dependency> <groupId>org.apache.openejb</groupId> <artifactId>openejb-core</artifactId> <scope>test</scope> <version>4.0.0-beta-1</version> </dependency> </project> Preciso de suporte a JPA, o que faço? <dependency> <groupId>org.apache.openejb</groupId> OpenEJB com Hibernate <artifactId>openejb-core-hibernate</artifactId> <version>4.0.0-beta-1</version> <type>pom</type> </dependency> www.4linux.com.br 23 / 44
  • 24.
    Iniciando container ● O container pode ser iniciado dentro dos testes, seja a cada teste ou em um setup para todos os testes. @Before <= EJB 3.0 public void inicializacao() { Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); Context context = new InitialContext(props); } >= EJB 3.1 @Before public void inicializacao() { EjbContainer container = EjbContainer.createEjbContainer(); Context context = container.getContext(); } www.4linux.com.br 24 / 44
  • 25.
    Testando SessionBeans @Stateless public classServicoPagamento { public void cobrar(double valor, CartaoCreditoInfo ccInfo) { ... } } Provê um JNDI padrão que você pode customizá-lo. @Test public 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 O OpenEJB caça sua aplicação por componentes JavaEE que podem ser de sua responsabilidade. www.4linux.com.br 25 / 44
  • 26.
    Configurando Recursos @Stateless public class OrderProcessor { Configurando recursos como @Resource DataSource, filas, tópicos, DataSource dataSource; fábricas de conexões... ... } public class OrderProcessorIT { @Test public 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”); } } www.4linux.com.br 26 / 44
  • 27.
    Ligando o testeno 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; @Resource private Queue filaJogadores; Acesso a todos os recursos do Container, como filas, @EJB datasources, ejbs e ao GameController controller; contexto cdi … public SetUp() throws Exception { EJBContainer container = EJBContainer.createEJBContainer(); container.getContext().bind(“inject”, this); } } www.4linux.com.br 27 / 44
  • 28.
    Mais eu querotestar em um servidor de aplicação completo, inútil! www.4linux.com.br 28 / 44
  • 29.
    Testando na realcom JBoss 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. www.4linux.com.br 29 / 44
  • 30.
    Arquillian + 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> Importando dependências <scope>import</scope> do Arquillian <type>pom</type> </dependency> Integração com Junit ou TestNG <dependency> <groupId>org.jboss.arquillian.junit</groupId> <artifactId>arquillian-junit-container</artifactId> <version>1.0.0.Final</version> </dependency> Falta a extensão do container... www.4linux.com.br 30 / 44
  • 31.
    Arquillian + Maven Arquilliancom Glassfish Extensões para <dependency> ● JBoss <groupId>org.jboss.arquillian.container</groupId> ● Tomcat <artifactId>arquillian-glassfish-embedded-3.1</artifactId> ● Glassfish <version>1.0.0.CR3</version> ● Resin <scope>test</scope> </dependency> Extensão para glassfish ● Weld ● OSGI <dependency> <groupId>org.glassfish.main.extras</groupId> ● CloudBees <artifactId>glassfish-embedded-all</artifactId> ● OpenEJB <version>3.1.2</version> ● Jetty <scope>test</scope> ● Google AppEngine </dependency> ● Spring Glassfish Embutido www.4linux.com.br 31 / 44
  • 32.
    JBoss 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. www.4linux.com.br 32 / 44
  • 33.
    Teste com CDIusando Arquillian @RunWith(Arquillian.class) public class GerenciadorReservasTest { @Inject private GerenciadorReservas reservas; @Deployment public static JavaArchive gerandoArquivoDeploy() { JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class); arquivo.addPackages(true, “fourlinux.justjava”); arquivo.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); return arquivo; } @Test public void reservaDeveGerarCobranca() throws Exception { Cabine cabine = new Cabine(“Titanic”, “A12”, Tipo.LUXO, 340.00f); Usuario usuario = new Usuario("gabriel.ozeas1@gmail.com", "Gabriel Ozeas"); Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario); assertEquals(new Float(340), new Float(cobranca.getValor())); } } www.4linux.com.br 33 / 44
  • 34.
    Testando em Containers Remotos <dependency> <groupId>org.jboss.as</groupId> <artifactId>jboss-as-arquillian-container-remote</artifactId> <version>7.1.1.Final</version> <scope>test</scope> </dependency> Cliente JBoss Remoto <dependency> <groupId>org.jboss.as</groupId> <artifactId>jboss-as-controller-client</artifactId> <version>7.1.1.Final</version> <scope>test</scope> </dependency> 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. www.4linux.com.br 34 / 44
  • 35.
    Arquillian como Cliente Teste OUT Container @RunWith(Arquillian.class) public class GerenciadorReservasTest { Deploy no container, mas testa no cliente @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; } Testando UI com Selenium @Test public 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()); } } www.4linux.com.br 35 / 44
  • 36.
    Misturando In eOut Container @RunWith(Arquillian.class) public class GerenciadorReservasTest { @Inject private GerenciadorReservas reservas; @Deployment public static JavaArchive gerandoArquivoDeploy() { JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class); arquivo.addClasses(...); ... } Teste será executado na JVM do container @Test public void reservaDeveGerarCobranca() throws Exception { …. Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario); assertEquals(new Float(340), new Float(cobranca.getValor())); } @Test Teste será executado na JVM que inicou os testes @RunAsClient public void verificandoTotalItensInicial() throws Exception { WebDriver navegador = new HtmlUnitDriver(); navegador.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); ... } www.4linux.com.br 36 / 44
  • 37.
    PLUS: 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 www.4linux.com.br 37 / 44
  • 38.
    Filtrando testes noInfinitest ● O Infinitest permite que você filtre os testes que serão executados continuamente. ● Arquivo infinitest.filters Bloqueia todos os testes de integração: .*ITest Bloqueia todos os testes de um pacote: org.soujava.justjava..* Bloqueia todos os teste do projeto: .* www.4linux.com.br 38 / 44
  • 39.
  • 40.
  • 41.
    Cobertura dos Testes www.4linux.com.br 41 / 44
  • 42.
    Cobertura dos Testes www.4linux.com.br 42 / 44
  • 43.
    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! www.4linux.com.br 43 / 44
  • 44.
    O que acontecena 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. www.4linux.com.br 44 / 44