SlideShare ist ein Scribd-Unternehmen logo
1 von 26
Downloaden Sie, um offline zu lesen
eXtreme Programming Brasil

      Testes de Integração
     em         J2EE com
      Jakarta
                  CACTUS
Helder da Rocha (helder@acm.org)   argonavis.com.br
Objetivos

                       1. Discutir as dificuldades relativas a testes em J2EE
                       2. Apresentar o framework Cactus e demonstrar como
                         utilizá-lo para testar aplicações J2EE
                       3. Mostrar como usar o Cactus com extensões como
                         HttpUnit e JUnitEE para testar servlets e EJBs
www.argonavis.com.br




                         Público-alvo:
                         Programadores J2EE familiarizados com o JUnit


                                                                                2
Por que outro framework para testes J2EE?

                       JUnit não é suficiente?
                         Sim, para testes de unidade (lógica de EJBs, por exemplo)
                         Aplicações J2EE possuem muitas dependências (é preciso
                         simular a rede, o servidor, o EJB container, etc.)
                         Testes de unidade não garantem o funcionamento de
                         toda uma aplicação J2EE
                       Mock objects não servem?
                         Sim, mock objects ajudam a testar com dependências e
www.argonavis.com.br




                         permitem testar toda a aplicação
                         Mock objects podem ficar muito complicados
                         Aplicações geralmente rodam em um servidor de
                         aplicação ou Web - testar a integração da aplicação com
                         o servidor é mais útil e mais fácil
                                                                                     3
O que é Cactus?

                       Um framework que oferece facilidades para testar
                       componentes J2EE
                         Componentes Web (Camada de Controle)
                         Camada EJB (Model) e cliente (View): indiretamente
                       Produto Open Source do projeto Jakarta
                         Metas de curto prazo: testar servlets, JSPs, filtros e EJB
                         Metas de longo prazo: oferecer facilidades para testar
                         todos os componentes J2EE; ser o framework de
www.argonavis.com.br




                         referência para testes in-container.
                       Cactus estende o JUnit framework
                         Execução dos testes é realizada de forma idêntica
                         TestCases são construídos sobre uma subclasse de
                         junit.framework.TestCase
                                                                                      4
Para que serve?
                       Para testar aplicações que utilizam componentes J2EE
                       Arquitetura MVC                  Controller    Model
                         Servlets, filtros e custom   Servlets   Taglibs
                                                                                EJBs
                                                                              Remotos
                         tags (Controladores)                    Classes      Classes
                                                                                             EJBs
                                                                                            Locais
                                                       Filtros
                         JSPs (camada de apre-                    Java         Java

                         sentação: View, através
                         de controladores)                            JSP   Velocity

                         EJB (Modelo de dados/                       XSLT                View
                         lógica de negócios)
www.argonavis.com.br




                       Cactus testa a integração desses componentes com seus
                       containers
                         não usa stubs - usa o próprio container como servidor e usa
                         JUnit como cliente
                         comunicação é intermediada por um proxy
                                                                             Ilustração: Manual do Cactus   5
Como funciona?

                       Cactus utiliza os test cases simultaneamente no
                       cliente e no servidor: duas cópias
                         Uma cópia é instanciada pelo servlet container
                         Outra cópia é instanciada pelo JUnit
                       Comunicação com o servlet container é feita através
                       de um proxy (XXXRedirector)
                         JUnit envia requisições via HTTP para proxy
                         Proxy devolve resultado via HTTP e JUnit os mostra
www.argonavis.com.br




                       Há, atualmente (Cactus 1.3) três tipos de proxies:
                         ServletRedirector: para testar servlets
                         JSPRedirector: para testar JSP custom tags
                         FilterRedirector: para testar filtros de servlets
                                                                              6
Arquitetura

                           Parte da mesma classe (ServletTestCase) é executada
                           no cliente, parte no servidor
                                                                                                            (4) setUp()
                              org.apache.cactus.                                                                testXXX()
                              ServletTestCase                (1) beginXXX()                                     tearDown()
                                                                               (2) (8)                (3)
                                                                                         Redirector
                                                             ServletTestCase                                ServletTestCase
                                                                                          Servlet
                                                                                                      (6)
                                                                               (7) (9)
                                                             (10) endXXX()
                           MeuServletTestCase                                                                       (5)
                       request: AbstractHttpServletRequest
                       response: HttpServletResponse                         lado   lado
www.argonavis.com.br




                                                                          cliente   servidor                   Classes
                       config: ServletConfigWrapper
                                                                                                            lado-servidor
                       ...

                       beginXXX(WebRequest)
                                                                         null, no cliente
                       setUp()
                       testXXX()                                        executados apenas no servidor
                       tearDown()
                       endXXX(WebResponse)                                 executados apenas no cliente
                                                                                                                              7
Diagrama UML
www.argonavis.com.br




                                      Fonte: Manual do usuário do Cactus
                                                                           8
ServletTestCase (ou similar)

                       Para cada método XXX() a ser testado, pode haver:
                          Um beginXXX(), para inicializar a requisição do cliente
                            encapsulada em um objeto WebRequest a ser enviado ao servidor
                          Um testXXX(), para testar o funcionamento do método
                          no servidor (deve haver ao menos um)
                          Um endXXX(), para verificar a resposta do servidor
                             devolvida em um objeto WebResponse retornada pelo servidor
                       Além desses três métodos, cada TestCase pode conter
