1.3.1 Exemplo Simples

Nesta seção, apresentamos um exemplo simples do ciclo TDD ilustrado na Seção 1.3, com base na especificação da sequência de Fibonacci, utilizando por Kent Beck (2003).

Considere a especificação do problema da sequência de Fibonacci apresentada a seguir:

A sequência de Fibonacci é constituída da seguinte forma: 1 1 2 3 5 8 13 21 34 55 e assim por diante. Nela, está presente o seguinte padrão. Um mais um igual a dois. Um mais dois é igual a três. Dois mais três são iguais a cinco. E assim por diante. Ou seja, o sucessor de um número na sequência é formada pela soma dos dois números anteriores a ele.

Todo número na série Fibonacci é de aproximadamente 0,618 a 1 em termos de sua relação com o número após ele. Essa proporção nunca muda porque a proporção permanece a mesma. O interessante da sequência é que ela gera a chamada espiral perfeita, conforme ilustrado na imagem abaixo. (Fonte: https://www.ambroker.com/pt/analysis/blog/sequencia-de-fibonacci/)

Espiral Perfeita gerada pela sequência de Fibonacci

Desse modo, suponha que fossemos implementar uma classe com exemplos matemáticos e um desses exemplos fosse um método que gerasse a sequência de Fibonacci. O código completo do exemplo apresentado abaixo está disponível no GitHub no endereço https://github.com/aurimrv/fibonacci. Os arquivos foram numerados sequencialmente para facilitar a apresentação das mudanças implementadas nos testes e na aplicação em si.

Caso não queira instalar as ferramentas de desenvolvimento em seu computador, é possível acompanhar e/ou realizar a execução pelo CoLab, no link https://colab.research.google.com/drive/1BDFJ_FroYLZFxQB0hhwS1SYESIea5L-K?usp=sharing.

Primeira Rodada do Ciclo de TDD

1º Passo do Ciclo TDD - Escreva um Teste que Falhe

Ao aplicar TDD para essa construção, iniciaríamos a escrita de um caso de teste (tests01.py) que representaria uma história de usuário conforme ilustrado abaixo:

O exemplo acima, ilustra o uso de um framework de execução de testes em Python denominado UnitTest. Precisamos dele para conduzir a execução automática de nossos testes. É importante observar que ele não é o único existente para tal finalidade. Temos muitos outros disponíveis para Python. Todo conjunto de teste em UnitTest deve ter nome iniciando com "test", como "tests01.py".

Vamos destrinchar o código acima. Inicialmente, na linha 1, indicamos que iremos fazer uso do unittest. Em seguida, na linha 2, o teste indica que estamos assumindo a existência de um pacote math_samples01 que possui dentro dele uma classe denominada MathSamples. Em seguida, na linha 4, é criada uma classe, denominada FibonacciTest a qual estende a classe unittest.TestCase do framework UnitTest. Na linha 6 é criado um método que representa um caso de teste. Métodos que representam casos de teste devem ter o nome iniciado com test_ pois é desse modo que o framework identifica quais métodos ele deve executar automaticamente. Finalmente, na linha 7, o método desejado é invocado com o valor 0 (MathSamples.fibonacci(0)). Conforme a definição, por definição, o valor da sequência de Fibonacci para o valor de n=0 deveria ser 0. Assim, o método self.assertEquals do framework recebe dois parâmetros que permitem realizar uma comparação do valor obtido com a execução do método da aplicação com o valor esperado conforme a especificação.

A partir do relato acima, observa-se que o caso de teste está guiando a escrita da aplicação. Ou seja, para fazer esse teste passar, os pré-requisitos demandados devem ser implementados para que o interpretador Python não acuse erros de sintaxe por não encontrar os elementos do qual o teste depende. Assim sendo, antes de executar o teste acima, construímos o esqueleto da implementação da classe MathSamples que, conforme pode ser observado no teste, tem o método estático fibonacci que aceita um número como argumento. Essa classe poderia ser especificada conforme abaixo e salva no arquivo chamado de math_samples01.py, salva no mesmo diretório do arquivo tests01.py.

Para a execução dos testes, basta executar o comando abaixo:

Como era de se esperar, o teste falhou pois a classe em teste ainda não implementa a funcionalidade capaz de fazer o teste passar.

2º Passo do Ciclo TDD - Escreva um Código para Passar o Teste

Em seguida, para passar o teste, iremos iniciar a escrita do código funcional da aplicação de modo a fazer o teste passar. Segundo Beck (2003), devemos perder aqui a menor quantidade de tempo possível para fazer o teste passar. Haverá o momento para melhorias. Por hora, a intenção é apenas a de fazer o teste passar com o menor esforço possível. A nova versão do método fibonacci da classe MathSamples, abaixo (arquivo math_samples02.py), tem esse objetivo.

Observamos que nela, a única alteração foi a de remover o comando pass e o substituir por um return 0 (linha 4). Desse modo, ao repetir a execução do teste (arquivo tests02.py), ele irá passar, conforme apresentado a seguir.

3º Passo do Ciclo TDD - Eliminar Redundância

Como o código do método fibonacci da classe MathSamples ainda é bem simples, não há necessidade de execução do passo 3 nesse momento e, desse modo, retorna-se ao 1º passo do ciclo para a escrita de mais testes.

Segunda Rodada do Ciclo de TDD

1º Passo do Ciclo TDD - Escreva um Teste que Falhe

O próximo teste, explora o segundo número da sequência de Fibonacci. Agora, nosso arquivo de teste, nomeado de tests03.py, apresenta o conteúdo abaixo:

Ao executar os testes, o segundo (test_fib02) irá falhar, conforme ilustrado abaixo. Ou seja, fibonacci(1), conforme nossa definição, é 1 e o código atual retorna 0.

2º Passo do Ciclo TDD - Escreva um Código para Passar o Teste

Escrevendo o código que faça o teste passar, a implementação do nosso método fibonacci , fica como se segue (arquivo math_samples04.py):

E agora, ao executar os testes (arquivo tests04.py) para essa implementação, ambos os testes passam:

3º Passo do Ciclo TDD - Eliminar Redundância

Como o código do método fibonacci da classe MathSamples ainda é bem simples, não há necessidade de execução do passo 3 nesse momento e, desse modo, retorna-se ao 1º passo do ciclo para a escrita de mais testes.

Terceira Rodada do Ciclo de TDD

1º Passo do Ciclo TDD - Escreva um Teste que Falhe

O próximo teste, explora o segundo número da sequência de Fibonacci. Agora, nosso arquivo de teste, nomeado de tests05.py, apresenta o conteúdo abaixo:

Ao executar esse teste na implementação math_samples05.py obtemos o resultado abaixo, ou seja, surpreendentemente, o nosso código responde adequadamente para esse novo teste, sem que seja necessário qualquer alteração pois, fibonacci(2) é 1, conforme nossa especificação e é assim que a aplicação se comporta:

Escrevemos, então, mais um teste, agora para o quarto número da sequência, ou seja, fibonacci(3), o qual deveria ser 2 (arquivo tests06.py, abaixo):

Ao executar o teste, a aplicação não se comporta corretamente, conforme apresentado a seguir.

2º Passo do Ciclo TDD - Escreva um Código para Passar o Teste

Escrevendo o código que faça o teste passar, a implementação do nosso método fibonacci , fica como se segue (arquivo math_samples07.py):

Após a correção, ao executar o conjunto de teste (arquivo tests07.py), todos eles passam:

3º Passo do Ciclo TDD - Eliminar Redundância

Nesse momento, é possível observar o código e eliminar redundância uma vez que, ao retornar 1 + 1, têm-se que esses valores já eram retornados quando se calculou o fibonacci(2) e fibonacci(1), ambos retornavam 1.

Desse modo, o primeiro 1 do return, poderia ser substituído por uma chamada recursiva a fibonacci(n-1) (arquivo math_samples08.py).

Em seguida, o segundo 1 pode ser substituído por fibonacci(n-2), conforme código abaixo (arquivo math_samples09.py).

Após as melhorias, o conjunto de teste (arquivo tests09.py) é executado com sucesso, encerrando o ciclo TDD. Obviamente, novos testes podem ser redigidos para verificar se continua funcional.

Last updated

Was this helpful?