Testes unitários em Java com JUnit

Esta não é de minha autoria, mas como de costume, coloco este excelente artigo aqui no meu blog, para que mais pessoas tenham acesso. ;D
Autor: Josiel <josiel_lkp at yahoo.com.br>
Data: 18/10/2011

Introdução



Geralmente, nós desenvolvedores deixamos para testar nossos softwares após o término de sua codificação. Isso porque testar é chato, porém necessário. Essa não é uma prática muito recomendável, pois se os testes forem feitos durante o desenvolvimento da aplicação muito menos bugs seriam encontrados nos softwares.

Neste artigo vou apresentar uma modalidade de testes muito interessante, o teste unitário, ou teste por unidade e ensinarei como implementar essa modalidade na linguagem Java com a ajuda do poderoso framework JUnit.

O que é teste unitário?

Teste unitário é aquele que testa separadamente a menor parte de um software, como por exemplo o método de uma classe. Você fornece a resposta certa e ele verifica se o retorno do método é igual a resposta fornecida.

É útil para testar o software pouco a pouco, e ter certeza de que todos os métodos / funcionalidades funcionam a contento.

JUnit

JUnit é um framework open source que possibilita a criação de testes unitários em Java.

O JUnit possibilita a criação das classes de testes. Estas classes contém um ou mais métodos para que sejam realizados os testes, podendo ser organizados de forma hierárquica, de forma que o sistema seja testado em partes separadas, algumas integradas ou até mesmo todas de uma só vez.

Além disso, este framework tem como objetivo facilitar a criação de casos de teste, além de permitir escrever testes que retenham seu valor ao longo do tempo, ou seja, que possam ser reutilizáveis.

Para instalar o JUnit, primeiramente faça o download em seu site oficial:
Após ter baixado o framework, copie o arquivo .jar para o CLASSPATH, caminho que o seu compilador Java procura pelas classes. Depois disso, é só usar.

Convenções

É recomendado que os testes sejam separados do software, geralmente eles ficam numa pasta chamada "tests", veja o exemplo:
  • /matematica -> aqui vão os arquivos do software;
  • /matematica/tests -> aqui vão os testes.

É recomendado também que todas as classes de teste tenham o sufixo "Test" e os métodos a serem testados devem ter o nome prefixado com "test":

Classe: Matematica;
Métodos da classe Matematica: add, subtract, multiply, divide;

Classe: MatematicaTest;
Métodos da classe MatematicaTest: testadd, testsubtract, testmultiply, testdivide.


Colocando a mão na massa - classe exemplo, classe de teste

Agora vamos para a parte interessante. Criei uma classe aqui que não faz nada de legal, é a classe Matematica. Ela não faz nada de muito complicado, recebe dois números inteiros em seu construtor e possui métodos para somar, subtrair, multiplicar e dividir os números.

Não há nada de misterioso em sua implementação, veja o código:

Matematica.java:
public class Matematica
{
private int n1;
private int n2;

public Matematica(int n1, int n2)
{
this.n1=n1;
this.n2=n2;
}

public int add()
{
return this.n1+this.n2;
}

public int subtract()
{
return this.n1-this.n2;
}

public int multiply()
{
return this.n1*this.n2;
}

public int divide()
{
return this.n1/this.n2;
}
}

Não me preocupei com DivisionByZero, pois essa classe é apenas para fins didáticos. Como pode perceber, não tem nada de interessante nessa classe. Ela recebe dois números, e os métodos verificam se os operadores cumprem com o que prometem. :)

Testando a classe Matematica

Agora vamos testar a classe Matematica. Antes de ver código, vamos a algumas regrinhas básicas:
  • Todas as classes de teste devem herdar de junit.framework.TestCase;
  • Todos os métodos a serem testados devem ter o prefixo "test".

Agora vamos ver o código, depois as explicações:

MatematicaTest.java:
import junit.framework.TestCase;