www.argonavis.com.br




                          setUp(), opcional, para inicializar objetos no servidor
                          tearDown(), opcional, para liberar recursos no servidor
                       Os métodos do lado do servidor têm acesso aos mesmos
                       objetos implícitos disponíveis em um servlet ou página JSP:
                       request, response, etc.
                                                                                            9
Cactus: exemplo

                       Veja cactusdemo.zip (distribuído com esta palestra)
                         Usa duas classes: um servlet (MapperServlet) e uma classe
                         (SessionMapper) que guarda cada parâmetro como atributo da
                         sessão e em um HashMap - veja fontes em src/xptoolkit/cactus
                       Para rodar, configure o seu ambiente:
                         build.properties - localização dos JARs usados pelo servidor Web
                         (CLASSPATH do servidor)
                         runtests.bat (para Windows) e runtests.sh (para Unix) - localização
                         dos JARs usados pelo JUnit (CLASSPATH do cliente)
www.argonavis.com.br




                         lib/client.properties (se desejar rodar cliente e servidor em máquinas
                         separadas, troque as ocorrências de localhost pelo nome do servidor)
                       Para montar, execute:
                         1. ant test-deploy         instala cactus-tests.war no tomcat
                         2. o servidor              (Tomcat 4.0 startup)      veja demonstração
                         3. runtests.bat            roda os testes no JUnit cactusdemo.zip
                                                                                                  10
CactusDemo: servlet
                            O objetivo deste servlet é
                                1) gravar qualquer parâmetro que receber na sessão (objeto session)
                                2) devolver uma página contendo os pares nome/valor em uma tabela
                                3) imprimir resposta em caixa-alta se <init-param> ALL_CAPS
                                definido no web.xml contiver o valor true
                        public void doGet(...) throws IOException {
                                                                             (1) Grava request
                            SessionMapper.mapRequestToSession(request);
                                                                                  em session
                            writer.println("<html><body><table border='1'>");
                             // (... loop for each parameter ...)
                                  if (useAllCaps()) {
                                    key = key.toUpperCase();    (3) Retorna true se <init-param>
                                    val = val.toUpperCase();        "ALL_CAPS" contiver "true"
www.argonavis.com.br




                                  }
                                  str = "<tr><td><b>"+key+"</b></td><td>"+val+"</td></tr>";
                                  writer.println(str);
                             // (...)
                                                                                       (2)
                               writer.println("</table></body></html>");
                                                                                            Trecho de
                        }
                                                                                     MapperServlet.java

                            Escreveremos os testes para avaliar esses objetivos
                       Fonte do exemplo: [1]                                                          11
CactusDemo: testes
                       MapperServletTest.java

                       public class MapperServletTest extends ServletTestCase { (...)
                         private MapperServlet servlet;
                         public void beginDoGet(WebRequest cSideReq) {
                            cSideReq.addParameter("user", "Jabberwock");             Simula DD
                         }                                                         <init-param>
                         public void setUp() throws ServletException {
                           this.config.setInitParameter("ALL_CAPS", "true");
                           servlet = new MapperServlet();
                           servlet.init(this.config);
                         }
                                                                                    Simula servlet
                         public void testDoGet() throws IOException {                 container
                           servlet.doGet(this.request, this.response);
                           String value = (String) session.getAttribute("user");
www.argonavis.com.br




                           assertEquals("Jabberwock", value);
                         }                                              Verifica se parâmetro foi
                         public void tearDown() { /* ... */ }              mapeado à sessão
                         public void endDoGet(WebResponse cSideResponse) {
                           String str = cSideResponse.getText();
                           assertTrue(str.indexOf("USER</b></td><td>JABBERWOCK") > -1);
                         }
                       }
                                                      Verifica se parâmetro aparece na tabela HTML   12
Exemplo: funcionamento
                               Cliente (JUnit)                                             Servidor (Tomcat)
                       beginDoGet(WebRequest req)
                                      - Grava parâmetro:               ReqInfo
                                  nome=user
                                  value=Jabberwock                                         setUp()
                                                                 2 conexões HTTP:          - Define init-params
                       SUCCESS!!          FAIL!                  • Uma p/ rodar os           no objeto config
                                                                   testes e obter          - Roda init(config)
                                                                   saida do servlet
                                                                 • Outra para esperar      testDoGet()
                                                                   resultados de testes    - Roda doGet()
                                                                   (info sobre exceções)   - Verifica se parâmetro
www.argonavis.com.br




                                                                                             (no response) foi
                                                                                             mapeado à sessão
                                                                       TestInfo
                                        falha     falha remota
                                        local
                                                                                           tearDown()
                                                  &
                        endDoGet(WebResponse res)                       Output
                             - Verifica se resposta contém
                       USER</b></td><td>JABBERWOCK
                                                                                                                     13
HttpUnit

                       Onde encontrar
                         http://httpunit.sourceforge.net
                       Framework para testes funcionais de interface (teste
                       tipo "caixa-preta")
                         Verifica a resposta de uma aplicação Web ou página HTML
                         É teste funcional caixa-preta (não é "unit")
                         Oferece métodos para "navegar" na resposta
                            links, tabelas, imagens
www.argonavis.com.br




                            objetos DOM (Node, Element, Attribute)
                       Pode ser combinado com Cactus no endXXX()
                         Argumento com.meterware.httpunit.WebResponse
                       Acompanha ServletUnit
                         stub que simula o servlet container         veja também

                                                                     httpunitdemo.zip
                                                                                        14
Resumo da API do HttpUnit
                       WebConversation
                         Representa uma sessão de cliente Web (usa cookies)
                         WebConversation wc = new WebConversation();
                         WebResponse resp = wc.getResponse("http://xyz.com/t.html");
                       WebRequest
                         Representa uma requisição
                       WebResponse
                         Representa uma resposta. A partir deste objeto pode-se obter
                         objetos WebLink, WebTable e WebForm
                       WebLink
