Testes de unidade com JUnit
Este artigo apresenta uma introdução à prática de testes de unidade e apresenta o JUnit como framework de testes para Java.
Autor: Diogo Castro Veloso Soares
Realizar testes de unidade é uma prática fundamental em projetos extreme programming. Em projetos baseados na linguagem Java essa prática pode ser implementada com a ajuda do JUnit, o mais popular framework de testes para Java. Escrito por Kent Beck e Martin Fowler, o JUnit faz parte da família de ferramentas de testes xUnit, que inclui implementações do framework para SmallTalk, C++ e outras linguagens. Apesar de simples, JUnit oferece um ambiente completo para a realização de testes de unidade em código Java, e ainda suporta extensões - algumas bastante populares como o Jakarta Cactus, usado em testes para na plataforma J2EE.
Por que devemos testar nosso código?
Os testes de unidade garantem que cada método testado (serviço oferecido por nossa aplicação) está produzindo o esperado. Essa garantia da uma segurança maior ao programador, que poderá mudar a implementação sem medo.
Códigos testados são mais seguros e uma das boas práticas abordadas na metodologia XP é a do TDD, que se baseia em escrever os testes antes de programarmos o código-fonte.
Testes Unitários
Antes de começarmos a parte prática, é pertinente compreendermos o conceito de testes unitários. Originalmente esse termo é definido como um teste capaz de analisar uma unidade de trabalho, que a IEEE define como: “Atividade capaz de testar unidades de hardware ou software ou grupo de unidades relacionadas”.
Certamente, estas definições estão um tanto subjetivas, então vamos a um exemplo que nos faça compreender. Vamos supor que você tenha uma classe chamada Funcionário com os métodos calcularDescontos(), calcularProventos() e calcularSalarioLiquido(), o que caracterizaria três unidades de trabalho. E vamos supor que exista um bug no método calcularSalarioLiquido(), que certamente depende dos métodos calcularDescontos() e calcularProventos().
Quando ocorre um erro, como saber de qual método está partindo o erro? Apenas fazendo um teste em cada unidade de trabalho conseguiremos detectar a raiz do problema. Uma das formas de se testar seria através do teste de aceitação, também conhecido como “executou, testou”, a outra seria o teste automatizado, que nos permite fazer várias suposições (asserts) sobre as unidades de trabalho, onerando assim menor tempo ao programador.
Dada à necessidade de automatização da tarefa de testes, um dos autores dos populares padrões de projeto “Gang of Four”, Erich Gamma, e o pai do XP, Kent Beck, usaram o conceito de testes unitários (unit tests) para Java e aproveitaram a ocasião para criar uma ferramenta, o framework JUnit, baseado no SUnit, do SmallTalk. Esta ferramenta ajuda a criar os testes de forma consistente e facilita muito a vida do desenvolvedor.
Qualquer framework de testes deve possuir as seguintes premissas básicas:
Cada unidade de teste precisa ser executada independente de todas as outras unidades de testes;
Erros precisam ser detectados e reportados, teste a teste;
Precisa ser simples a tarefa de definir cada unidade de teste a ser executada.
Instalação
Antes de iniciar, você deve fazer o download do framework JUnit no site oficial.A versão utilizada nesse artigo é a 3.8.1. Normalmente as IDEs mais utilizadas no mercado já trazem o JUnit em seus pacotes de instalação.
Testes sem JUnit
Para início de estudo dos testes unitários, vamos elaborar um estudo de caso, que será um simples aplicativo de calculadora que pode somar, subtrair, multiplicar e dividir dois números. Esta aplicação terá a organização de pastas conforme mostra a Figura 1. O IDE Netbeans 5.0 já separa os pacotes do aplicativo real (Source Packages) dos pacotes de teste (Test Packages).
Figura 1. Organização dos arquivos.
Como podemos ver no código da Listagem 1, temos no pacote junit.aplicativos a classe Calculadora, que fornece as operações matemáticas de: somar, subtrair, multiplicar e dividir.
Listagem 1. Classe Calculadora
package junit.aplicativos;
/**
*
* @autor Diogo
*/
public class Calculadora{
public double somar (double num1, double num2){
return 0.0;
}
public double subtrair (double num1, double num2){
return 0.0;
}
public double multiplicar (double num1, double num2){
return 0.0;
}
public double dividir (double num1, double num2){
return 0.0;
}
}
Agora que já temos a nossa classe de negócios, criaremos outra somente para fins de testes, conforme o código da Listagem 2.
Listagem 2. Classe de negócios
package junit.aplicativos;
/**
*
* @autor Diogo
*/
public class TestaCalculadora {
public static void main (String args[]{
Calculadora calc = new Calculadora();
double resultado = cal.somar(10,20);
if (resultado!=30){
System.out/printl("Oops! Deu um resultado não esperado: "+resultado);
}
else System.out.println("OK! Passou do teste.");
}
}
A classe TestaCalculadora possui o método PSVM (public static void main) que faz a instância da classe Calculadora, faz a chamada do método somar e atribui o resultado em uma variável. Até agora tudo bem. Lembrando que, antes de programar já devemos saber de antemão que o resultado da soma deve ser igual a 30 (já que 10 + 20 = 30).
Agora, verificaremos se o resultado da soma feita no programa será realmente igual a 30. Ao rodarmos a aplicação TestaCalculadora, teremos a mensagem que o resultado não foi o esperado. Por quê? Algo está errado no método somar. Olhando com calma, descobrimos que a fórmula está errada, pois obviamente o correto é somar o num1 com o num2 ao invés de retornar zero. Ao corrigirmos o retorno, compilar e rodar a classe de teste, a mensagem indicará que o resultado passou no teste:
public double somar(double num1, double num2){
return num1+num2;
}
Contudo, para a boa prática de programação, as falhas devem ser tratadas com o uso de exceções (blocos try-catch) ao invés das condições if...else. Porém, esta é uma tarefa muito trabalhosa, além de poluir o código com muitos blocos try-catch para cada verificação de erro. É aqui que sentimos a necessidade de uma ferramenta para diminuir esse trabalho todo. É a vez de apresentar o JUnit.
O que é o JUnit?
O JUnit nada mais é que um framework que facilita o desenvolvimento e execução de testes de unidade em código Java. Atualmente o core deste framework está dividido em sete classes e interfaces, são elas: Assert, TestResult, Test, TestListener, TestCase, TestSuite e BaseTestRunner.
Apesar de o JUnit possuir esse core, existem três classes que são a estrutura principal do framework: TestCase, TestSuite e BaseTestRunner, como mostra a Figura 2.
Figura 2.Arquitetura do JUnit.
Testes com JUnit no Netbeans 5
Explanado os principais conceitos do JUnit, agora vamos ver como funciona na prática, testando a mesma classe Calculadora utilizando os recursos do JUnit no Netbeans. Para isso devemos criar nossa classe de teste.
Para criar nossa classe de teste, na aba de Projects do Netbeans clique com o botão direito do mouse sobre a classe Calculadora, procure pelo menu Tools e depois pelo sub-menu Create JUnit Tests (Ctrl+Shift+U), de acordo com a Figura 3.
Figura 3.Criando a classe de testes.
Uma nova janela será exibida, e para nosso caso de teste específico, vamos marcar as opções de acordo com a Figura 4.
Figura 4.Opções de criação do teste.
Ao clicar no botão OK, o stub de nossa classe de teste será criado automaticamente, como demonstrado na Listagem 3.
Listagem 3.Stub da classe de testes
package junit.aplicativos;
import junit.framework.*;
/**
*
* @autor Diogo
*/
public class CalculadoraTest extends TestCase {
public CalculadoraTest (String testName) {
super(testName);
}
public static Test suite() {
testSuite suite = new TestSuite(CalculadoraTest.class);
return suite;
}
/**
* Test of somar method, of class junit.aplicativos.Calculadora.
*/
public void testSomar() {
//TODO add your test code.
}
/**
* Test of subtrair method, of class junit.aplicativos.Calculdora.
*/
public void testSubtrair() {
//TODO add your test code.
}
Vamos para o código. Vamos à implementação do método testSomar():
private Calculadora calc = new Calculadora();
/**
* Test of somar method, of class junit.aplicativos.Calculadora.
*/
public void testSomar() {
assertEquals(30, calc.somar(10,30), 0);
}
Primeiro instanciamos um objeto calc do tipo Calculadora, que irá fornecer os serviços a ser testados. Em seguida iremos utilizar o método assertEquals da classe Assert que permite fazer suposições sobre um resultado, com três parâmetros. O primeiro parâmetro passa uma suposição do resultado correto da soma, o segundo é o valor resultante da soma feita pelo programa e o terceiro permite uma técnica de range, que determina o intervalo que o valor somado deve estar dentro. Por exemplo, se o range for de 5, então será feito um intervalo resultado-range a resultado+range.
O parâmetro range normalmente é definido como 0 e raramente é usado. Ele se torna necessário quando o resultado tem cálculos de precisão numérica, como é o caso de cálculos que envolvem pontos flutuantes.
Agora que os testes foram criados e explicados, vamos executa-los no Netbeans. Para isso basta clicar com o botão direito do mouse na raiz do nosso projeto, na aba Projects e procurar pelo menu Test Project (Alt+F6), como mostra a Figura 5.
Figura 5.Executando os testes.
Ao executar os testes do nosso projeto, será exibida uma aba contendo as estatísticas sobre os testes na parte inferior do Netbeans, como demonstrado na Figura 6. Quando ocorrem erros uma marcação de FAILED é apresentada nas estatísticas do nosso projeto.
Figura 6.Relatório de testes.
Gerando relatórios de teste com JUnitReport
Por padrão, o script ant encontrado no arquivo build-impl.xml não implementa as propriedades necessárias para a geração do nosso relatório de testes. Para solucionar essa pendência, iremos aperfeiçoar nosso script, então vamos ao Netbeans. Procure pelo arquivo build-impl.xml no diretório nbproject do nosso projeto na aba Files, como na Figura 7.
Figura 7.Buscando o script ant da aplicação.
Abra o arquivo e procure pela propriedade “-init-macrodef-junit”, basta fazer uma busca no código, através do atalho Ctrl+F.
Abaixo do fechamento da tag adicione o seguinte trecho de código de acordo com a Figura 8e salve o arquivo.
Figura 8. Script para a geração de relatório de testes.
Ao rodar os testes novamente (Alt+F6) o Netbeans irá criar o relatório de testes na pasta test\html do nosso projeto. Para visualizar o relatório, clique com o botão direito do mouse sobre o arquivo index.html na pasta que contém o relatório de testes criado pelo Netbeans através da aba Files e procure pela opção View. Em seguida será carregado pelo seu navegador padrão uma página contendo um relatório detalhado sobre os testes da sua aplicação, como demonstrado na Figura 10.
Figura 10 - Relatório de testes gerado pelo JunitReport.
Conclusão
Muitas pequenas empresas se vêem reféns dos seus clientes devido a um mau planejamento estratégico ao fornecer seu software. Através de contratos mal elaborados, essas empresas acabam falindo pela gana em fornecer software cada vez mais rápido, muitas vezes atropelando um dos pilares da engenharia de software, o planejamento da manutenção.
A intenção desse artigo não é expor todos os métodos e técnicas de testes, muito menos explorar todo framework JUnit, uma vez que o assunto é vasto. O objetivo é expor algumas das funcionalidades desse framework, uma vez que se torna inviável, no contexto atual, desenvolver sem conhecer as técnicas e ferramentas voltadas para o ambiente de teste.
>Bibliografia
Site oficial dedicado à comunidade JUnit:http://www.junit.org/index.htm
Artigo da Argonavis relacionado ao JUnit:
http://www.argonavis.com.br/palestras/xpbrasil2002/index.html
Regras de testes unitários do XP:
http://www.extremeprogramming.org/rules/unittests.html
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo