Estórias Bonitas vs Testes Unitários

Após ter saído da Leosoft, dia 11 voltei lá pela primeira vez, e foi para se reunir com o pessoal e fazermos um coding dojo sobre TDD e BDD. Seguindo a idéia da url anterior, como exemplo para o evento, usamos um problema que implica em converter uma sintaxe de sql do Access para o padrão do Postgresql.

Test::Unit

Após coletar alguns exemplos de casos de sql que haviam uma mudança na sintaxe, resolvemos codificar um exemplo. Primeiro, escrevemos um exemplo clássico usando test unit do ruby.

require 'test/unit'
require 'resolver.rb'
class RegexTest < Test::Unit::TestCase
  def test_deve_converter_para_yyyy_mm_dd
    sql_access = "select DateValue('12/02/2010')"
    sql_esperado = "select '2010-02-12'"
    assert_equal resolver(sql_access), sql_esperado
  end
end

Cucumber

Quando executamos o código acima e o teste passou, então resolvemos escrever uma estória do Cucumber, para fazer uma comparação entre os frameworks de teste.

Funcionalidade: Alterar um sql de Access para Postgresql
  Como um programador preguiçoso
  Desejo criar um conversor de string
  Por que quero poupar o meu tempo
  Cenário: Uso de DateValue na consulta
  Dado a consulta "select DateValue('12/02/2010')"
  Quando eu converter
  Então não deve conter a função DateValue
  E a data com formato yyyy-mm-dd
  E a consulta como "select '2010-02-12'"

  Dado a consulta "select DateValue('12/02/2010') as data_1, 
                          DateValue('12/04/1995') as b"

  Quando eu converter
  Então não deve conter a função DateValue

Na estória acima, o exemplo é autoexplicativo, a forma como ele se descreve, permitiria que não precisasse de muitas explicações sobre qual era o objetivo do programa. Foi mais simples de entender o código, observe os seguintes passos:

require 'resolver.rb'

Dado /^a consulta "([^\"]*)"$/ do |consulta|
  @consulta = consulta
end

Quando /^eu converter$/ do
  @resolvida =  resolver(@consulta)
end

Entao /^não deve conter a função (.*)$/ do |string|
  @resolvida.should_not include(string)
end

Entao /^a data com formato  yyyy\-mm\-dd$/ do
  @resolvida.should match(/\d{4}-\d{2}-\d{2}/)
end

Entao /^a consulta como "([^\"]*)"$/ do |esperado|
  @resolvida.should == esperado 
end

Mesmo usando mais linhas para codificação dos testes, Cucumber transforma os testes em uma métodologia de teste auto-documentada.

Estou usando o Cucumber desde sua primeira versão e cada dia gosto mais de programar com ele. Usando simples passos para descrever uma tarefa, tem-se um comportamento.

Esquecendo do resultado esperado, BDD aborda o que cada linha faz, e o teste é mais responsável por o que a linha faz e não o resultado que ela retorna.

O código resolver.rb que é o código que resolve os dois testes acima, segue abaixo:

HAS_DATE_VALUE = /(.*)DateValue\(['"]([^\1]+)\1\)(.*)/
def resolver(str)
  while str =~ HAS_DATE_VALUE
    start, date, finish = $1, $2, $3
    date = "'" + date.split("/").reverse.join("-") + "'"
    str = [start, date, finish].join 
  end
  str
end

Durante o treinamento, usamos apenas o meu mac ligado a uma projetor. O pessoal ficou um pouco reprimido com o VIM, mas gostaram do TextMate. Foi um exercício legal, pois a maioria dos programadores era do Delphi, e logo conseguiram entender a codificação em Ruby.

Após o coding-dojo, fizemos uma rápida retrospectiva sobre o treinamento e levantamos alguns pontos de melhorias do coding, e o próximo treinamento vai ter um horário maior e uma rotatividade de linguagens e assuntos.

No próximo dojo, já foi definido que será usado a linguagem PlPgsql juntamente com PGUnit para bateria de testes. Eu sou muito fã desta biblioteca e sempre me ajudou em tarefas extensas de BD.

Durante este treinamento, o exemplo acima só foi apresentado no final. Outros exemplos semelhantes foram discutidos. Achei engraçado pois o pessoal do Delphi não trabalha muito com expressões regulares e eu simplesmente não conseguia pensar em outra forma de resolver o problema.


Share → Twitter Facebook Linkedin


Hello there, my name is Jônatas Davi Paganini and this is my personal blog.
I'm developer advocate at Timescale and I also have a few open source projects on github.

Check my talks or connect with me via linkedin / twitter / github / instagram / facebook / strava / meetup.