www.argonavis.com.br




                         Possui métodos para extrair dados de links de hipertexto
                       WebTable
                         Possui métodos para navegar na estrutura de tabelas
                       WebForm
                         Possui métodos para analisar a estrutura de formulários
                                                                                        15
HttpUnit com Cactus
                       Veja MapperServletTest2.java

                            Troque o WebResponse em cada endXXX() por
                                  com.meterware.httpunit.WebResponse
                          public void endDoGet(com.meterware.httpunit.WebResponse resp)
                                                        throws org.xml.sax.SAXException {
                             WebTable[] tables = resp.getTables();
                             assertNotNull(tables);
                             assertEquals(tables.length, 1); // só há uma tabela
                             WebTable table = tables[0];
                             int rows = table.getRowCount();
                             boolean keyDefined = false;
                             for (int i = 0; i < rows; i++) {
                                 String key   = table.getCellAsText(i, 0); // col 1
                                 String value = table.getCellAsText(i, 1); // col 2
www.argonavis.com.br




                                 if (key.equals("USER")) {
                                     keyDefined = true;
                                     assertEquals("JABBERWOCK", value);
                                 }
                             }
                             if (!keyDefined) {
                                 fail("No key named USER was found!");
                             }
                          }
                                                                                            16
Outros testes com Cactus

                       Testes em taglibs (JspRedirector)                   veja

                          Veja exemplos em cactusdemo/taglib/src            taglibdemo.zip
                       Testes em filtros (FilterRedirector)                veja também

                                                                          strutsdemo.zip
                          Usa proxy FilterRedirector
                          Teste básico é verificar se método doFilter() foi chamado
                          Veja exemplos em cactusdemo/src/xptoolkit/AuthFilter
                       Testes indiretos em páginas JSP (camada View)              veja

                          Ideal é JSP não ter código Java                    hellojsp.zip
www.argonavis.com.br




                          Principais testes são sobre a interface: HttpUnit!
                       Testes indiretos em EJB (camada Model)                     veja

                                                                           helloejb.zip
                          Indireto, através dos redirectors + JUnitEE
                          Redirectors permitem testar EJBs com interface local ou
                          remota chamados por código no servidor
                                                                                             17
Exemplo de aplicação MVC
                                             getCommand(cmd)
                       cmd                                                                  consulta
                               ControlServlet                CommandFactory                                   mapping.xml
                                                                              cria
                                                   executa                            Command

                                        despacha                                                            DefaultCommand
                                                                      Model
                                                                                                       NewMessageCommand
                                            index.html                View
                                                                                                 ShowLastMessageCommand
                                                                      Controller
                                                                                                       ShowMessagesCommand
                             inclui                           usa
                                          messages.jsp
                                                                                     cria                      grava / recupera
www.argonavis.com.br




                               inclui                         usa             MessageBean                   MessageBeanDAO
                                        lastMessage.jsp                                         preenche


                                                          taglib

                                                          PrintMessagesTag
                       navbar.html                                                                            JAXB (XML)
                                                              PrintFieldTag                                      ou BD
                                                                                                                              18
ControlServletTest: client set up
                       import org.apache.cactus.*;
                       import junit.framework.*;

                       ...

                       public class ControlServletTest extends ServletTestCase {

                             private String testMessage = "This is a Web Message.";

                           public void beginServiceNewMessage(WebRequest clientRequest) {
                               clientRequest.addParameter("cmd", "newMessage");
                               clientRequest.addParameter("message", testMessage);
                           }
                           public void beginServiceShowLastMessage(WebRequest clientRequest) {
                               clientRequest.addParameter("cmd", "showLastMessage");
www.argonavis.com.br




                           }
                           public void beginServiceShowMessages(WebRequest clientRequest) {
                               clientRequest.addParameter("cmd", "showAllMessages");
                           }
                           public void beginServiceDefaultCommand(WebRequest clientRequest) {
                               // nothing or unknown command
                           }
                          ...


                                                                                                 19
ControlServletTest: server set up & fixture
                       ...
                             private HttpServlet servlet;
                             private String messageDir = "/tmp/test";

                             public void setUp() throws ServletException {
                                 config.setInitParameter("mappings-file",
                                                         "/WEB-INF/mapping.xml");
                                 config.setInitParameter("message-dir",
                                                         messageDir);
                                 servlet = new ControlServlet();
                                 servlet.init(this.config);
www.argonavis.com.br




                             }
                       ...




                                                                                    20
ControlServletTest: server-side tests
                       ...

                       public void _testService() throws ServletException, IOException {
                               System.out.print("Starting servlet...");
                               servlet.service(this.request, this.response);
                               System.out.println("Server side testing is done.");
                       }
                       public void testServiceNewMessage() throws ServletException, IOException {
                               assertEquals("newMessage", request.getParameter("cmd"));
                               assertEquals(testMessage, request.getParameter("message"));
                               _testService();
                       }
                       public void testServiceShowLastMessage() throws ServletException,... {
                               assertEquals("showLastMessage", request.getParameter("cmd"));
                               _testService();
www.argonavis.com.br




                       }
                       public void testServiceShowMessages() throws ServletException,IOException {
                               assertEquals("showAllMessages", request.getParameter("cmd"));
                               _testService();
                       }
                       public void testServiceDefaultCommand() throws ServletException,... {
                               _testService();
                       }
                       ...
                                                                                                 21
ControlServletTest: clientp-side response
                       public void
                         endServiceNewMessage(com.meterware.httpunit.WebResponse clientResponse)
                                                             throws SAXException, IOException {
                               String pageTitle = clientResponse.getTitle();
                               assertTrue("Wrong page: " + pageTitle,
                                           pageTitle.indexOf("Last Message") >= 0);
                               String responseString = clientResponse.getText();
                               assertTrue("Test Message is not in result page!",
                                          responseString.indexOf(testMessage) >= 0);
                       }

                       public void endServiceShowLastMessage(...) ... {
                               String pageTitle = clientResponse.getTitle();
                               assertTrue("Wrong page: " + pageTitle,
www.argonavis.com.br




                                           pageTitle.indexOf("Last Message") >= 0);
                       }

                       public void endServiceShowMessages(...) ... {
                               String pageTitle = clientResponse.getTitle();
                               assertTrue("Wrong page: " + pageTitle,
                                           pageTitle.indexOf("All Messages") >= 0);
                           }
                       ...
                       }
                                                                                                   22
