2010-10-20 17 views
6

In un gruppo di rotaie RSpec Specifiche unità che faccio qualcosa di simile:Come si scrivono i metodi che inseriscono esempi rspec?

describe Foo do 
    [:bar, :baz].each do |a| 
    it "should have many #{a}" do 
     Foo.should have_many(a) 
    end 
    end 
end 

Per il codice più pulito Preferirei fare qualcosa di simile:

describe Foo do 
    spec_has_many Foo, :bar, :baz 
end 

Così Come faccio a scrivere un metodo di supporto come spec_has_many() per inserire il codice DSL come il metodo it() di rspec? Se fosse per un metodo di istanza ordinaria farei qualcosa di simile:

def spec_has_many(model, *args) 
    args.each do |a| 
    define_method("it_should_have_many_#{a}") do 
     model.should have_many(a) 
    end 
    end 
end 

Quale sarebbe l'equivalente per la definizione esempi RSpec?

risposta

9

Ok, questo ha richiesto un po 'di confusione, ma penso di averlo fatto funzionare. E 'un po' di metaprogrammazione aggiustamenti, e io personalmente sarebbe solo usare la prima cosa che hai descritto, ma è quello che volevi: P

module ExampleMacros 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 
    # This will be available as a "Class Macro" in the included class 
    def should_have_many(*args) 
     args.each do |a| 
     # Runs the 'it' block in the context of the current instance 
     instance_eval do 
      # This is just normal RSpec code at this point 
      it "should have_many #{a.to_s}" do 
      subject.should have_many(a) 
      end 
     end 
     end 
    end 
    end 
end 

describe Foo do 
    # Include the module which will define the should_have_many method 
    # Can be done automatically in RSpec configuration (see below) 
    include ExampleMacros 

    # This may or may not be required, but the should_have_many method expects 
    # subject to be defined (which it is by default, but this just makes sure 
    # it's what we expect) 
    subject { Foo } 

    # And off we go. Note that you don't need to pass it a model 
    should_have_many :a, :b 
end 

mie specifiche fallire perché Foo non ha un metodo has_many?, ma entrambi i test eseguito , quindi dovrebbe funzionare.

È possibile definire (e rinominare) il modulo ExampleMacros nel file spec_helper.rb e sarà disponibile per l'inclusione. Si desidera chiamare include ExampleMacros nei blocchi describe (e non in altri).

Per rendere tutte le specifiche includono il modulo automaticamente, configurare RSpec in questo modo:

# RSpec 2.0.0 
RSpec.configure do |c| 
    c.include ExampleMacros 
end 
Problemi correlati