public class MatematicaTest extends TestCase
{
private Matematica math=new Matematica(4, 2);

public void testadd()
{
this.assertTrue(this.math.add()==6);
}

public void testsubtract()
{
this.assertTrue(this.math.subtract()==2);
}

public void testmultiply()
{
this.assertTrue(this.math.multiply()==8);
}

public void testdivide()
{
this.assertTrue(this.math.divide()==2);
}

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

Vamos por partes:

A classe MatematicaTest herda de junit.framework.TestCase, isso é obrigatório. A propriedade "math" é a instância da classe Matematica, criei-a para não ter que criar uma nova instância em todos os métodos de teste.

No método main, invocamos o programa TestRunner, que é um programinha de linha de comando. Fiz a invocação pelo método main, pois pela linha de comando ele não funcionou comigo. :(

Em todos os métodos "testX" temos uma chamada ao método "assertTrue" da classe junit.framework.Assert, ele é útil para avaliar se uma condição é verdadeira.

Pode-se especificar uma mensagem de erro que será exibida caso a condição seja falsa. Esta mensagem pode ser especificada no primeiro parâmetro do método, pois ele é sobrecarregado.

Depois da edição do programa acima, basta compilar e executar:

$ javac Matematica.java MatematicaTest.java
$ java MatematicaTest

....
Time: 0,002

OK (4 tests)


Outros métodos além do assertTrue

A classe junit.framework.Assert provê outros métodos além do AssertTrue. Todos são sobrecarregados para especificar uma mensagem no primeiro parâmetro, caso queira.

Veja-os:
  • assertEquals(Object expected, Object actual): Verifica se "expected" é igual a "actual". Ele também é sobrecarregado para algumas classes e tipos nativos, como a classe String e o tipo double;
  • assertFalse(boolean condition): Verifica se "condition" é falsa;
  • assertTrue(boolean condition): Verifica se "condition" é verdadeira;
  • assertNotNull(Object object): Verifica se "object" não é nulo. Ele é um atalho para "assertTrue(object!=null);";
  • assertNull(Object object): Verifica se "object" é nulo;
  • assertSame(Object expected, Object actual): Verifica se "expected" referencia a "actual". Note que este método verifica as referências, não os objetos propriamente ditos;
  • assertNotSame(Object expected, Object actual): Verifica se "expected" não referencia a "actual". Este método também compara as referências, não os objetos propriamente ditos.

Com todos esses métodos você pode verificar o que quiser, que eles disparam uma exceção, com uma mensagem formatada caso não ocorra como você espera.

Métodos da classe junit.framework.TestCase que podem ser sobrecarregados

A classe junit.framework.TestCase provê alguns métodos que podem ser sobrecarregados:
  • setUp: executa algum código antes dos testes;
  • tearDown: executa algum código depois dos testes.

Os métodos apresentados acima podem ser úteis para fazer algo antes dos testes serem iniciados / terminados. Por exemplo, o método setUp pode iniciar uma conexão com a internet, enquanto o método tearDown pode ser usado para fechar a conexão com a internet. Esses métodos são protected, não retornam nada e não fazem nada por padrão.

Sobrecarregando o método setUp

O método setUp pode ser sobrecarregado para fazer algo antes dos testes serem iniciados. Por exemplo, podemos separar a inicialização do objeto math de sua declaração.

Antes:

private Matematica math=new Matematica(4, 2);

Depois:

private Matematica math;

@Override protected void setUp()
{
this.math=new Matematica(4, 2);
}

Pode testar, o teste funcionará da mesma forma que o primeiro.

Eu, particularmente, acho essa maneira mais interessante, o código fica mais bonito na minha opinião.

Bom, é isso.

Espero que este artigo possa ajudar muita gente que deseja fazer testes unitários, e que ele possa ser útil para alguém.



Original em:
vivaolinux.com.br: Testes unitarios em Java com JUnit

Comentários

Anônimo disse…
Overloading é diferente de Override, no caso de setUp(). ;)