Web,ruby, Ajax ou qualquer outra coisa que me venha a cabeça (com prioridade para esta última)

02 março, 2007

TDD vs BDD - Parte I

Em dezembro escrevi aqui um pequeno artigo sobre BDD - Desenvolvimento Orientado pelo comportamento e TDD - Desenvolvimento Orientado pelo Teste para melhor ilustrar a diferença hoje apresento um exemplo básico de desenvolvimento em TDD.

Os passos a seguir são:

  1. Escrever o teste
  2. Escrever a lógica
  3. Fazer a lógica passar o teste
  4. Refactorizar
  5. A cada refactorização verificar que o teste continua a ser passado
  1. Vamos pois passar ao primeiro passo escrever o teste mais simples possível. Em TDD em ruby a primeira coisa que há a fazer é criar um programa que comece por requisitar os testes unitários:

    
    require 'test/unit'
    

    Para exemplificar iremos criar um Exemplo e portanto iremos criar um teste designado por ExemploTeste:

    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def test_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
    end
    

    Corra o programa e veja o que sucede surge um relatório com o número de presunções, falhas e erros com um erro (1 presunção, 0 falhas e 1 erro).

  2. Passemos pois ao passo número 2.

    Criar a classe a testar:

    
    class Exemplo
       def initialize
       end
    end
    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def test_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
    end
    

    Se agora corrermos o teste iremos ver que não temos erros. Passámos o teste.

    Se o programa só fizesse isto não servia para nada, por isso, imaginemos que quando um Exemplo é gerado o mesmo gera uma variável com uma string vazia. Ao teste existente acrescentamos um método:

    
    class Exemplo
       def initialize
       end
    end
    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def test_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
      def teste_exe
        ex = Exemplo.new
        assert_equal("",ex.exe)
      end
    end
    
  3. Agora corremos novamente o programa teste e vemos que obtemos um erro, pois não existe variável exe na classe a testar. A nossa próxima acção é tratar de a incluir da forma mais simples para passar este teste.

    
    class Exemplo
       attr_reader :exe
       def initialize
       end
    end
    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def testar_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
      def testar_exe
        ex = Exemplo.new
        assert_equal("",ex.exe)
      end
    end
    

    Executando novamente o programa vemos que ele passa sem erros mas falha! Porque falta a atribuição inicial de valor a exe. Então tratemos disso

    
    class Exemplo
       attr_reader :exe
       def initialize
         # a arroba denota que é uma variável de instância
         @exe = ""
       end
    end
    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def testar_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
      def testar_exe
        ex = Exemplo.new
        assert_equal("",ex.exe)
      end
    end
    

    Agora se correr o programa este passa sem erros nem falhas. O programa evoluíu um pouco. Mas se uma variável não pudesse mudar de valor de pouco servia, vamos pois tentar criar um teste para a mudança do seu valor.

    
    class Exemplo
       attr_reader :exe
       def initialize
         # a arroba denota que é uma variável de instância
         @exe = ""
       end
    end
    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def testar_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
      def testar_exe
        ex = Exemplo.new
        assert_equal("",ex.exe)
        ex.exe = "Olá moça!"
        assert_equal("Olá moça!",ex.exe)
      end
    end
    

    Se corrermos o programa ele terá uma falha pois não há forma de mudar o valor. Então tratemos de o fazer.

    
    class Exemplo
       attr_reader :exe
       attr_writer :exe
       def initialize
         # a arroba denota que é uma variável de instância
         @exe = ""
       end
    end
    
    require 'test/unit'
    
    class ExemploTeste < Test::Unit::TestCase
      def testar_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
      def testar_exe
        ex = Exemplo.new
        assert_equal("",ex.exe)
        ex.exe = "Olá moça!"
        assert_equal("Olá moça!",ex.exe)
      end
    end
    
  4. Agora já não temos nem erros nem falhas. Passamos o teste. Então chegou o momento de refactorizarmos a nossa classe Exemplo:

    
    class Exemplo
       attr_accessor :exe
    
       def initialize
         # a arroba denota que é uma variável de instância
         @exe = ""
       end
    end
    class ExemploTeste < Test::Unit::TestCase
      def testar_initialize
        ex = Exemplo.new
        assert_not_nil(ex)
      end
      def testar_exe
        ex = Exemplo.new
        assert_equal("",ex.exe)
        ex.exe = "Olá moça!"
        assert_equal("Olá moça!",ex.exe)
      end
    end
    
  5. Voltamos a correr o teste e podemos comprovar que a nossa refactorização correu bem.

Recursos em inglês

Sem comentários: