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...')
 
Linha 1: Linha 1:
 +
[[Padrões de Desenvolvimento|'''Voltar''']]
 +
<br/><br/>
 
== Como escrever um bom teste unitário ==
 
== Como escrever um bom teste unitário ==
 
   '''Princípio Básico:''' Sempre utilizar Test Driven Development (TDD) para criação de novos códigos
 
   '''Princípio Básico:''' Sempre utilizar Test Driven Development (TDD) para criação de novos códigos

Edição das 14h37min de 4 de maio de 2021

Voltar

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.