Testando aplicações web

É bem mais complicado testar interfaces web do que classes Java.

Aplicações WEB não permitem verificar facilmente se o conteúdo presente é o esperado. Informações importantes que precisam ser avaliadas encontram-se misturadas com tags HTML.

O layout das aplicações web mudam com frequência.

É preciso construir testes que não precisem ser reescritos toda vez que o layout das páginas mudem.

Alguns problemas que dificultam a criação de testes automáticos para aplicações web:

Tanto páginas JSP quanto Servlets são complicadas de testar, pois é necessário um container rodando para poder avaliar suas funcionalidades.

Além disso, páginas JSP são particularmente complicadas de testar, pois elas não existem até que o deployment seja feito dentro do container web.

Aplicações WEB são difíceis de testar pois dependem da comunicação com o container.

Para testar aplicações WEB precisamos fazer:

Veremos aqui três tecnologias:

 

ServletUnit

Nós podemos testar as camadas das classes Java presentes de uma aplicação WEB fora do container utilizando a API JUnit, entretanto faz-se necessário criar mock objects para emular o container.

O projeto ServletUnit provê um mecanismo que permite invocar servlets e outras classes dependentes da API Servlet fora do container.

Permite invocar diretamente métodos e fazer asserções nas suas respostas. Dessa forma, podemos avaliar o valor dos atributos e parâmetros associados com cada requisição.

ServletUnit é parte do framework HttpUnit e pode ser utilizado para testar servlets fora do servlet container. Embora HttpUnit possa ser utilizado para testar servlets e JSPs, ele é mais utilizado para fazer testes de caixa-preta (ex.: testes funcionais) do ponto de vista do browser. 

ServletUnit também permite testar métodos individuais. 

ServletUnit simula servlet container que prover todas as funcionalidades de servlet container real. Os seguintes passos são necessários para testar um servlet:

  1. Criar um instância da classe ServletRunner. Essa é a classe que simula o container e permite o acesso a objetos do servlet que estejam rodando.

  2. Registrar o(s) servlet(s) que serão testados no contexto simulado pelo ServletRunner.

  3. Criar um ServletUnitClient. Esse cliente permitirá acessar diferentes partes dos servlets registrados.

  4. Criar uma WebRequest que é usado para chamar o servlet.

  5. Recuperar o InvocationContext. O InvocationContext consiste em um objeto que permite acessar os objetos request e response.

  6. Uma vez possuindo o InvocationContext, é possível acessar o servlet e executar seus métodos. Isso permite testar partes do servlets, e não apenas seu resultado como um todo.

Seja o seguinte servlet a ser testado:

public class SimpleServlet extends HttpServlet { 
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String user = getUser(request, response);
response.getWriter().print("User that call this servlet is " + user);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

public String getUser(HttpServletRequest request, HttpServletResponse response) {
return((String)request.getAttribute("UserName"));
}
}

Seja o teste para o servlet apresentado:

public void testServletGetUser(){
ServletRunner sr = new ServletRunner();
sr.registerServlet("SimpleServlet", SimpleServlet.class.getName());
ServletUnitClient sc = sr.newClient();
WebRequest request = new PostMethodWebRequest("http://localhost/SimpleServlet");
try {
InvocationContext ic = sc.newInvocation(request);
SimpleServlet simpleServlet = (SimpleServlet) ic.getServlet();
HttpServletRequest simpleServletRequest = ic.getRequest();
simpleServletRequest.setAttribute("UserName", "TimmyC");
String userName = simpleServlet.getUser(ic.getRequest(),ic.getResponse());
assertEquals("TimmyC", userName);
}
catch (Exception e){
fail("Error testing getUser exception is " + e);
e.printStackTrace();
}
}

 

Exemplo mais completo

HTTPUnit

Nome Cor
morango vermelho
pêssego amarelo

 

Cactus 

Arquitetura

public class TestSimpleServlet extends ServletTestCase {
public void beginRegisterUser(WebRequest theRequest) {
theRequest.addParameter("USER_NAME", "Vincent");
}

public void testRegisterUser() throws ServletException {
SimpleServlet servlet = new SimpleServlet();
try {
servlet.doGet(request, response);
} catch (IOException e) {
fail("Exception not expected!");
}
String name = servlet.registerUser(request, response);
assertEquals("Vincent", name);
assertEquals("Vincent", (String) session.getAttribute("NAME"));
}

public void endRegisterUser(WebResponse theResponse) {
Cookie cookie = theResponse.getCookie("ID");
assertEquals("Vincent", cookie.getValue());
assertEquals("<html><body><h1>Your name is Vincent</h1></body></html>", theResponse.getText());
}

}
public void endRegisterUser(com.meterware.httpunit.WebResponse theResponse) throws SAXException {
assertEquals("Vincent", theResponse.getNewCookieValue("ID"));
WebTable table = theResponse.getTables()[0];
assertEquals("rows", 1, table.getRowCount());
assertEquals("columns", 2, table.getColumnCount());
assertEquals("value", "Vincent" , table.getTableCell(0, 1).getText());
assertEquals("title", "Teste cactus!" , theResponse.getTitle());
}

Download

Download do exemplo completo (utilizando ServletUnit, HttpUnit e Cactus)

Bibliografica

Livro Test Driven Development: A J2EE Example; Russell Gold, Thomas Hammell and Tom Snyder ISBN:1590593278 Apress © 2005

Livro J2EE Design and Development

Site http://httpunit.sourceforge.net

Site http://jakarta.apache.org/cactus

Material de Helder Rocha - Testes de integração em J2EE com Jakarta Cactus

Material de Julio Cesar Fernander Correa - Conhecendo o Framework HttpUnit; Como usar o HttpUnit com o JUnit para testar sua aplicação WEB.