TDD + Ruby: Número de Fibonacci

June 15, 2009 at 3:34 am | In Ruby/Rails | Leave a Comment

Estou necessitado de escrever posts melhores, eu sei, mas enquanto isso, tava brincando aqui com TDD + Ruby, então resolvi fazer um código para gerar a sequencia de Fibonacci fazendo o uso de TDD.

Para quem ainda não sabe, o numero de fibonacci e uma sequencia de numero, que é gerada começando com 1 e em seguida somando os dois anteriores para se conhecer o próximo, na prática:

Começamos com 1, então o proximo numero será : 0 + 1 = 1, o seguinte será 1 + 1 = 2 … 2 +1 = 3 … e assim vai… essa sequencia é defenida como sendo recursiva, a formula é:

0d5cce25d67941bb4661afd52609d93c

Bom, o problema ta entendido(eu acho) rs.

Como vamos fazer o uso de TDD, vamos começar escrevendo nossos testes

Precisamos ter um método chamdo por exemplo fibo, esse método deve receber como argumento um inteiro, inicialmente se passarmos 0(zero) devemos ter como retorno 0(zero), entõa vamos criar o esqueleto do teste:


require "test/unit"

require "fibonacci.rb"

class Test < Test::Unit::TestCase
   def test_case_name

   end
end

Acima está o esquelete de um teste básico, na primeira linha fizemos a inclusão do framework de teste, no segundo require chamamos a nossa classe fibonacci(que ainda nao existe), e logo em seguida temos o primeiro método para teste, vamos mudar o nome dele e acresentar o comportamento que nossa classe fibonacci deve ter quando receber zero.

require "test/unit"
require "fibonacci.rb"
class TestFibonacci < Test::Unit::TestCase
	def test_fiboZero
		assert_equal(0, Fibonacci.seqfibo(0))
	end
end

Todo teste deve iniciar com o palavra test, logo em seguida vem nosso teste propriamente dito, é justamente o que falamos acima, se receber Zero, retorne Zero, vamos rodar nosso teste para ver o que acontece:

LoadError: no such file to load  fibonacci.rb

Ops, certamente teriamos um erro ai mesmo, pois ainda nao criamos nossa classe fibonacci, vamos cria-la,(sem nehum codigo ainda) e rodar novamente:

Ops, denov, so temos um arquivo e mais nada então recebemos o seguinte:


Started
E
Finished in 0.002 seconds.

1) Error:
test_fiboZero(TestFibonacci):
NameError: uninitialized constant TestFibonacci::Fibonacci
C:\Documents and Settings\casa\Desktop\Nova pasta\fibonacciTest:5:in `test_fiboZero’

1 tests, 0 assertions, 0 failures, 1 errors

Vamos criar essa classe, acresente o seguinte em fibonacci.rb:


class Fibonacci
    def self.seqfibo(num)
       return 0 if num == 0
    end
end

Bom, isso provavelmente irá fazer nosso teste passar, rodando recebemos o seguinte:

Started
.
Finished in 0.002 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Legal, tudo passou, nosso primeiro caso esta feito, agora, podemos pensar em outro comportamento para nossa classe. . . .bom testamos com zero agora vamos tentar passar um(1) para o método e ver o que acontece, incluindo mais método para teste (poderia ser feito no mesmo método, mas vou separar aqui), nosso código de teste agora fica assim:


require "test/unit"
require "fibonacci.rb"
class TestFibonacci < Test::Unit::TestCase
    def test_fiboZero
       assert_equal(0, Fibonacci.seqfibo(0))
    end
    def test_fiboUm
       assert_equal(1, Fibonacci.seqfibo(1))
    end
end

a lógica dos teste aqui, nao mudou nada, vamos rodar para ver:

Started
F.
Finished in 0.033 seconds.

1) Failure:
test_fiboUm(TestFibonacci) [C:\Documents and Settings\casa\Desktop\Nova pasta\fibonacciTest:8]:
<1> expected but was
<nil>.

2 tests, 2 assertions, 1 failures, 0 errors

Bom, vimos ali que o teste esperava 1 mas retornou nil, vamos implementar essa lógica na nossa classe, agora temos isso:


class Fibonacci
    def self.seqfibo(num)
       return 0 if num == 0
      return 1 if num == 1
    end
end

Exatamente igua ao anterior, agora não seria nada bom ficar acresentando todos essas asserts ai para testar cada um dos numero que esperamos obter,  para isso em nosso teste vamos criar um array de arrays contendo vários cassos de testes algo do tipo:

testes = [[0,0][1,1][2,1] . . .]

e logo interar por esse array passando esses valores para nosso teste, logo iremos ter um unico método, nossa classe teste fica +  – assim agora:


require "test/unit"
require "fibonacci.rb"
class TestFibonacci < Test::Unit::TestCase
    def test_fiboZero
       teste = [[0,0],[1,1],[2,2],[4,5],[3,2]]
       teste.each do |t|
          assert_equal(t[1], Fibonacci.seqfibo(t[0]))            
       end
    end
end

Bom, creie um array de array com alguns cassos, agora so falta implementar na classe fibonacci um funcao recursiva para fazer o calculo, então agora tempo:


class Fibonacci
     def self.seqfibo(num)
        return num unless num > 2
       seqfibo(num-1) + seqfibo(num-2)
   end

 #um metodo pra executar

   def execute
       for i in 1..10
          puts seqfibo(i)
       end 
  end
end

Agora rodamos o código de teste e recebemos:


Started
.
Finished in 0.002 seconds.

1 tests, 5 assertions, 0 failures, 0 errors

Bom, aqui acabamos nossa implementação, obviamente da para melhorar e fazer muitos outros teste, e melhorar o teste, e tudo mais, se alguem achar erros, ou quizer falar algo, porfavor deixe um comentário.

No Comments Yet »

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.