Как смешать модуль с контекстом rspec

Как я могу смешать модуль с контекстом rspec (он же describe), чтобы константы модуля были доступны для спецификации?

module Foo
  FOO = 1
end

describe 'constants in rspec' do

  include Foo

  p const_get(:FOO)    # => 1
  p FOO                # uninitialized constant FOO (NameError)

end

Интересен тот факт, что const_get может получить константу, когда имя константы не может. Что вызывает любопытное поведение rspec?

Я использую MRI 1.9.1 и rspec 2.8.0. Симптомы те же, что и при МРТ 1.8.7.


person Wayne Conrad    schedule 04.02.2012    source источник
comment
Какую версию Ruby вы используете?   -  person John Feminella    schedule 04.02.2012


Ответы (2)


Вы можете использовать shared_context RSpec:

shared_context 'constants' do
  FOO = 1
end

describe Model do
  include_context 'constants'

  p FOO    # => 1
end
person Brandan    schedule 04.02.2012
comment
Прошло некоторое время с тех пор, как я узнал новую интересную вещь о rspec. Очень хорошо. - person steve; 04.01.2013

Вы хотите extend, а не include. Это работает в Ruby 1.9.3, например:

module Foo
  X = 123
end

describe "specs with modules extended" do
  extend Foo
  p X # => 123
end

В качестве альтернативы, если вы хотите повторно использовать контекст RSpec в разных тестах, используйте shared_context:

shared_context "with an apple" do
  let(:apple) { Apple.new }
end

describe FruitBasket do
  include_context "with an apple"

  it "should be able to hold apples" do
    expect { subject.add apple }.to change(subject, :size).by(1)
  end
end

Если вы хотите повторно использовать спецификации в разных контекстах, используйте shared_examples и it_behaves_like:

shared_examples "a collection" do
  let(:collection) { described_class.new([7, 2, 4]) }

  context "initialized with 3 items" do
    it "says it has three items" do
      collection.size.should eq(3)
    end
  end
end

describe Array do
  it_behaves_like "a collection"
end

describe Set do
  it_behaves_like "a collection"
end
person John Feminella    schedule 04.02.2012
comment
Я тоже пробовал extend, но все равно получил NameError. Еще более странно, когда я попробовал include Foo и p(constants - Object.constants), константа X явно есть в списке, но я не могу на нее сослаться напрямую — только через const_get. Это Руби 1.8.7. - person Brandan; 04.02.2012
comment
В версии 1.8.7 extend работает немного по-другому в контексте RSpec. Я на 1.9.3. - person John Feminella; 04.02.2012
comment
@John, ни MRI 1.8.7, ни MRI 1.9.1 не работают с решением extend. Какую версию rspec вы используете? - person Wayne Conrad; 04.02.2012
comment
лучший ответ, который я нашел при использовании общего контекста, спасибо - person Paul Brunache; 10.01.2018