PrintMessagesTagTest
                       public class PrintMessagesTagTest extends JspTestCase {
                           ...
                           public void testDoAfterBody() throws JspException, java.io.IOException {
                               tag.doStartTag();
                               bodyContent = pageContext.pushBody();
                               tag.setBodyContent(bodyContent); int count = 0;
                               do {
                                   bodyContent.print(
                                  "<test>"+testBeans[count].getMessage()+"</test>");
                                   assertEquals("Unexpected contents.",
                                               "<test>This is Cactus Test Message number "
                                               + (count + 1) + "</test>",
                                               tag.getBodyContent().getString());
                                   count++;
                               } while (tag.doAfterBody() == tag.EVAL_BODY_BUFFERED);
                               pageContext.popBody();
                               assertEquals(3, count);
www.argonavis.com.br




                               assertEquals("Body Content not empty!", "",
                                             tag.getBodyContent().getString().trim());
                           }
                           public void endDoAfterBody(WebResponse response) {
                               String resultString = "";
                               for (int i = 0; i < 3; i++) {
                                   resultString += "<test>This is Cactus Test Message number "
                                                   + (i + 1) + "</test>";
                               }
                               assertEquals(resultString, response.getText());
                           } ...
                       }                                                                          23
Testes em aplicações Web: conclusões
                       Aplicações Web são difíceis de testar porque dependem da
                       comunicação com servlet containers
                          Stubs, proxies e APIs, que estendem ou cooperam com o JUnit,
                          tornam o trabalho mais fácil
                          Neste bloco, conhecemos três soluções que facilitam
                          testes de unidade, de integração e de caixa-preta em
                          aplicações Web
                       Stubs como ServletUnit permitem testar as unidades de
                       código mesmo que um servidor não esteja presente
www.argonavis.com.br




                       Proxies como os "redirectors" do Cactus permitem testar a
                       integração da aplicação com o container
                       Uma API, como a fornecida pelo HttpUnit ajuda a testar o
                       funcionamento da aplicação do ponto de vista do usuário
                                                                                     24
Fontes
                       [1] RichardHightower e Nicholas Lesiecki. Java Tools for eXtreme Programming.
                          Wiley, 2002. Explora as ferramentas Ant, JUnit, Cactus, JUnitPerf, JMeter, HttpUnit usando
                          estudo de caso com processo XP.

                       [2] Apache    Cactus User's Manual. Contém tutorial para instalação passo-a-passo.
                       [3] Mackinnon,    Freeman, Craig. Endo-testing with Mock Objects.
                          http://mockobjects.sourceforge.net/misc/mockobjects.pdf. O autor apresenta técnicas para testes
                          usando uma variação da técnica de stubs chamada de "mock objects".
www.argonavis.com.br




                                                                                                                        25
Palestra: Cactus


              helder@argonavis.com.br

         Selecione o link relativo a esta palestra no endereço

www.argonavis.com.br/xpbrasil2002
  Recursos disponíveis no site:
  • Palestra completa em PDF
  • Todo o código-fonte usado nos exemplos e demonstrações
  • Instruções detalhadas sobre como rodar e instalar os exemplos
  • Links para software utilizado e documentação


          Tutorial: Implementando eXtreme Programming em Java
                         XP Brasil 2002, São Paulo
                         © 2002, Helder da Rocha

Weitere ähnliche Inhalte

Was ist angesagt?

Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)Helder da Rocha
 
Sistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBSistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBAdriano Teixeira de Souza
 
Introdução a Linguagem Java
Introdução a Linguagem JavaIntrodução a Linguagem Java
Introdução a Linguagem JavaUFPA
 
A arquitetura modular do Java 9
A arquitetura modular do Java 9A arquitetura modular do Java 9
A arquitetura modular do Java 9Helder da Rocha
 
Construção de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em JavaConstrução de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em JavaFernando Camargo
 
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...Adriano Teixeira de Souza
 
Introdução à Metaprogramação com Java Reflection API
Introdução à Metaprogramação com Java Reflection APIIntrodução à Metaprogramação com Java Reflection API
Introdução à Metaprogramação com Java Reflection APIGuilherme de Cleva Farto
 
001 cesep - turma java
001   cesep - turma java001   cesep - turma java
001 cesep - turma javaJunior Souza
 
Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Helder da Rocha
 
Java 02 Iniciando Uso Java
Java 02 Iniciando Uso JavaJava 02 Iniciando Uso Java
Java 02 Iniciando Uso JavaRegis Magalhães
 
Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5Gilberto Holms
 

