Skip to content
abril 15, 2009 / cassiomarques

Cucumber: Um step para criar qualquer número de objetos, para qualquer model

Uma simples técnica utilizando Factory-Girl e um pouco de Ruby para preparar cenários do Cucumber com qualquer quantidade de objetos, de qualquer model.

O problema

Quando escrevemos cenários com o Cucumber, muitas vezes é necessário criar um determinado número de registros no banco de dados para preparar um determinado cenário. Isso faz com que tenhamos que criar vários steps, cada um capaz de criar objetos para um determinado tipo de model. Isso pode se tornal realmente trabalhoso se tivermos muitos models diferentes.

Imagine um trecho de um cenário como este:

Given there are 3 products

Aqui temos ‘products’, que provavelmente exige a existência de um model Product e de um step parecido com

Given /^there are (\d+) products$/ do |n|
  n.to_i.times { Product.create(:description => 'foo', :price => 15.00) }
end

Agora imagine fazer esse tipo de coisa para vários models. Imagine também o inferno que isso se tornará se você tiver um monte de declarações do tipo validates_uniqueness_of nesses models…

A solução

Precisamos criar uma forma genérica de criar objetos nos nosso cenários. Com a ajuda do Factory-Girl e com um pouquinho de Ruby, a coisa fica fácil!

1 – Configurando o Cucumber para usar o Factory-Girl

Já expliquei isso aqui antes, é bem simples!

  • Crie uma pasta para guardar suas factories em algum lugar. Eu uso as mesmas factories tanto pro Cucumber quanto pro Rspec, então acabo deixando tudo em spec/factories. Coloque onde fizer mais sentido para o seu projeto.
  • Dentro dessa pasta, crie uma factory por arquivo. Isso ajuda a manter tudo organizado. Convencione o nome de cada factory como sendo o nome do model, no singular, com o camelCase substituído por underlines. Por exemplo, a definição de uma factory para o model ProductCategory, dentro de um arquivo em spec/factories/product_category_factory.rb ficaria mais ou menos assim:

        Factory.define(:product_category) do |pc|
          # ...
        end
        
  • Configure o Cucumber para incluir as factories quando os cenários forem executados. Basta adicionar duas linhas no arquivo features/support/env.rb:

        require 'factory_girl'
        Dir.glob(File.join(File.dirname(__FILE__), '../../spec/factories/*.rb')).each {|f| require f }
        

2 – Criando nossa definição de step mágico

A idéia é escrever os steps utilizando sempre o nome do model no plural, com camelCase substituído por espaços. Isso ajuda a deixar as coisas mais legíveis nos nossos cenários e se aproveita da convenção que criamos para o nome das factories para encontrar facilmente a factory a ser utilizada. Outro detalhe é que se especificarmos em nosso step que existem x objetos de um determinado model, todos os objetos previamente existentes deverão ser removidos. Vamos ao código, que pode ser definido em qualquer arquivo dentro de features/step_definitions:

Given /^there are (\d+) (.+)$/ do |n, model_str|
  model_str = model_str.gsub(/\s/, '_').singularize
  model_sym = model_str.to_sym
  klass = eval(model_str.camelize)
  klass.transaction do
    klass.destroy_all
    n.to_i.times do |i|
      Factory(model_sym)
    end
  end
  end

O que esse código faz é

  • Cria qualquer quantidade de instâncias de qualquer model.
  • Abre uma transação e apaga todos os objetos deste model do banco
  • Cria n objetos utilizando o Factory Girl (assume que existe uma factory definida com um symbol que é o nome do model passado no cenário, com os espaços substituídos por underlines e no singular)

Ou seja, agora podemos escrever steps como:

Given there are 123 clients

ou ainda

Given there are 123 clients
And there are 7 product categories

e nunca mais nos preocupar com as definições destes steps. Detalhe: Estamos usando as regras para pluralização em inglês. Se for programar em português, lembre-se de definir novas regras de pluralização no Inflector.

One Comment

Deixe um comentário
  1. uchoaaa / abr 16 2009 1:40 am

    Boa, cara! Factory-Girl e Cucumber! Ótimo post, parabéns!

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: