Você está na página 1de 33

Testes de Unidade com JUnit

Introduo prtica ao uso de JUnit para desenvolver testes unitrios

JUnit

Junit: framework para desenvolvimento e execuo de testes de unidade em programas Java Define um modelo de programao para a criao de testes de unidade em classes Java Disponibiliza o TestRunner: aplicao em modo texto ou grfico para execuo de testes Podemos baixar o Junit em www.junit.org O arquivo junit.jar deve estar no classpath do nosso projeto

Facilidades do JUnit

Permite criao de testes unitrios para mtodos pertencentes a uma classe Permite a definio e execuo de um conjunto de testes unitrios Suites de Teste Permite a execuo de teste com relato de problemas ocorridos e onde especificamente ocorreram os erros

JUnit Passo a Passo

1 Passo)

Criar uma classe de teste para cada classe a ser testada Exemplo: classe Aritmetica ter como classe de teste AritmeticaTest A classe de Teste deve herdar da classe TestCase do framework JUnit

JUnit Passo a Passo

2 Passo)

criar mtodos de teste para cada mtodo (ou funcionalidade) a ser testado (cujos nomes devem comear com a palavra test) com tipo de retorno void. Exemplo para a classe AritmeticaTest:
public void testSoma() public void testSubtracao() public void testDivisao() public void testMultiplicacao()

JUnit Passo a Passo

3 Passo)

para cada mtodo de teste definir seu comportamento: invocao de mtodos da classe do sistema a ser testada avaliao do resultado dos mtodos sendo testados usando os mtodos assertEquals(), fail(), assertNull(), assertNotNull() do framework JUnit

JUnit Passo a Passo


Mtodo assertEquals(a,b) assertFalse(a) assertTrue(a) assertNotNull(a) assertNull(a) assertNotSame(a,b) assertSame(a,b) fail() Descrio Compara dois valores Avalia uma expresso booleana Compara uma varivel com nulo Compara dois objetos Causa uma falha no teste atual Teste passa se a.equals(b) a == false a == true a != null a == null a == b a != b

JUnit Passo a Passo: Exemplo


public class Aritmetica { public int soma(int op1, int op2) { return op1 + op2; } public int subtracao(int op1,int op2) { return op1 -op2; } public int multiplicacao(int op1, int op2) { return op1 * op2; } public int divisao(int op1, int op2) throws Exception { if (op2 == 0 ) { throw new Exception("Divisao por zero"); } else { return op1/op2; } } }

JUnit Passo a Passo: Exemplo


import junit.framework.*; public class AritmeticaTest extends TestCase { public void testSoma() { Aritmetica operacoes = new Aritmetica(); this.assertEquals(4,operacoes.soma(3,1)); } public void testSubtracao(){ Aritmetica operacoes = new Aritmetica(); this.assertEquals(2, operacoes.subtracao(3,1)); } public void testDivisao() { Aritmetica operacoes = new Aritmetica(); try { operacoes.divisao(3,0); fail("Deveria lanar Excecao"); } catch (Exception e) { } } public void testMultiplicacao(){ Aritmetica operacoes = new Aritmetica(); this.assertEquals(3,operacoes.multiplicacao(3,1)); } }

JUnit Passo a Passo: Exemplo

Como Executar o teste? Direto na linha de comando:

java junit.textui.TestRunner ContaTeste

Ou inserir os mtodos abaixo na classe de teste


} public static void main(String[] args){ junit.textui.TestRunner.run(suite()); }

