Frage

In einem Bündel von rspec Schienen Einheit Spezifikationen ich so etwas wie:

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

ich saubereren Code würde eher so etwas wie:

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

Wie schreibe ich eine Hilfsmethode wie spec_has_many() zum Einfügen DSL Code wie it() Methode des rspec? Wenn es für einen gewöhnlichen Instanzmethode wäre, würde ich so etwas wie:

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

Was wäre das Äquivalent für die Definition rspec Beispiele sein?

War es hilfreich?

Lösung

Ok, das war etwas rumgespielt, aber ich glaube, ich habe es funktioniert. Es ist ein bisschen von Metaprogrammierung hackery, und ich würde persönlich benutzen nur das erste, was Sie beschrieben, aber es ist das, was man wollte: 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

Meine Spezifikationen scheitern, weil Foo keine has_many? Methode, aber beide Tests laufen, so sollte es funktionieren.

können Sie definieren (und benennen) die ExampleMacros in Ihrem spec_helper.rb Datei-Modul und es wird für die Aufnahme zur Verfügung stehen. Sie wollen include ExampleMacros in Ihrem describe Blöcke nennen (und nicht irgendwelche andere).

Um alle Ihre Angaben zu machen umfassen das Modul automatisch configure RSpec etwa so:

# RSpec 2.0.0
RSpec.configure do |c|
  c.include ExampleMacros
end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top