RSpec shared_examples с использованием аргумента let или block

#rspec #interface #tdd

#rspec #интерфейс #tdd

Вопрос:

В «Практическом объектно-ориентированном проектировании на Ruby» Санди Мец использовал Minitest для демонстрации написания общего теста для тестирования ролей. Итак, я думаю о том, как сделать эквивалент RSpec.
wheel Играет роль a diameterizable . A diameterizable определяется как объект, который отвечает на width . До сих пор я придумал две разные версии, чтобы сделать объект доступным для общего примера. Какой подход лучше или есть лучший способ?

версия 1, используйте let:

 # wheel_spec.rb
RSpec.describe Wheel do
  let(:wheel) { Wheel.new(26, 1.5) }

  it_behaves_like "a diameterizable" do
    let(:diameterizable) { wheel }
  end

  # wheel is available for use ...
end

# diameterizable_interface.rb
RSpec.shared_examples "a diameterizable" do
  it "implements the diameterizable interface" do
    expect(diameterizable).to respond_to(:width)
  end
end
  

версия 2, использовать аргумент block:

 # wheel_spec.rb
RSpec.describe Wheel do
  let(:wheel) { Wheel.new(26, 1.5) }

  it_behaves_like "a diameterizable", Wheel.new

  # wheel is available for use ...
end

# diameterizable_interface.rb
RSpec.shared_examples "a diameterizable" do |diameterizable|
  it "implements the diameterizable interface" do
    expect(diameterizable).to respond_to(:width)
  end
end 
  

Ответ №1:

Похоже, сейчас самое время использовать неявный subject:

 RSpec.shared_examples "a diameterizable" do
  it "implements the diameterizable interface" do
    expect(subject).to respond_to(:width)
  end
end

RSpec.describe Wheel do
  let(:wheel) { Wheel.new(26, 1.5) }
  subject { wheel }

  it_behaves_like "a diameterizable"
end
  

кстати, ваша вторая версия создает новый Wheel для общего примера, что может создать проблемы.

Комментарии:

1. использование неявного subject кажется вполне уместным! Это также упрощает применение нескольких «it_behaves_like».