2012-07-01 15 views
13

Quiero compartir un método memorado entre mis especificaciones. Así que traté de usar el contexto compartido como esteCompartir contexto automáticamente en RSpec

RSpec.configure do |spec| 
    spec.shared_context :specs do 
    let(:response) { request.execute! } 
    end 
end 

describe 'something' do 
    include_context :specs 
end 

Funciona bien. Pero tengo alrededor de 60 archivos de especificaciones, por lo que me veo obligado a incluir explícitamente el contexto en cada uno de ellos. ¿Hay alguna manera de incluir automáticamente el contexto compartido (o al menos let definición) para todos los grupos de ejemplo en spec_helper.rb?

Algo como esto

RSpec.configure do |spec| 
    spec.include_context :specs 
end 
+0

Esto probablemente duplica http://stackoverflow.com/questions/9965111/rspec-shared-context-and-include-context-for-all-specs pero todavía no tiene respuesta. – p0deje

Respuesta

28

Puede configurar globales before ganchos utilizando RSpec.configure través configure-class-methods y Configuration:

RSpec.configure {|c| c.before(:all) { do_stuff }} 

let no está soportada en RSpec.configure, pero puede establecer una global let incluyéndolo en un SharedContext module e incluyendo ese módulo usando config.before:

module MyLetDeclarations 
    extend RSpec::Core::SharedContext 
    let(:foo) { Foo.new } 
end 
RSpec.configure { |c| c.include MyLetDeclarations } 
+12

FYI para cualquiera que use RSpec 3, parece que 'RSpec :: Core :: SharedContext' se ha ido, y se ha reemplazado por' RSpec :: SharedContext'. – womble

+0

Esta es una buena solución. Un pequeño error que encontré en RSpec 3 es que al pasar una etiqueta para incluir y tener esa etiqueta en mis bloques de ejemplo (en lugar de ejemplos de bloques de grupo) recibí un error 'NoMethodError: super: no superclass method \' foo 'for # ¿Quiso decir? # foo'. La solución es solo para asegurarse de que la etiqueta esté en el grupo de ejemplo en lugar del ejemplo. –

+1

Apagué el mismo error que @GabeKopley pero descubrí que la actualización a RSpec 3.4.0 resolvió el problema. – phylae

5

Usted puede hacerlo casi así: hay un mecanismo para incluir un módulo, y la inclusión del módulo tiene su propio mecanismo de devolución de llamada.

Supongamos, por ejemplo, que tenemos un contexto compartido disconnected que queremos utilizar para ejecutar todas las especificaciones de nuestro modelo sin una conexión a la base de datos.

shared_context "disconnected" do 
    before :all do 
    ActiveRecord::Base.establish_connection(adapter: :nulldb) 
    end 

    after :all do 
    ActiveRecord::Base.establish_connection(:test) 
    end 
end 

Ahora puede crear un módulo que incluirá ese contexto en la inclusión.

module Disconnected 
    def self.included(scope) 
    scope.include_context "disconnected" 
    end 
end 

Por último, puede incluir ese módulo en todas las características de la forma normal (que he demostrado lo hace sólo para los modelos, sólo para demostrar que se puede), que es casi exactamente lo que usted pidió.

RSpec.configure do |config| 
    config.include Disconnected, type: :model 
end 

que trabaja con rspec-core 2.13.0 y 2.13.0 rspec-rails.

0

También si usted necesita capacidad de utilizar los datos compartidos en before bloques especificaciones dentro, como yo, tratan de incluir esto (si su proyecto Rails):

module SettingsHelper 
    extend ActiveSupport::Concern 

    included do 
    attr_reader :default_headers 

    before :all do 
     @default_headers = Hash[ 
      'HTTP_HOST' => 'test.lvh.me' 
     ] 
    end 

    after :all do 
     @default_headers = nil 
    end 
    end 
end 

RSpec.configure do |config| 
    config.include SettingsHelper 
end 

O intentar algo similar, mire respuesta @threedaymonk .

1

Otra forma de hacerlo es automatically share examples via metadata. Por lo tanto:

shared_context 'a shared context', a: :b do 
    let(:foo) { 'bar' } 
end 

describe 'an example group', a: :b do 
    # I have access to 'foo' variable 
end 

La forma más común es que lo uso en rspec-carriles, con un poco de contexto compartido dependiendo del tipo de grupo de ejemplo. Así que si usted tiene config.infer_spec_type_from_file_location!, sólo tiene que hacer:

shared_context 'a shared context', type: :controller do 
    let(:foo) { 'bar' } 
end 

describe SomeController do 
    # I have access to 'foo' variable 
end 
5

En RSpec 3+, esto se puede lograr de la siguiente manera - sobre la base de la respuesta de Jeremy Peterson.

# spec/supprt/users.rb 
module SpecUsers 
    extend RSpec::SharedContext 

    let(:admin_user) do 
    create(:user, email: '[email protected]') 
    end 
end 

RSpec.configure do |config| 
    config.include SpecUsers 
end 
Cuestiones relacionadas