tests spectroscopy run rails how example better ruby rspec

ruby - spectroscopy - Rspec dejó ver el alcance



rspec spectroscopy (5)

Descubrí que si no pasas explícitamente el parámetro declarado por let , estará disponible en el ejemplo compartido.

Asi que:

describe Connection do let(:connection) { described_class.new(connection_settings) } it_behaves_like "any connection" end

la conexión estará disponible en las especificaciones de ejemplo compartidas

Creo que tengo un problema con rspec let y scoping. Puedo usar los métodos definidos con let in examples (los bloques "it"), pero no afuera (el bloque describe donde hice el let).

5 describe Connection do 8 let(:connection) { described_class.new(connection_settings) } 9 10 it_behaves_like "any connection", connection 24 end

Cuando intento ejecutar esta especificación, obtengo el error:

connection_spec.rb: 10: variable local indefinida o método `connection ''para Class: 0xae8e5b8 (NameError)

¿Cómo puedo pasar el parámetro de conexión a it_behaves_like?


Encontré lo que funciona para mí:

describe Connection do it_behaves_like "any connection", new.connection # new.connection: because we''re in the class context # and let creates method in the instance context, # instantiate a instance of whatever we''re in end


Esto funciona para mí:

describe "numbers" do shared_examples "a number" do |a_number| let(:another_number) { 10 } it "can be added to" do (a_number + another_number).should be > a_number end it "can be subtracted from" do (a_number - another_number).should be < a_number end end describe "77" do it_should_behave_like "a number", 77 end describe "2" do it_should_behave_like "a number", 2 end end


let () se supone que tiene un alcance para los bloques de ejemplo e inutilizable en otro lugar. En realidad, no usa let () como parámetros. La razón por la que no funciona con it_behaves_like como parámetro tiene que ver con cómo se define let (). Cada grupo de ejemplo en Rspec define una clase personalizada. let () define un método de instancia en esa clase. Sin embargo, cuando llamas it_behaves_like en esa clase personalizada, está llamando al nivel de clase en lugar de desde una instancia.

He usado let () de esta manera:

shared_examples_for ''any connection'' do it ''should have valid connection'' do connection.valid? end end describe Connection do let(:connection) { Connection.new(settings) } let(:settings) { { :blah => :foo } } it_behaves_like ''any connection'' end

He hecho algo similar a la respuesta de bcobb, aunque rara vez uso shared_examples:

module SpecHelpers module Connection extend ActiveSupport::Concern included do let(:connection) { raise "You must override ''connection''" } end module ClassMethods def expects_valid_connection it "should be a valid connection" do connection.should be_valid end end end end end describe Connection do include SpecHelpers::Connection let(:connection) { Connection.new } expects_valid_connection end

La definición de esos ejemplos compartidos es más detallada que usar ejemplos compartidos. Creo que encuentro que "it_behave_like" es más incómodo que extender Rspec directamente.

Obviamente, puede agregar argumentos a .expects_valid_connections

Escribí esto para ayudar a la clase rspec de un amigo: http://ruby-lambda.blogspot.com/2011/02/agile-rspec-with-let.html ...


Redacted - completamente añicos en mi primera solución. Ho-Sheng Hsiao dio una gran explicación de por qué.

Puedes darle it_behaves_like a block como ese:

describe Connection do it_behaves_like "any connection" do let(:connection) { described_class.new(connection_settings) } end end