ruby “include_examples”和“it_behaves_like”有什么区别?

qoefvg9y  于 2023-04-05  发布在  Ruby
关注(0)|答案(3)|浏览(101)

在RSpec中,it_behaves_likeinclude_examples有什么区别?
documentation表示:
include_examples-包括当前上下文中的示例
it_behaves_like "name"-在嵌套上下文中包含示例
但是这实际上意味着什么呢?用一个替换另一个似乎对我的测试是通过还是失败没有影响。在某些情况下,有理由更喜欢一个吗?
it_should_behave_likeit_behaves_like是同义词吗?

siv3szwd

siv3szwd1#

您可能知道如何使用describecontextitspecify来清楚地传达代码的某个方面。it_behaves_like提供的嵌套上下文可用于改善与读者的这种沟通。
我的示例将基于shared examples的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

如果使用--format documentation运行RSpec,则会得到以下输出:

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

因此,不同之处在于如何读取规范,例如在失败的情况下。
你喜欢哪种风格是一个美学问题,你喜欢你的规格阅读。此外,你会建议总是使用相同的风格,如果你在一个团队中工作,以提高一致性。
另外,it_should_behave_like和it_behaves_like是否只是同义词?
几乎,上下文的命名不同。it should behave like ... vs behaves like ...。再次是美学问题。

fd3cxomn

fd3cxomn2#

这里有的区别,如果你传递参数给shared_examples。
在警告in their doc中解释得很好:
警告:当你在当前上下文中多次包含参数化的示例时,你可能会覆盖以前的方法定义,最后一个声明获胜。

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_behaviors_like,这样可以避免方法重写,因为it_behaviors_like创建了嵌套的上下文

plicqrtu

plicqrtu3#

在使用shared_examples方法时,我发现it_behaves_likeinclude_context之间有很大的区别。
当你使用include_context时,你可以在你的shared_examples块中定义letbeforeit语句。我想你可能也可以使用contextdescribe块。
但是如果你使用it_behaves_like,你可以在你的共享示例中使用it语句,但是如果你在你的shared_example上定义了一些let块,它们就不能在包含it_behaves_like语句的原始rspec.describe块中使用。
我认为这是一个巨大的差异。
同样适用于include_examples。我认为可能include_examplesinclude_context非常相似。

相关问题