Was ist angesagt? (20)

Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
 
Fundamentos de Objetos Remotos
Fundamentos de Objetos RemotosFundamentos de Objetos Remotos
Fundamentos de Objetos Remotos
 
Sistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBSistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJB
 
Introdução a Linguagem Java
Introdução a Linguagem JavaIntrodução a Linguagem Java
Introdução a Linguagem Java
 
Java 9, 10, 11
Java 9, 10, 11Java 9, 10, 11
Java 9, 10, 11
 
A arquitetura modular do Java 9
A arquitetura modular do Java 9A arquitetura modular do Java 9
A arquitetura modular do Java 9
 
Construção de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em JavaConstrução de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em Java
 
Java 14
Java 14Java 14
Java 14
 
Tutorial +login+mvc
Tutorial +login+mvcTutorial +login+mvc
Tutorial +login+mvc
 
Java 01
Java 01Java 01
Java 01
 
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
 
Introdução à Metaprogramação com Java Reflection API
Introdução à Metaprogramação com Java Reflection APIIntrodução à Metaprogramação com Java Reflection API
Introdução à Metaprogramação com Java Reflection API
 
Aula JPA
Aula JPAAula JPA
Aula JPA
 
001 cesep - turma java
001   cesep - turma java001   cesep - turma java
001 cesep - turma java
 
Introducao logica2
Introducao logica2Introducao logica2
Introducao logica2
 
Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)
 
Aplicações web parte 2
Aplicações web parte 2Aplicações web parte 2
Aplicações web parte 2
 
Java 02 Iniciando Uso Java
Java 02 Iniciando Uso JavaJava 02 Iniciando Uso Java
Java 02 Iniciando Uso Java
 
Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5
 
Benchmarking Tools
Benchmarking ToolsBenchmarking Tools
Benchmarking Tools
 

Andere mochten auch

Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigmsrodrigovmoraes
 
Transfromada de Laplace
Transfromada de LaplaceTransfromada de Laplace
Transfromada de Laplacerodrigovmoraes
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your BusinessBarry Feldman
 

Andere mochten auch (6)

Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigms
 
Heap
HeapHeap
Heap
 
Proyecto
ProyectoProyecto
Proyecto
 
Transfromada de Laplace
Transfromada de LaplaceTransfromada de Laplace
Transfromada de Laplace
 
AES Proposal
AES ProposalAES Proposal
AES Proposal
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
 

Ähnlich wie Teste Integração J2EE Cactus

Ähnlich wie Teste Integração J2EE Cactus (20)

Cactus - Testes em J2EE com Jakarta Cactus
Cactus - Testes em J2EE com Jakarta CactusCactus - Testes em J2EE com Jakarta Cactus
Cactus - Testes em J2EE com Jakarta Cactus
 
Testes em aplicações JEE: Montando sua infra de testes automatizados
Testes em aplicações JEE: Montando sua infra de testes automatizadosTestes em aplicações JEE: Montando sua infra de testes automatizados
Testes em aplicações JEE: Montando sua infra de testes automatizados
 
Framework struts2v2.5
Framework struts2v2.5Framework struts2v2.5
Framework struts2v2.5
 
Tutorial struts
Tutorial strutsTutorial struts
Tutorial struts
 
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
 
Conceitos de Java Web
Conceitos de Java WebConceitos de Java Web
Conceitos de Java Web
 
Apache e Java
Apache e JavaApache e Java
Apache e Java
 
1409243945064
14092439450641409243945064
1409243945064
 
servlet-introducao
servlet-introducaoservlet-introducao
servlet-introducao
 
JUDCon Brazil 2013
JUDCon Brazil 2013JUDCon Brazil 2013
JUDCon Brazil 2013
 
MC - Java Enterprise Edition 6 (Java EE)
MC - Java Enterprise Edition 6 (Java EE)MC - Java Enterprise Edition 6 (Java EE)
MC - Java Enterprise Edition 6 (Java EE)
 
JAVA REFLETCION
JAVA REFLETCIONJAVA REFLETCION
JAVA REFLETCION
 
Asp net mvc
Asp net mvcAsp net mvc
Asp net mvc
 
Apostilava Java EE 5 - 2007
Apostilava Java EE 5 - 2007Apostilava Java EE 5 - 2007
Apostilava Java EE 5 - 2007
 
Uso de Critérios de Seleção para Frameworks Livres em Plataforma Java EE
Uso de Critérios de Seleção para Frameworks Livres em Plataforma Java EEUso de Critérios de Seleção para Frameworks Livres em Plataforma Java EE
Uso de Critérios de Seleção para Frameworks Livres em Plataforma Java EE
 
Introdução ao java
Introdução ao javaIntrodução ao java
Introdução ao java
 
Sistema S2DG e Tecnologias Web
Sistema S2DG e Tecnologias WebSistema S2DG e Tecnologias Web
Sistema S2DG e Tecnologias Web
 
Apresentação JSF
Apresentação JSFApresentação JSF
Apresentação JSF
 
Servlets e jsp
Servlets e jspServlets e jsp
Servlets e jsp
 
Apache Struts
Apache StrutsApache Struts
Apache Struts
 

