Mudanças entre as edições de "Padrão de Desenvolvimento - Testes Unitários"

De Redome
Ir para: navegação, pesquisa
(Criou página com '== 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 con...')
(Sem diferença)

Edição das 20h44min de 15 de dezembro de 2017

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:

  1. Crie o cenário, popule o(s) objeto(s) a serem utilizados no seu teste
  2. Execute a unidade a ser testada
  3. 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

  1. Test-driven development,IBM Cloud Garage Method, 2017.
  2. Escreva Testes Melhores em 5 Passos, ThoughWorks, 2014.