Páginas

sábado, abril 21, 2012

Desenvolvimento orientado a testes: O inicio


Tranquilo, ágil e preciso, como um ninja

O desenvolvimento orientado por testes (Test-Driven Development) é com certeza um dos novos meios de agilizar o processo de desenvolvimento, não através de aceleração da programação, mas através da criação de testes automatizados antes mesmo da implementação e refatoração do código (Isso mesmo que você leu, antes de programar algo, você "testa" ele), trabalhando em cima da qualidade do código, de forma tranquila e ágil, como um verdadeiro ninja da programação.

Apesar de ser difícil de compreender no início, o desenvolvimento orientado a testes segue uma abordagem simples: código limpo que funciona. Ao iniciar o desenvolvimento de uma nova funcionalidade, você deve saber qual será o resultado em um determinado cenário e implementar algo que comprove que o seu código chegará ao resultado deste cenário. Um exemplo simples seria criar uma função ao receber o valor do raio de um circulo retorne o seu perímetro. 

Obs: Antes de prosseguir, vamos lembrar da fórmula usado para calcular o perímetro de um circulo, que é o seu raio multiplicado por dois multiplicado por PI (2 * raio * PI). Vamos considerar PI = 3,1415.

Então, pensando "ao contrário", criamos o teste para um circulo com raio igual a 5 que deve retornar 31,415:

se calculaPerimetro(5) = 31,415 então
    exiba "O teste passou""
senão
    exiba "O teste não passou"

Com o teste criado, realizamos o teste e percebemos um pequeno problema, a função calculaPerimetro nem existe ainda, então como poderemos testá-la? Calma, é assim mesmo, não podemos testar algo que nem existe ainda, então criamos a implementação mais simples possível da função em questão e fazemos nosso teste:

função calculaPerimetro(numero raio)
    retorna vazio
fim da função

Agora rodamos o nosso teste (de mesa) e ele falha miseravelmente... Choro? Tristeza? Hora de afogar as mágoas em uma garrafa de café? Não, jovem padawan. A falha no teste mostra que realmente o teste funciona, afinal vazio não é igual a 31,4 em nenhum lugar desse universo. Vamos prosseguir em pequenos passos. 
Agora o que devemos fazer é forçar a passagem no teste com a implementação mais simples possível, desta forma, vamos alterar nossa função para retornar o valor esperado:

função calculaPerimetro(numero raio)
    retorna 31,415
fim da função

Que que isso? Trapaça? Sabotagem? Preguiça?
Não amigos, apenas seguimos um dos principais preceitos do desenvolvimento guiado a testes, dar passos pequenos para podermos progredir sem medo. Ao realizarmos o nosso deste ele funciona perfeitamente e agora podemos progredir para a refatoração,e ai entra um dos principais segredos do desenvolvimento orientado a testes.

Como eu já tenho um teste comprovadamente funcional e perfeito, qualquer alteração que eu fizer deve satisfaze-lo, ou seja, o que eu fizer na minha função só estará correto ao passar no teste e por isso nós temos um norte a seguir. Vamos prosseguir:

função calculaPerimetro(numero raio)
    numero PI = 3,1415
    numero dobroDoRaio
    numero perimetro
    
    dobroDoRaio = 2 * raio
    perimetro = dobroDoRaio * PI
    
    retorna perimetro
fim de função

Então vamos lá, mais uma vez rodar o nosso teste de mesa e... Rufem os tambores... Ele passa! Nosso teste continua funcionando e agora com a função implementada, podemos partir para outra fase, a refatoração. Eu sei, eu sei, você deve estar gritando ai dentro, que devemos diminuir esta função e usar menos variáveis, por isso vamos lá, altera-la novamente, cotando essa variável feiosa chamada dobroDoRaio e na sequência vamos testa-la:

função calculaPerimetro(numero raio)
    numero PI = 3,1415
    numero perimetro
    
    perimetro = 2 * raio * PI
    
    retorna perimetro
fim de função

Realizamos um novo teste, que também passa, ou seja, nossa implementação ainda é válida, mas é claro que nosso código ainda pode melhorar, simplificar mais um pouco:

função calculaPerimetro(numero raio)
    numero perimetro
    
    perimetro = 2 * raio * 3,1415
    
    retorna perimetro
fim de função

Isso ai, eliminamos mais uma variável que eu não considerava útil declarar por usarmos apenas uma vez em nosso código e o teste continua passando. Mas perai, existe uma varável ali que também só é usada uma vez... vamos nos ver agora variável "perimetro":

função calculaPerimetro(numero raio)        
    retorna 2 * raio * 3,1415
fim de função

Vamos testar e... podemos ver que realmente o teste continua funcionando e acredito que não há mais nada que possa ser feito em nossa função para aperfeiçoa-la (mas é claro, caso surja uma idéia, podemos testa-la na prática a qualquer momento, pois já temos o teste pronto). 

Cinco dragõezinhos, um de cada vez, é bem mais fácil.
Apesar de simples (e eu sei que você ficou se coçando para fazer essa implementação ou parecida com ela desde o começo), desta forma nós podemos ver como realmente funciona o desenvolvimento guiado por testes, através de passos pequenos e mudanças aparentemente simples, podemos retrabalhar um código sem ter que enfrentar um dragão de cinco cabeças que assusta até o pior vilão de um chifre só, podendo dividir o problema em partes menores e verificar o resultado das nossas alterações.

Existem diversas formas de criarmos nossos testes unitários, e não é necessário você fazer um programa só para testar. Existem diversos frameworks em praticamente todas as linguagem que facilitam a realização dos testes, além de terem ferramentas que mostram estatísticas úteis para auxiliar no desenvolvimento. 

No próximo post vou mostrar um exemplo prático baseado neste nosso pequeno problema, utilizando o JUnit, que é uma ferramenta para testes de código Java, junto com o Eclipse, então, até lá.

Nenhum comentário:

Postar um comentário

Frase

“Inovação distingue um líder de um seguidor.”
(Steve Jobs)