Teste Integração J2EE Cactus

  • 1. eXtreme Programming Brasil Testes de Integração em J2EE com Jakarta CACTUS Helder da Rocha (helder@acm.org) argonavis.com.br
  • 2. Objetivos 1. Discutir as dificuldades relativas a testes em J2EE 2. Apresentar o framework Cactus e demonstrar como utilizá-lo para testar aplicações J2EE 3. Mostrar como usar o Cactus com extensões como HttpUnit e JUnitEE para testar servlets e EJBs www.argonavis.com.br Público-alvo: Programadores J2EE familiarizados com o JUnit 2
  • 3. Por que outro framework para testes J2EE? JUnit não é suficiente? Sim, para testes de unidade (lógica de EJBs, por exemplo) Aplicações J2EE possuem muitas dependências (é preciso simular a rede, o servidor, o EJB container, etc.) Testes de unidade não garantem o funcionamento de toda uma aplicação J2EE Mock objects não servem? Sim, mock objects ajudam a testar com dependências e www.argonavis.com.br permitem testar toda a aplicação Mock objects podem ficar muito complicados Aplicações geralmente rodam em um servidor de aplicação ou Web - testar a integração da aplicação com o servidor é mais útil e mais fácil 3
  • 4. O que é Cactus? Um framework que oferece facilidades para testar componentes J2EE Componentes Web (Camada de Controle) Camada EJB (Model) e cliente (View): indiretamente Produto Open Source do projeto Jakarta Metas de curto prazo: testar servlets, JSPs, filtros e EJB Metas de longo prazo: oferecer facilidades para testar todos os componentes J2EE; ser o framework de www.argonavis.com.br referência para testes in-container. Cactus estende o JUnit framework Execução dos testes é realizada de forma idêntica TestCases são construídos sobre uma subclasse de junit.framework.TestCase 4
  • 5. Para que serve? Para testar aplicações que utilizam componentes J2EE Arquitetura MVC Controller Model Servlets, filtros e custom Servlets Taglibs EJBs Remotos tags (Controladores) Classes Classes EJBs Locais Filtros JSPs (camada de apre- Java Java sentação: View, através de controladores) JSP Velocity EJB (Modelo de dados/ XSLT View lógica de negócios) www.argonavis.com.br Cactus testa a integração desses componentes com seus containers não usa stubs - usa o próprio container como servidor e usa JUnit como cliente comunicação é intermediada por um proxy Ilustração: Manual do Cactus 5
  • 6. Como funciona? Cactus utiliza os test cases simultaneamente no cliente e no servidor: duas cópias Uma cópia é instanciada pelo servlet container Outra cópia é instanciada pelo JUnit Comunicação com o servlet container é feita através de um proxy (XXXRedirector) JUnit envia requisições via HTTP para proxy Proxy devolve resultado via HTTP e JUnit os mostra www.argonavis.com.br Há, atualmente (Cactus 1.3) três tipos de proxies: ServletRedirector: para testar servlets JSPRedirector: para testar JSP custom tags FilterRedirector: para testar filtros de servlets 6
  • 7. Arquitetura Parte da mesma classe (ServletTestCase) é executada no cliente, parte no servidor (4) setUp() org.apache.cactus. testXXX() ServletTestCase (1) beginXXX() tearDown() (2) (8) (3) Redirector ServletTestCase ServletTestCase Servlet (6) (7) (9) (10) endXXX() MeuServletTestCase (5) request: AbstractHttpServletRequest response: HttpServletResponse lado lado www.argonavis.com.br cliente servidor Classes config: ServletConfigWrapper lado-servidor ... beginXXX(WebRequest) null, no cliente setUp() testXXX() executados apenas no servidor tearDown() endXXX(WebResponse) executados apenas no cliente 7
  • 8. Diagrama UML www.argonavis.com.br Fonte: Manual do usuário do Cactus 8
  • 9. ServletTestCase (ou similar) Para cada método XXX() a ser testado, pode haver: Um beginXXX(), para inicializar a requisição do cliente encapsulada em um objeto WebRequest a ser enviado ao servidor Um testXXX(), para testar o funcionamento do método no servidor (deve haver ao menos um) Um endXXX(), para verificar a resposta do servidor devolvida em um objeto WebResponse retornada pelo servidor Além desses três métodos, cada TestCase pode conter www.argonavis.com.br setUp(), opcional, para inicializar objetos no servidor tearDown(), opcional, para liberar recursos no servidor Os métodos do lado do servidor têm acesso aos mesmos objetos implícitos disponíveis em um servlet ou página JSP: request, response, etc. 9
  • 10. Cactus: exemplo Veja cactusdemo.zip (distribuído com esta palestra) Usa duas classes: um servlet (MapperServlet) e uma classe (SessionMapper) que guarda cada parâmetro como atributo da sessão e em um HashMap - veja fontes em src/xptoolkit/cactus Para rodar, configure o seu ambiente: build.properties - localização dos JARs usados pelo servidor Web (CLASSPATH do servidor) runtests.bat (para Windows) e runtests.sh (para Unix) - localização dos JARs usados pelo JUnit (CLASSPATH do cliente) www.argonavis.com.br lib/client.properties (se desejar rodar cliente e servidor em máquinas separadas, troque as ocorrências de localhost pelo nome do servidor) Para montar, execute: 1. ant test-deploy instala cactus-tests.war no tomcat 2. o servidor (Tomcat 4.0 startup) veja demonstração 3. runtests.bat roda os testes no JUnit cactusdemo.zip 10
  • 11. CactusDemo: servlet O objetivo deste servlet é 1) gravar qualquer parâmetro que receber na sessão (objeto session) 2) devolver uma página contendo os pares nome/valor em uma tabela 3) imprimir resposta em caixa-alta se <init-param> ALL_CAPS definido no web.xml contiver o valor true public void doGet(...) throws IOException { (1) Grava request SessionMapper.mapRequestToSession(request); em session writer.println("<html><body><table border='1'>"); // (... loop for each parameter ...) if (useAllCaps()) { key = key.toUpperCase(); (3) Retorna true se <init-param> val = val.toUpperCase(); "ALL_CAPS" contiver "true" www.argonavis.com.br } str = "<tr><td><b>"+key+"</b></td><td>"+val+"</td></tr>"; writer.println(str); // (...) (2) writer.println("</table></body></html>"); Trecho de } MapperServlet.java Escreveremos os testes para avaliar esses objetivos Fonte do exemplo: [1] 11
  • 12. CactusDemo: testes MapperServletTest.java public class MapperServletTest extends ServletTestCase { (...) private MapperServlet servlet; public void beginDoGet(WebRequest cSideReq) { cSideReq.addParameter("user", "Jabberwock"); Simula DD } <init-param> public void setUp() throws ServletException { this.config.setInitParameter("ALL_CAPS", "true"); servlet = new MapperServlet(); servlet.init(this.config); } Simula servlet public void testDoGet() throws IOException { container servlet.doGet(this.request, this.response); String value = (String) session.getAttribute("user"); www.argonavis.com.br assertEquals("Jabberwock", value); } Verifica se parâmetro foi public void tearDown() { /* ... */ } mapeado à sessão public void endDoGet(WebResponse cSideResponse) { String str = cSideResponse.getText(); assertTrue(str.indexOf("USER</b></td><td>JABBERWOCK") > -1); } } Verifica se parâmetro aparece na tabela HTML 12
  • 13. Exemplo: funcionamento Cliente (JUnit) Servidor (Tomcat) beginDoGet(WebRequest req) - Grava parâmetro: ReqInfo nome=user value=Jabberwock setUp() 2 conexões HTTP: - Define init-params SUCCESS!! FAIL! • Uma p/ rodar os no objeto config testes e obter - Roda init(config) saida do servlet • Outra para esperar testDoGet() resultados de testes - Roda doGet() (info sobre exceções) - Verifica se parâmetro www.argonavis.com.br (no response) foi mapeado à sessão TestInfo falha falha remota local tearDown() & endDoGet(WebResponse res) Output - Verifica se resposta contém USER</b></td><td>JABBERWOCK 13
  • 14. HttpUnit Onde encontrar http://httpunit.sourceforge.net Framework para testes funcionais de interface (teste tipo "caixa-preta") Verifica a resposta de uma aplicação Web ou página HTML É teste funcional caixa-preta (não é "unit") Oferece métodos para "navegar" na resposta links, tabelas, imagens www.argonavis.com.br objetos DOM (Node, Element, Attribute) Pode ser combinado com Cactus no endXXX() Argumento com.meterware.httpunit.WebResponse Acompanha ServletUnit stub que simula o servlet container veja também httpunitdemo.zip 14
  • 15. Resumo da API do HttpUnit WebConversation Representa uma sessão de cliente Web (usa cookies) WebConversation wc = new WebConversation(); WebResponse resp = wc.getResponse("http://xyz.com/t.html"); WebRequest Representa uma requisição WebResponse Representa uma resposta. A partir deste objeto pode-se obter objetos WebLink, WebTable e WebForm WebLink www.argonavis.com.br Possui métodos para extrair dados de links de hipertexto WebTable Possui métodos para navegar na estrutura de tabelas WebForm Possui métodos para analisar a estrutura de formulários 15
  • 16. HttpUnit com Cactus Veja MapperServletTest2.java Troque o WebResponse em cada endXXX() por com.meterware.httpunit.WebResponse public void endDoGet(com.meterware.httpunit.WebResponse resp) throws org.xml.sax.SAXException { WebTable[] tables = resp.getTables(); assertNotNull(tables); assertEquals(tables.length, 1); // só há uma tabela WebTable table = tables[0]; int rows = table.getRowCount(); boolean keyDefined = false; for (int i = 0; i < rows; i++) { String key = table.getCellAsText(i, 0); // col 1 String value = table.getCellAsText(i, 1); // col 2 www.argonavis.com.br if (key.equals("USER")) { keyDefined = true; assertEquals("JABBERWOCK", value); } } if (!keyDefined) { fail("No key named USER was found!"); } } 16
  • 17. Outros testes com Cactus Testes em taglibs (JspRedirector) veja Veja exemplos em cactusdemo/taglib/src taglibdemo.zip Testes em filtros (FilterRedirector) veja também strutsdemo.zip Usa proxy FilterRedirector Teste básico é verificar se método doFilter() foi chamado Veja exemplos em cactusdemo/src/xptoolkit/AuthFilter Testes indiretos em páginas JSP (camada View) veja Ideal é JSP não ter código Java hellojsp.zip www.argonavis.com.br Principais testes são sobre a interface: HttpUnit! Testes indiretos em EJB (camada Model) veja helloejb.zip Indireto, através dos redirectors + JUnitEE Redirectors permitem testar EJBs com interface local ou remota chamados por código no servidor 17
  • 18. Exemplo de aplicação MVC getCommand(cmd) cmd consulta ControlServlet CommandFactory mapping.xml cria executa Command despacha DefaultCommand Model NewMessageCommand index.html View ShowLastMessageCommand Controller ShowMessagesCommand inclui usa messages.jsp cria grava / recupera www.argonavis.com.br inclui usa MessageBean MessageBeanDAO lastMessage.jsp preenche taglib PrintMessagesTag navbar.html JAXB (XML) PrintFieldTag ou BD 18
  • 19. ControlServletTest: client set up import org.apache.cactus.*; import junit.framework.*; ... public class ControlServletTest extends ServletTestCase { private String testMessage = "This is a Web Message."; public void beginServiceNewMessage(WebRequest clientRequest) { clientRequest.addParameter("cmd", "newMessage"); clientRequest.addParameter("message", testMessage); } public void beginServiceShowLastMessage(WebRequest clientRequest) { clientRequest.addParameter("cmd", "showLastMessage"); www.argonavis.com.br } public void beginServiceShowMessages(WebRequest clientRequest) { clientRequest.addParameter("cmd", "showAllMessages"); } public void beginServiceDefaultCommand(WebRequest clientRequest) { // nothing or unknown command } ... 19
  • 20. ControlServletTest: server set up & fixture ... private HttpServlet servlet; private String messageDir = "/tmp/test"; public void setUp() throws ServletException { config.setInitParameter("mappings-file", "/WEB-INF/mapping.xml"); config.setInitParameter("message-dir", messageDir); servlet = new ControlServlet(); servlet.init(this.config); www.argonavis.com.br } ... 20
  • 21. ControlServletTest: server-side tests ... public void _testService() throws ServletException, IOException { System.out.print("Starting servlet..."); servlet.service(this.request, this.response); System.out.println("Server side testing is done."); } public void testServiceNewMessage() throws ServletException, IOException { assertEquals("newMessage", request.getParameter("cmd")); assertEquals(testMessage, request.getParameter("message")); _testService(); } public void testServiceShowLastMessage() throws ServletException,... { assertEquals("showLastMessage", request.getParameter("cmd")); _testService(); www.argonavis.com.br } public void testServiceShowMessages() throws ServletException,IOException { assertEquals("showAllMessages", request.getParameter("cmd")); _testService(); } public void testServiceDefaultCommand() throws ServletException,... { _testService(); } ... 21
  • 22. ControlServletTest: clientp-side response public void endServiceNewMessage(com.meterware.httpunit.WebResponse clientResponse) throws SAXException, IOException { String pageTitle = clientResponse.getTitle(); assertTrue("Wrong page: " + pageTitle, pageTitle.indexOf("Last Message") >= 0); String responseString = clientResponse.getText(); assertTrue("Test Message is not in result page!", responseString.indexOf(testMessage) >= 0); } public void endServiceShowLastMessage(...) ... { String pageTitle = clientResponse.getTitle(); assertTrue("Wrong page: " + pageTitle, www.argonavis.com.br pageTitle.indexOf("Last Message") >= 0); } public void endServiceShowMessages(...) ... { String pageTitle = clientResponse.getTitle(); assertTrue("Wrong page: " + pageTitle, pageTitle.indexOf("All Messages") >= 0); } ... } 22
  • 23. PrintMessagesTagTest public class PrintMessagesTagTest extends JspTestCase { ... public void testDoAfterBody() throws JspException, java.io.IOException { tag.doStartTag(); bodyContent = pageContext.pushBody(); tag.setBodyContent(bodyContent); int count = 0; do { bodyContent.print( "<test>"+testBeans[count].getMessage()+"</test>"); assertEquals("Unexpected contents.", "<test>This is Cactus Test Message number " + (count + 1) + "</test>", tag.getBodyContent().getString()); count++; } while (tag.doAfterBody() == tag.EVAL_BODY_BUFFERED); pageContext.popBody(); assertEquals(3, count); www.argonavis.com.br assertEquals("Body Content not empty!", "", tag.getBodyContent().getString().trim()); } public void endDoAfterBody(WebResponse response) { String resultString = ""; for (int i = 0; i < 3; i++) { resultString += "<test>This is Cactus Test Message number " + (i + 1) + "</test>"; } assertEquals(resultString, response.getText()); } ... } 23
  • 24. Testes em aplicações Web: conclusões Aplicações Web são difíceis de testar porque dependem da comunicação com servlet containers Stubs, proxies e APIs, que estendem ou cooperam com o JUnit, tornam o trabalho mais fácil Neste bloco, conhecemos três soluções que facilitam testes de unidade, de integração e de caixa-preta em aplicações Web Stubs como ServletUnit permitem testar as unidades de código mesmo que um servidor não esteja presente www.argonavis.com.br Proxies como os "redirectors" do Cactus permitem testar a integração da aplicação com o container Uma API, como a fornecida pelo HttpUnit ajuda a testar o funcionamento da aplicação do ponto de vista do usuário 24
  • 25. Fontes [1] RichardHightower e Nicholas Lesiecki. Java Tools for eXtreme Programming. Wiley, 2002. Explora as ferramentas Ant, JUnit, Cactus, JUnitPerf, JMeter, HttpUnit usando estudo de caso com processo XP. [2] Apache Cactus User's Manual. Contém tutorial para instalação passo-a-passo. [3] Mackinnon, Freeman, Craig. Endo-testing with Mock Objects. http://mockobjects.sourceforge.net/misc/mockobjects.pdf. O autor apresenta técnicas para testes usando uma variação da técnica de stubs chamada de "mock objects". www.argonavis.com.br 25
  • 26. Palestra: Cactus helder@argonavis.com.br Selecione o link relativo a esta palestra no endereço www.argonavis.com.br/xpbrasil2002 Recursos disponíveis no site: • Palestra completa em PDF • Todo o código-fonte usado nos exemplos e demonstrações • Instruções detalhadas sobre como rodar e instalar os exemplos • Links para software utilizado e documentação Tutorial: Implementando eXtreme Programming em Java XP Brasil 2002, São Paulo © 2002, Helder da Rocha