¿Cómo escribo métodos que insertan ejemplos rspec?
-
09-10-2019 - |
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?
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