Shoulda para RSpec é Remarkable!

13 de novembro de 2008  |  Open Source  | 

Durante um bom tempo andei evangelizando o uso do Shoulda na Surgeworks e fiz muito uso dele em meus projetos pessoais. O fato é que não obtive muito sucesso em evangelizar meus colegas de trabalho a adotarem o Shoulda, por outro lado eles conseguiram me convencer a aprender e usar RSpec.

E realmente RSpec é um framework de testes muito interessante. Mas tudo ficou ainda mais interessante quando comecei a brincar com o Cucumber (pretendo escrever sobre isto no futuro).

Mas o segredo do sucesso do Shoulda é a maneira em que ele transforma testes comuns como verificar se as associações estão funcionando, se todas as validações necessárias foram adicionadas ou se uma simples informação foi adicionada corretamente a sessão, em algo extremamente trivial.

Passei a gostar cada dia mais do RSpec e decidi adotá-lo como meu framework oficial de testes de agora em diante. Mas não posso mais viver sem as facilidades que o Shoulda me oferecia. Então resolvi coçar a minha própria coceira.

Remarkable

Inicialmente, a função do Remarkable é portar para RSpec todas as macros do Shoulda, mas obviamente o plano é muito mais ambicioso do que isto. Tenho muita coisa em mente que tornará este projeto especialmente útil para os usuários de RSpec.

Neste momento você talvez se pergunte: “Mas já não existem plugins que fazem a mesma coisa, como o skinny e o rspec-on-rails-matchers, por exemplo?”. Sou obrigado a responder: “Sim”. Então, por que mais um projeto?

Por que mais um projeto?

Em primeiro lugar este não é simplesmente “mais um” plugin com matchers para RSpec. Vou usar um clichê agora, mas é mais pura verdade: “Este é um projeto feito do jeito certo!”.

Vejamos então uma lista com o que torna o Remarkable único:

  1. Não é um plugin, e sim um gem.
  2. Porta todas as macros atuais do Shoulda para RSpec.
  3. Possui duas sintaxes de escrita, uma para quem gosta do estilo RSpec e outra para os que estão migrando seus projetos Shoulda para RSpec.
  4. Testes.
  5. Mais testes.
  6. E mais um pouco de testes.

Sim, diferente de todos os outros projetos com o mesmo objetivo, o Remarkable é o único que possui testes, e este é um grande diferencial, acredite! Como se pode confiar em um projeto que não tem testes? Como evoluir um projeto open-source que não possui testes? O que garante que o último commit não quebrou alguma coisa que estava funcionando?

Instalação

Instalar o Remarkable é muito fácil. Ele está armazenado no GitHub, então se você nunca instalou um gem via GitHub execute primeiro:

gem sources -a http://gems.github.com

Agora instale o gem:

sudo gem install carlosbrando-remarkable

Por último adicione a seguinte linha no seu arquivo RAILS_ROOT/config/environment.rb:

config.gem "carlosbrando-remarkable", :lib => "remarkable", :source => "http://gems.github.com"

Usando

Todas as macros do Remarkable podem ser acessadas de duas maneira diferentes. Para aqueles que preferem o estilo Shoulda, vejamos como ficaria o teste de um modelo:

describe Post do
  fixtures :all

  should_belong_to :user
  should_belong_to :owner
  should_belong_to :user, :owner

  should_have_many :tags, :through => :taggings
  should_have_many :through_tags, :through => :taggings
  should_have_many :tags, :through_tags, :through => :taggings

  should_require_unique_attributes :title
  should_require_attributes :body, :message => /wtf/
  should_require_attributes :title
  should_only_allow_numeric_values_for :user_id
end

Igualzinho ao Shoulda? É esta a idéia! Esta sintaxe é ideal para aqueles que desejarem migrar seus testes do Shoulda para o RSpec (tendo apenas de alterar de context para describe e de should para it) ou mesmo para os que adoram a jeitão do Shoulda, assim como eu.

Mas se você não gosta desta sintaxe, também pode criar os mesmos testes da seguinte forma:

describe Post do
  fixtures :all

  it { should belong_to(:user) }
  it { should belong_to(:owner) }
  it { should belong_to(:user, :owner) }

  it { should have_many(:tags, :through => :taggings) }
  it { should have_many(:through_tags, :through => :taggings) }
  it { should have_many(:tags, :through_tags, :through => :taggings) }

  it { should require_unique_attributes(:title) }
  it { should require_attributes(:body, :message => /wtf/) }
  it { should require_attributes(:title) }
  it { should only_allow_numeric_values_for(:user_id) }
end

Agora muito mais no estilo RSpec!

Macros

Veja uma relação com todas as macros disponíveis na documentação do projeto.

Para o estilo Shoulda, clique aqui.
Para o estilo RSpec, clique aqui.

Finalizando

Este projeto já atingiu o primeiro objetivo, que era portar todas as macros do Shoulda para o RSpec. Tudo feito da maneira correta, com todos os cuidados e muitos testes. Mas nada melhor do que o uso na prática para encontrarmos pontos que devem ser melhorados.

Enfim, usem o Remarkable, e ajudem a torná-lo ainda melhor!


12 Comentários


  1. Muito bom Carlos, isso realmente vai me ajudar a diminuir um pouco da duplicação de código desnecessária nas minhas specs. Vou usar um pouco e ver se consigo levantar alguns pontos para melhoria, mas pelo que vi até agora parece estar muito bacana. Parabéns!

  2. Muito bom! Já faz um tempo que queria fazer um plugin assim também. Agora que já esta feito, só resta colaborar. :)

  3. Assim q aprender rspec e shoulda vou começar a user o gem. Gostei muito da ideia. =D

  4. Cara, muito bom isso, estavamos mesmo precisando de uma forma mais simples de fazer essas validações do Rails :)

  5. Aqui uso Linux com o gedit e já estou criando uns snippets para usar as macros do Remarkable! Minhas specs encolheram!

  6. Legal Cássio. Obrigado pelo feedback!

  7. Carlos,

    Atualizei aqui pro Rspec 1.1.12 e alguns testes que antes passavam normalmente agora estão falhando. Aparentemente é alguma coisa que só acontece nas macros que testam associações.
    Coloquei uma pequena explicação do problema com exemplo aqui => http://pastie.org/360467

    Abraço!

  8. Já estou sabendo do problema Cássio. Vou corrigir em breve. Mas obrigado por avisar.

  9. Você está usando uma versão muito antiga do Remarkable.

  10. Olha só, acabei descobrindo o projeto pelo Google. Parabéns, muito legal mesmo! Chega de testes repetitivos e chatos! O melhor do Shoulda no RSpec! :-)

    Vou continuar no aguardo pelas outras features!

    Abraço!

  11. Carlos,

    Como eu poderia fazer para pegar o valor correto em klass aqui no seguinte trecho (estou querendo fazer um matcher simples para validar modelos que utilizam o Paperclip):

    def should_have_attached_file(attachment)
      should_have_db_column("#{attachment}_file_name",    :type => :string)
      should_have_db_column("#{attachment}_content_type", :type => :string)
      should_have_db_column("#{attachment}_file_size",    :type => :integer)
    
      it "should have a paperclip attachment named ##{attachment}" do
        klass.new.respond_to?(attachment.to_sym).should == true
        klass.new.send(attachment.to_sym).class.should == Paperclip::Attachment
      end
    end
  12. Davis, ainda precisamos melhorar a documentação da criação de macros personalisadas, mas olhando no código do projeto você encontrará um exemplo de uma macro chamada my_macro.rb que deve lhe dar uma idéia de como fazer.

    Mas eu prometo escrever algo sobre isto em breve.

Trackbacks

  1. Nome do Jogo » Blog Archive » The RSpec Book: Behaviour Driven Development with Ruby
  2. Nome do Jogo » Blog Archive » Rails Podcast Brasil - Episódio 39
  3. Nome do Jogo » Blog Archive » Remarkable 2.0.1 e Atualização do (Comovente) Guia de Ruby do Why

Deixe um comentário