Padrão de Desenvolvimento - Testes Unitários
Índice
Como escrever um bom teste unitário
Princípio Básico: Sempre utilizar Test Driven Development (TDD) para criação de novos códigos
Caso você já tenha conhecimento do TDD, isso já é 80% do caminho para que seu teste seja bem escrito. Mas para que o princípio do TDD seja complementado e então os testes sejam melhores organizados e menos propensos a falhas é recomendável seguir os três princípios abaixo:
- Crie o cenário, popule o(s) objeto(s) a serem utilizados no seu teste
- Execute a unidade a ser testada
- Verifique se o teste é aprovado através dos asserts
Tendo em mente os princípios citados acima vemos no código abaixo um exemplo de código que os demonstra:
class Avaliador {
private double maiorDeTodos = Double.NEGATIVE_INFINITY;
private double menorDeTodos = Double.POSITIVE_INFINITY;
public void avalia(Leilao leilao) {
for(Lance lance : leilao.getLances()) {
if(lance.getValor() > maiorDeTodos) {
maiorDeTodos = lance.getValor();
}
else if(lance.getValor() < menorDeTodos) {
menorDeTodos = lance.getValor();
}
}
}
public double getMaiorLance() { return maiorDeTodos; }
public double getMenorLance() { return menorDeTodos; }
}
|
import org.junit.Assert;
class AvaliadorTest {
@Test
public void deveEntenderLancesEmOrdemCrescente() {
//1 - populando o objeto
Usuario joao = new Usuario("Joao");
Usuario jose = new Usuario("José");
Usuario maria = new Usuario("Maria");
Leilao leilao = new Leilao("Playstation 3 Novo");
leilao.propoe(new Lance(maria,250.0));
leilao.propoe(new Lance(joao,300.0));
leilao.propoe(new Lance(jose,400.0));
//2 - Executando a unidade a ser testada
Avaliador leiloeiro = new Avaliador();
leiloeiro.avalia(leilao);
double maiorEsperado = 400;
double menorEsperado = 250;
//3 - Verificando se o teste é aprovado através dos asserts
Assert.assertEquals(maiorEsperado, leiloeiro.getMaiorLance(), 0.0001);
Assert.assertEquals(menorEsperado, leiloeiro.getMenorLance(), 0.0001);
}
}
|
Nomenclatura e localização da classe de teste
Nome das classes
Toda classe de teste deve ter a como nome o mesmo nome que foi utilizado na classe origem seguido do sufixo "Test". Desta forma temos o seguinte exemplo:
Classe de Origem: DoadorDao
Classe de Teste: DoadorDaoTest
Nome do método
O nome do teste sempre deve ter a ver exatamente com o que é testado dentro dele de forma que quem o ler saiba exatamente o que está sendo verificado, sem a necessidade de entender o que foi codificado no teste. Veja o exemplo:
Método de origem: salva()
Método de teste: salvaNomeNulo()
Atenção: Verifique todas as possibilidades, não somente o "Caminho Feliz =D"
No exemplo anterior utilizamos uma classe de leilão. Dentro desta classe é possível verificar que os objetos de Usuário e Leilão são populados e posteriormente testados, mas não há nenhum tipo de previsão no código para caso haja algum tipo de excessão ou erro. Ou seja, caso o valor do lance seja nullo ou menor que zero nosso sistema gerará uma excessão. Desta forma torna-se necessário realizar testes para todos os caminhos possíveis em nosso código antes de então ele ser dado como testado. Verifique no exemplo com um teste mais abrangente:
import org.junit.Assert;
class AvaliadorTest {
@Test
public void deveEntenderLancesEmOrdemCrescente() {
//1 - populando o objeto
Usuario joao = new Usuario("Joao");
Usuario jose = new Usuario("José");
Usuario maria = new Usuario("Maria");
Leilao leilao = new Leilao("Playstation 3 Novo");
leilao.propoe(new Lance(maria,250.0));
leilao.propoe(new Lance(joao,300.0));
leilao.propoe(new Lance(jose,400.0));
//verificação do caminho infeliz =\
Assert.assertNotNull(leilao.getPropostas());
//2 - Executando a unidade a ser testada
Avaliador leiloeiro = new Avaliador();
leiloeiro.avalia(leilao);
double maiorEsperado = 400;
double menorEsperado = 250;
//3 - Verificando se o teste é aprovado através dos asserts
Assert.assertEquals(maiorEsperado, leiloeiro.getMaiorLance(), 0.0001);
Assert.assertEquals(menorEsperado, leiloeiro.getMenorLance(), 0.0001);
}
}
|
Utilização da classe Assert
A classe assert tem todos os métodos necessários para realizar os testes do projeto, desta forma evite fazer comparações boleanas utilizando o método assert. Exemplo de má utilização:
Assert.assertTrue(leilao.getPropostas() != null);
Material Complementar
- Test-driven development,IBM Cloud Garage Method, 2017.
- Escreva Testes Melhores em 5 Passos, ThoughWorks, 2014.