Domanda

In un gruppo di rotaie RSpec Specifiche unità che faccio qualcosa di simile:

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

Quindi, come faccio a scrivere un metodo di supporto come spec_has_many() per l'inserimento di codice DSL come 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?

È stato utile?

Soluzione

Ok, questo ha preso un po 'di fare in giro, ma penso che ho preso a lavorare. E 'un po' di aggiustamenti metaprogrammazione, 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

I miei spec fallire perché Foo non ha un metodo has_many?, ma entrambi i test eseguito, così 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 vostri blocchi describe (e non tutti gli altri).

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

# RSpec 2.0.0
RSpec.configure do |c|
  c.include ExampleMacros
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top