public static Test suite(){ return new TestSuite(AritmeticaTest.class);

TestRunner chama suite() automaticamente e trata como testes (e executa) todos os mtodos sem argumentos cujos nomes comearem com "test"

JUnit Passo a Passo: Exemplo

Teste com erro

Teste sem erro

Observaes

Caso necessrio, pode-se definir configuraes iniciais para serem executadas antes de cada mtodo de teste usando o mtodo setUp() configurao de objetos comuns aos casos de teste configurao de recursos comuns aos casos de teste (exemplo: abertura de conexes de banco de dados, socket, etc) Para liberar recursos utilizados pelos mtodos de teste pode-se usar o mtodo tearDown() Exemplos de recursos que podem ser liberados: streams, fechar conexes de banco de dados, apagar/mover arquivos de dados.

JUnit Passo a Passo


public class Aritmetica { private int op1,op2; public void setOp1(int op1) { this.op1 = op1; } public void setOp2(int op2) { this.op2 = op2; } public int soma() { return op1 + op2; } public int subtracao() { return op1 -op2; } public int multiplicacao() { return op1 * op2; } public int divisao() throws Exception { if (op2 == 0 ) { throw new Exception("Divisao por zero"); } else { return op1/op2; } } }

JUnit Passo a Passo


import junit.framework.*; public class AritmeticaTest extends TestCase { Aritmetica operacoes; public void setUp() { operacoes = new Aritmetica(); operacoes.setOp1(3); operacoes.setOp2(1); } public void testSoma() { this.assertEquals(4,operacoes.soma()); } public void testSubtracao(){ this.assertEquals(2, operacoes.subtracao()); } public void testDivisao() { try { this.assertEquals(3,operacoes.divisao()); } catch (Exception e) { } }

Executa antes de cada mtodo de teste

public void testMultiplicacao(){ this.assertEquals(3,operacoes.multiplicacao()); } }

Execuo JUnit

Seqncia de execuo do JUnit: Cria uma instncia da classe de teste para cada mtodo de teste. (Exemplo: 4 testes, 4 instncias). O test case instanciado para executar um mtodo testXXX() de cada vez. As alteraes que ele fizer ao estado do objeto no afetaro os demais testes

Para cada instncia:


Chama o mtodo setUp(); Chama o mtodo de teste; Chama o mtodo tearDown();

Suites de Testes

Quando falamos em teste automatizado, comum querermos executar um conjunto de testes de uma nica vez; Suites de testes representam um conjunto de testes que sero executados seqencialmente; JUnit define a classe TestSuite que:

Permite incluir todos os mtodos de teste de uma classe em um suite de teste; Permite definir uma classe que inclui todos os suites de teste das classes do sistema.

TestSuite

P ermite executar uma coleo de testes

Mtodo addTest(TestS uite) adiciona um teste na lista P adro de codificao: retornar um TestS uite em cada test-case:

criar uma classe AllTests que combina as suites:


public class AllTests { public static Test suite() { TestSuite testSuite = new TestSuite("Roda tudo"); testSuite.addTest(pacote.AllTests.suite()); testSuite.addTest(MinhaClasseTest.suite()); testSuite.addTest(SuaClasseTest.suite()); return testSuite;

public static TestSuite suite() { return new TestSuite(SuaClasseTest.class); }

Observaes gerais

Cada teste deve verificar um pedao especfico da funcionalidade No combine testes no relacionados em um nico mtodo testXXX() Se o primeiro teste falhar os seguintes no sero executados

Testes com Objetos Mock

Mocks

So objetos de mentira (substitutos) que permitem isolar classes de um sistema.

Conta

LinhaItem Item: Item quantidade: int total(): int

Item nome:String preco: int

adicionar(): void total(): int

Testes com Objetos Mock


public class Conta { private int total; public void adiciona (LinhaItem linhaItem) { total += linhaItem.total(); } public int total() { return total; } } public class LinhaItem { private Item item; private int quantidade; public class Item { private String nome; private int preco; public void setNome(String nome) { this.nome = nome; } public void setPreco(int preco) { this.preco = preco; } }

public LinhaItem(Item item, int quantidade) { this.item = item; this.quantidade = quantidade; } public int total() { return item.getPreco() * quantidade; }

Testes com Objetos Mock


import junit.framework.TestCase; public class ContaTeste extends TesteCase { Conta conta = new Conta(); Item lasanha = new Item(); lasanha.setNome("Lasanha verde"); lasanha.setPreco(10); Item refrigerante = new Item(); refrigerante.setNome("Guaran"); refrigerante.setPreco(2); Item sorvete = new Item(); sorvete.setNome("Sorvete de Chocolate"); sorvete.setPreco(4); Item cafe = new Item(); cafe.setNome("Cafe Expresso"); cafe.setPreco(1); LinhaItem LinhaItem LinhaItem LinhaItem linhaLasanha = new LinhaItem(lasanha, 2); linhaRefri = new LinhaItem(refrigerante, 4); linhaSorvete = new LinhaItem(sorvete, 1); linhaCafe = new LinhaItem(cafe, 2);

conta.adiciona(linhaLasanha); conta.adiciona(linhaRefri); conta.adiciona(linhaSorvete); conta.adiciona(linhaCafe); } } assertEquals(34. conta.total);

Testes com Objetos Mock

Problemas da classe ContaTeste:


Mtodo de teste maior e complexo; O teste no verdadeiramente um teste de unidade:

Uma falha no teste pode ser causada por uma falha na classe Conta, na classe LinhaItem ou mesmo na classe Item.

Soluo:

Usar objetos mock Elimina a dependncia entre as classes (Conta e LinhaItem) Ao testarmos, ao invs de usar a classe LinhaItem, usaremos uma classe que finge ser a ela.

Testes com Objetos Mock

Como usar mock no exemplo?

Usaremos uma classe especial chamada de LinhaMock

A classe LinhaItem passa a implementar uma interface, Linha, com um nico mtodo: total() Esse mtodo ser utilizado pela classe Conta.
public interface Linha{ int total(); }

Essa classe j recebe no construtor o valor total de uma LinhaItem.

Testes com Objetos Mock

Nova classe de Teste:


public class ContaTeste{ public void TestaTotalNota() { Conta conta = new Conta(); conta.adiciona(new LinhaMock(20)); conta.adiciona(new LinhaMock(8)); conta.adiciona(new LinhaMock(2)); conta.adiciona(new LinhaMock(1)); conta.adiciona(new LinhaMock(1)); assertEquals(32,conta.total()); } public static Test suite(){ return new TestSuite(ContaTeste.class); } }

Usando Easymock

Nem sempre simples escrever objetos mock. Ferramenta Easymock: APIs para gerar objetos mock. Como fazer para testar um servlet que implementa um mecanismo simplificado de login, recebendo dois parmetros: login e senha.

Para obter parmetros em um servlet usamos

getParameter(nomeParametro) da interface HttpServletRequest

Usando Easymock

Qual seria o problema?

A interface HttpServletRequest possui mais de 10 mtodos e s estamos interessados no getParameter().

Criar um mock objeto para isso significa criar uma classe coma implementao desejada de getParameter() e uma implementao vazia ou mnima para todos os outros mtodos.

Soluo:

Usar APIs para gerar e manipular objetos mock. Ao invs de criarmos uma classe que implementa uma interface especfica, deixamos que o EasyMock faa isso por ns.

No precisaremos criar um arquivo para nosso mock.

EasyMock

O EasyMock pode ser obtido em:

easymock.org

Basta extrair do download a biblioteca easymock.jar e coloc-la no classpath de seu projeto.

Passo a passo usando EasyMock

1 Passo)

Solicitamos a criao de um mock para um interface particular


HttpServletRequest requestMock = createMock(HttpServletRequest.class);

2 Passo)

Criamos comportamentos especficos

O mock objeto request ir esperar que alguma outra classe acesse o seu mtodo getParameter()
expect(requestMock.getParameter(login)). andReturn(Marilia); expect(requestMock.getParameter(senha)). andReturn(cefet);

Passo a passo usando EasyMock

3 Passo)

