Подтвердить что ты не робот

Какая разница между "include_examples" и "it_behaves_like"?

В RSpec, какая разница между it_behaves_like и include_examples?

В документации говорится:

include_examples - включить (-ы) примеры в текущем контексте

it_behaves_like "name" - включить (-ы) примеры во вложенном контексте

Но что это значит? Замена одного на другой, похоже, не влияет на то, проходят ли мои тесты или не проходят. Есть ли причина предпочесть друг другу в некоторых ситуациях?

Также есть it_should_behave_like и it_behaves_like только синонимы?

4b9b3361

Ответ 1

Вероятно, вы знаете, как использовать describe, context, it и specify, чтобы четко передать один аспект вашего кода. Вложенный контекст, предоставляемый it_behaves_like, может использоваться для улучшения этой связи с читателем.

Я опишу свой пример на примере, приведенном в документации RSpec для общих примеров:

shared_examples "a collection" do
  context "initialized with 3 items" do
    it "says it has three items" do
      # ...
    end
  end
end

describe Array do
  it_behaves_like "a collection"
  include_examples "a collection"
end

Если вы запустите RSpec с помощью --format documentation, вы получите следующий вывод:

Array
  behaves like a collection
    initialized with 3 items
      says it has three items
  initialized with 3 items
    says it has three items

Таким образом, разница в том, как считывается спецификация, например, в случае сбоя.

Какой стиль вы предпочитаете - это вопрос эстетики того, как вам нравятся ваши спецификации. Кроме того, вы бы предложили всегда использовать один и тот же стиль, если вы работаете в команде, чтобы улучшить согласованность.


Кроме того, являются ли это_should_behave_like и it_behaves_like только синонимами?

Почти, контекст назван по-разному. it should behave like ... vs behaves like .... Опять вопрос об эстетике.

Ответ 2

Там есть разница в том, что вы передаете параметры в shared_examples.

Он очень хорошо объяснил предупреждение в своем документе:

ПРЕДУПРЕЖДЕНИЕ. Когда вы включаете параметризованные примеры в текущем контексте несколько раз, вы можете переопределить предыдущие определения методов и последние победы в объявлении. Поэтому, если у вас есть такой общий пример (или общий контекст)

RSpec.shared_examples "some example" do |parameter|
  \# Same behavior is triggered also with either `def something; 'some value'; end`
  \# or `define_method(:something) { 'some value' }`
  let(:something) { parameter }
  it "uses the given parameter" do
    expect(something).to eq(parameter)
  end
end

RSpec.describe SomeClass do
  include_examples "some example", "parameter1"
  include_examples "some example", "parameter2"
end

Вы действительно это делаете (обратите внимание, что первый пример не удастся):

RSpec.describe SomeClass do
  \# Reordered code for better understanding of what is happening
  let(:something) { "parameter1" }
  let(:something) { "parameter2" }

  it "uses the given parameter" do
    \# This example will fail because last let "wins"
    expect(something).to eq("parameter1")
  end

  it "uses the given parameter" do
    expect(something).to eq("parameter2")
  end
end

Чтобы предотвратить такую ​​тонкую ошибку, выдается предупреждение, если вы объявить несколько методов с тем же именем в одном контексте. Если вы получите это предупреждение, самое простое решение - заменить include_examples с it_behaves_like, таким образом, метод переопределения исключается из-за вложенного контекста, созданного it_behaves_like