16 maio 2016
Agil com TDD

TDD: Na prática

Introdução

O TDD (Test Driven Design) é uma boa prática que podemos utilizar para desenvolver um aplicativo, pois esta técnica que tem como premissa desenvolver o teste primeiro e depois a classe que implementará o algoritmo.

Para utilizar o TDD é necessário seguir o ciclo de vida RED, GREEN e REFACTOR.

Segue abaixo os passos:

  • Escrever o teste primeiro;
  • Escrever o algoritmo;
  • Testar o algoritmo até passar;
  • Refatorar o código.

Utilizando esses passos podemos usar as boas práticas de desenvolvimento de software, garantindo que o algoritmo esteja funcionando corretamente sem se preocupar com todas as funcionalidades. Outro ponto positivo é que o código será escrito de forma simples para atender o problema, evitando escrever códigos desnecessários. A prática também permite um feedback rápido dos testes executados após serem escritos, caso ocorra um erro, o ajuste é realizado imediatamente.

A ilustração abaixo demonstra a visão de feedback rápido:

Feedback do Teste

Feedback do Teste

Esta prática também permite documentar o sistema e aumentar a curva de aprendizagem do software desenvolvido.

Hora da Ação

Agora vamos fazer um teste utilizando o TDD na prática, para isso utilizaremos a linguagem o Java e framework de teste unitário Junit.

Para nossa ilustração utilizaremos como exemplo uma classe para converter um número arábico em número romano (neste artigo será utilizado o IDE Eclipse).

O primeiro passo será criar um teste com Junit :

public class ConverteNumeroRomanoTest {

    @Test
    public void deveraConverterNumeroRomanoEmArabico() {
         fail(“Not yet implementes”);
    }
}

Veja que neste passo há o método fail, esse método será usado propositalmente para realizar o primeiro passo do ciclo de vida o RED, neste caso o teste falha.

Abaixo segue a imagem para executar o teste.

Ação para executar o Teste

Ação para executar o Teste

Ao executar o teste a IDE exibirá a view do Junit com o seguinte resultado:

Feedeback do Junit

Feedeback do Junit

Agora o próximo passo é fazer o teste passar, para isso devemos escrever o nome da classe no teste (O Eclipse não irá reconhecer a classe por que não existe, então será necessário criar a classe para o erro desaparecer).

public class ConverteNumeroRomanoTest {

    @Test
    public void deveraConverterNumeroRomanoEmArabico() {
         String valor = “”;

         ConverterNumeroRomano converter = new ConverterNumeroRomano(“MCMXCIX”);

         fail(“Not yet implemented”);
    }
}

O próximo passo será criar uma classe e começar a desenvolver algoritmo. Neste passo o método retornará 0, pois será realizada a implementação da classe até chegar ao estágio GREEN.

public class ConverterNumeroRomano {

    private String valor = “”;

    public ConverterNumeroRomano(String valor) {
        this.valor = valor;
    }

    public int converterNumero() {
        return 0;
    }
} 

Agora na classe do teste acrescente o método assertEquals, dentro do método converterNumero para retornar o resultado esperado.

public class ConverteNumeroRomanoTest {

    @Test
    public void deveraConverterNumeroRomanoEmArabico() {
         String valor = “”;

         ConverterNumeroRomano converter = new ConverterNumeroRomano(“MCMXCIX”);
         int result = converter.converterNumero();

         assertEquals(1999, result);
    }
}

Neste momento o teste foi executado novamente. Veja o resultado do teste abaixo:

Feedeback do Junit

Feedeback do Junit

O código ainda não retornou um resultado satisfatório, pois o resultado esperado era 1999 e não zero, para este teste passar fiz o seguinte algoritmo:

public class ConverterNumeroRomano {

    private String valor = “”;

    public ConverterNumeroRomano(String valor) {
        this.valor = valor;
    }

    enum NumeroRomano {
        I(1), V(5), X(10), L(50), C(100), D(500), M(1000);

        public int numero;

        NumeroRomano(int numero) {
            this.numero = numero;
        }

        public int getNumero() {
            return numero;
        }
    }

    static Map mapDeParaRomanoArabico;

    static {
        mapDeParaRomanoArabico = new HashMap();

        NumeroRomano[] numerosRomanos = NumeroRomano.values();

        for (NumeroRomano numeroRomano : numerosRomanos) {
          mapDeParaRomanoArabico.put(numeroRomano.toString().charAt(0), numeroRomano.getNumero());
        }
    }

    public int converterNumero() {

        char[] sequenciaCaracteres = valor.toCharArray();
        int index = sequenciaCaracteres.length – 1;

        Integer numero = 0;

        do {
           int valorAtual = mapDeParaRomanoArabico.get(sequenciaCaracteres[index]);
           int valorProximo = mapDeParaRomanoArabico.get(sequenciaCaracteres[index == 0 ? 0 : index – 1]);

          if (valorAtual > valorProximo) {
              numero = numero.sum(numero, valorAtual – valorProximo);
              index = index – 2;
          } else {
              numero = numero.sum(numero, valorAtual);
              index–;
          }
    } while (index >= 0);
        return numero;
    }
}

Veja que a classe realmente está uma bagunça, mas calma, pois o objetivo é fazer o teste passar, veja que elementos static e enum estão dentro da classe e isso pode gerar uma confusão se deixarmos assim, por isso faremos uma refatoração depois que o teste passou do ciclo GREEN.

Agora ao executar o código acima veja o resultado.
imag5

Esta é a melhor parte, pois o teste foi satisfatório, mesmo assim o código não está pronto.

Para isso será necessário ir para próximo estágio do ciclo o REFACTOR. Abaixo o segue o código refatorado:

public class ConverterNumeroRomano {

    private String valor = “”;

    public ConverterNumeroRomano(String valor) {
        this.valor = valor;
    }

    public int converterNumero() {

        char[] sequenciaCaracteres = valor.toCharArray();

        // começara a percorrer do último caracter áte a posição inicial (0)
        int index = sequenciaCaracteres.length – 1;

        Integer numero = 0;

        do {
           int valorAtual = MapaValores.getMapa().get(sequenciaCaracteres[index]);
           int valorProximo = MapaValores.getMapa().get(sequenciaCaracteres[index == 0 ? 0 : index – 1]);

           if (valorAtual > valorProximo) {
              numero = numero.sum(numero, valorAtual – valorProximo);
              index = index – 2;
          } else {
             numero = numero.sum(numero, valorAtual);
             index–;
          }
       } while (index >= 0);

       return numero;
    }
}

Neste caso refatorei a classe e executei o teste novamente.
imag5

Caso precisar-se criar outro teste, este ciclo RED, GREEN, REFACTOR deverá ser realizado novamente.

Conclusão

O objetivo deste artigo foi ilustrar o passo a passo na prática o ciclo de vida do TDD. Espero que este artigo ajude no dia a dia e traga resultados satisfatórios na qualidade do desenvolvimento do software.
O código está disponível no github.

https://github.com/ander-f-silva/projects-java.git

Baixar or projeto: PROJETO TDD

CTA-ebook-transformação-digital

Comments

  • Camila Ferreira
    maio 16, 2016 Responder

    Tive a conclusão que o TDD é um ótimo projeto para a elaboração de um aplicativo.
    Um texto muito bem explicativo, que facilita o entendimento de todos os leitores, eu que sou leiga ainda do assunto consegui compreender perfeitamente.
    Parabéns pelo trabalho!!

Leave a Comment