Precisamos informar ao mock que ele j no est mais sendo preparado, ou seja, hora da ao. Para isso usamos o mtodo replay(); A partir deste ponto o mock pode ser usado normalmente onde antes teria sido necessrio utilizar um objeto real da aplicao.

replay(requestMock); LoginServlet loginServlet = new LoginServlet(); assertTrue(loginServlet.loginValido(requestMock ());

Passo a passo usando EasyMock

Observaes:

Os mtodos usados para programar mock ficam disponveis para a classe de testes atravs de um import esttico dos mtodos da classe EasyMock. necessrio usarmos java 5 ou superior

import static org.easymock.EasyMock.*;

Passo a passo usando EasyMock


import import import import import import java.io.IOException; javax.servlet.ServletException; javax.servlet.ServletOutputStream; javax.servlet.http.HttpServlet; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletOutputStream out = response.getOutputStream(); if(loginValido(request)) { out.println("Bem-vindo"); } else { out.println("Acesso negado"); } } public boolean loginValido(HttpServletRequest request) { if("Marilia".equals(request.getParameter("login")) && "cefet".equals(request.getParameter("senha"))) { return true; } return false; } }

Passo a passo usando EasyMock


import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; import static org.easymock.EasyMock.*; public class LoginTeste extends TestCase { public void testeLoginComSucesso(){ HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getParameter("login")).andReturn("Marilia"); expect(requestMock.getParameter("senha")).andReturn("cfet"); replay(requestMock); LoginServlet loginServlet = new LoginServlet(); assertTrue(loginServlet.loginValido(requestMock));

} }

Para maiores informaes

Junit:

http://junit.sourceforge.net/ http://www.easymock.org/EasyMock2_2_Docum entation.html

EasyMock

Você também pode gostar