Técnico

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 :

[markdown]
“`
public class ConverteNumeroRomanoTest {

@Test
public void deveraConverterNumeroRomanoEmArabico() {
fail(“Not yet implementes”);
}
}
“`
[/markdown]

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).

[markdown]
“`
public class ConverteNumeroRomanoTest {

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

ConverterNumeroRomano converter = new ConverterNumeroRomano(“MCMXCIX”);

fail(“Not yet implemented”);
}
}
“`
[/markdown]

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.

[markdown]
“`
public class ConverterNumeroRomano {

private String valor = “”;

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

public int converterNumero() {
return 0;
}
}
“`
[/markdown]

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

[markdown]
“`
public class ConverteNumeroRomanoTest {

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

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

assertEquals(1999, result);
}
}
“`
[/markdown]

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:

[markdown]
“`
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;
}
}
“`
[/markdown]

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:

[markdown]
“`
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;
}
}
“`
[/markdown]

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

1 Comments

  • 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!!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Compartilhe isso: