Estoy usando RSpec (2.10.1) para probar validaciones en un modelo y he extraído algún código para compartir con otras validaciones de modelo. Las validaciones fueron escritas por primera vez en la mesa de Empresas, por lo que el código es el siguiente:Cómo pasar una variable de instancia a un ejemplo compartido RSpec
# support/shared_examples.rb
shared_examples "a text field" do |field, fill, length|
it "it should be long enough" do
@company.send("#{field}=", fill * length)
@company.should be_valid
end
etc...
end
y el uso es:
# company_spec.rb
describe Company do
before { @company = Company.new(init stuff here) }
describe "when address2" do
it_behaves_like "a text field", "address2", "a", Company.address2.limit
end
etc...
end
me gustaría pasar el @company
como parámetro a la compartida ejemplo, por lo que puede volver a utilizar el código para diferentes modelos, algo como esto:
# support/shared_examples.rb
shared_examples "a text field" do |model, field, fill, length|
it "it should be long enough" do
model.send("#{field}=", fill * length)
model.should be_valid
end
etc...
end
y el uso es:
# company_spec.rb
describe Company do
before { @company = Company.new(init stuff here) }
describe "when address2" do
it_behaves_like "a text field", @company, "address2", "a", Company.address2.limit
end
etc...
end
Sin embargo, cuando hago esto obtengo undefined method 'address2' for nil:NilClass
. Parece que @company
no se está aprobando (¿no en el alcance?) ¿Cómo puedo hacer que algo así funcione?
Algunas piezas no tienen sentido para mí. Si es que el "yo" es diferente, ¿dónde es diferente? ¿Por qué '@ company.send()' y '@ company.should' funcionan en' shared_examples'? En su sugerencia, puedo reemplazar 'Company.new()' con '@ company' (manteniendo el bloque' before') y eso funciona. A mi comprensión le falta algo sobre qué está pasando exactamente aquí. Parece que 'self 'solo es diferente en un lugar en particular (la línea' it_behaves_like' hasta 'do'). –
Hay dos valores básicos que 'self' toma en RSpec, y es análogo a los dos valores de self en una definición de clase ruby. Entre un 'describe' /' context'/'shared_examples_for' y su correspondiente' end' (pero no en los bloques 'it'),' self' es el grupo de ejemplo - al igual que 'self' en un cuerpo de clase (pero no en una definición de método) es la clase misma. 'self' en un bloque' it'/'let' o un hook' before'/'after' /' around' o es el ejemplo - al igual que 'self' en la definición de un método de instancia de una clase es la instancia de la clase . –
Otra forma de pensarlo: hay un proceso de dos pasos que realiza RSpec. En primer lugar, evalúa todos los bloques anidados 'describe' /' context'/'shared_examples_for' para definir todos los ejemplos; en este punto, 'self' en estos contextos es el grupo de ejemplo correspondiente. En segundo lugar, RSpec ejecuta todos los ejemplos definidos (los bloques 'it'). Cada ejemplo definido se evalúa en una instancia del grupo de ejemplo correspondiente, y 'self' es el ejemplo. –