Posted by andrefaria on Jul 12, 2008 in Agile, Software | 3 comments
O contato com Scrum, XP e Agile em geral, me levaram à diversos conceitos que até então desconhecia, um dos quais resolvi me aprofundar foi TDD (Test Driven Devolpment), para isso li o livro ”Test-Driven Development by Example” escrito por Kent Beck. O Livro é muito esclarecedor e divertido de ler, apresenta diversos conceitos e técnicas através de exemplos de implementações de pequenas soluções.
TDD ou Desenvolvimento Dirigido por Testes, é uma técnica de desenvolvimento de software que consiste em pequenas iterações onde testes são escritos primeiro e o código produzido é somente o necessário para fazer o teste passar, e finalmente o código é refatorado para acomodar as mudanças. TDD proporciona feedback rápido depois de cada mudança. Não é considerado somente uma ténica de escrita de testes, mas uma técnica para design de software.
TDD pode ser facilmente explicado em cinco simples passos:
Para melhor entender este ciclo de cinco fases, vamos constuir um pequeno programa Java para realizar um simples cálculo de potência. Para executar os testes precisamos de uma ferramenta de testes unitários, utilizaremos o JUnit.
O JUnit possui uma classes chamada TestCase, a qual nossa classe de teste deverá extender. Essa classe possui uma série de métodos que nos auxiliarão no processo de testes unitários, tais métodos fazem o teste falhar caso determinadas condições não sejam satisfeitas.
Ex: O método “AssertEquals(x,y)“ faz o teste falhar caso x seja direferente de y.
assertEquals(“TDD”,”DDD”); //Falha assertEquals(100, 100); //Passa
Começaremos então pelo teste:
public class CalculadoraTest extends TestCase { public void testCalcularOitoAoQuadrado(){ Calculadora calculadora = new Calculadora(); assertEquals(calculadora.calcularPotencia(8, 2), new BigDecimal(“64”)); } }
Se tentarmos executar nosso teste, o JUnit nos apresentará uma barra vemelha o que signfica que o teste falhou, e falhou porque a classe Calculadora e o método estático calcularPotencia ainda não existem. Vamos então criar a classe e o método para fazer o teste ao menos compilar.
public class Calculadora { public void calcularPotencia(Integer a, Integer b){ return null; } }
Nossa missão agora é fazer, rapidamente, o teste passar. Para isso vamos então retornar o valor que nosso primeiro teste espera, 64.
public class Calculadora { public void calcularPotencia(Integer a, Integer b){ return new BigDecimal(“64”); } }
Se executarmos o teste novamente o mesmo passará… Eu seu, eu sei, que isso pode parecer meio estranho no inicio, mas não se assuste, você se acostumará e entenderá melhor o que está por traz disso tudo com o tempo. Vamos adicionar mais um método de teste em nossas classe de testes
public void testCalcularDoisAoCubo(){ Calculadora calculadora = new Calculadora(); assertEquals(calculadora.calcularPotencia(2, 3), new BigDecimal(“8”)); }
E vamos fazer a alteração mais simples possível para fazer o teste passar:
public class Calculadora { public void calcularPotencia(Integer a, Integer b){ if (b == 2) return new BigDecimal(“64”); else return new BigDecimal("8"); } }
Agora que os dois testes estam passando, realizaremos o processo de refatoração para remover as constantes e a redundancia do código, assegurando que o teste continue passando.
public void calcularPotencia(Integer a, Integer b){ BigDecimal result = new BigDecimal(a); for (int I = 0; I < b; I++) { result = result.multipliedBy(BigDecimal.valueOf(a)); } return result; }
Pronto! Refatoramos nosso código removendo as constantes e se executarmos nossos testes verificaremos que este será bem sucedido! Este é o processo básico de TDD.
Ops!!! O que acontecerá se tentarmos executar o método executar uma potencia de um número elevado a zero? Problemas!!! Todo o número elevado a Zero é igual a 1 (Um), dessa forma devemos adicionar um novo teste que verifique se um número elevado a zero retorna 1, fazer o teste passar, refatorar e assegurar de que os outros testes continuem passando.
public void calcularPotencia(Integer a, Integer b){ if (b.equals(0)){ return BigDecimal.valueOf(1); } BigDecimal result = new BigDecimal(a); for (int I = 0; I < b; I++) { result = result.multipliedBy(BigDecimal.valueOf(a)); } return result; }
public void testTodoNumeroElevadoAZeroDeveRetornarUm(){ Calculadora calculadora = new Calculadora(); assertEquals(calculadora.calcularPortencia(21, 0), new BigDecimal(“1”)); assertEquals(calculadora.calcularPortencia(8, 0), new BigDecimal(“1”)); }
É isso pessoal! Parece simples, mas não é fácil. Depois muito treinamento e prática em diferentes cenários isso começa a ficar mais natural e você passa a enxergar mais claramente os benefício desta poderosa técnica. Estou a disposição para esclarecimento de dúvidas. Comentários são sempre muito bem vindos.
Pingback: Bluesoft Labs: Clean Code por Bruno Lui « Blog da Bluesoft
Pingback: Bluesoft Labs: Clean Code por Bruno Lui « Blog da Bluesoft