Pregunta

En un montón de carriles rspec especificaciones de la unidad que hago algo como:

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

Para obtener un código más limpio prefiero hacer algo como:

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

Entonces, ¿cómo escribir un método de ayuda como spec_has_many() para insertar código de ADSL como método de it() rspec? Si se tratara de un método de instancia ordinaria que me gustaría hacer algo como:

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

¿Cuál sería el equivalente para definir ejemplos rspec?

¿Fue útil?

Solución

Ok, esto tomó un poco de jugar un poco, pero creo que tengo trabajo. Es un poco de hackery metaprogramming, y yo, personalmente, sólo tiene que utilizar la primera cosa que usted describe, pero es lo que quería: 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

Mis especificaciones fallar porque Foo no tiene un método has_many?, pero ambas pruebas correr, así que debería funcionar.

Se puede definir (y cambiar el nombre) Módulo de los ExampleMacros en su archivo spec_helper.rb y estará disponible para su inclusión. Al que desea llamar include ExampleMacros en sus bloques describe (y no cualquier otro).

Para hacer todas sus especificaciones incluyen el módulo automáticamente, configure RSpec este modo:

# RSpec 2.0.0
RSpec.configure do |c|
  c.include ExampleMacros
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top