我正在尝试学习如何使用Rspec的共享示例功能,并在运行测试时收到警告:
WARNING: Shared example group 'required attributes' has been previously defined at:
/Users/me/app/spec/support/shared_examples/required_attributes_spec.rb:1
...and you are now defining it at:
/Users/me/app/spec/support/shared_examples/required_attributes_spec.rb:1
The new definition will overwrite the original one.
....
我已经阅读了我认为有关此问题的文档here,但我无法理解它/看到我案例的内容。
以下是我的共享示例:
# spec/support/shared_examples/required_attributes_spec.rb
shared_examples_for 'required attributes' do |arr|
arr.each do |meth|
it "is invalid without #{meth}" do
subject.send("#{meth}=", nil)
subject.valid?
expect(subject.errors[meth]).to eq(["can't be blank"])
end
end
end
我正在尝试在User
模型和Company
模型中使用它。这是它的样子:
# spec/models/user_spec.rb
require 'rails_helper'
describe User do
subject { build(:user) }
include_examples 'required attributes', [:name]
end
# spec/models/company_spec.rb
require 'rails_helper'
describe Company do
subject { build(:company) }
include_examples 'required attributes', [:logo]
end
根据我上面链接的Rspec文档中的建议,我尝试将include_examples
更改为it_behaves_like
,但这没有帮助。我还完全评论了company_spec.rb
因此只有一个使用共享示例的规范,我仍然收到警告。
任何人都可以帮助我看看这里发生了什么,以及在这种情况下我应该做些什么来避免警告?
答案 0 :(得分:26)
我在Rspec Github的issue找到了答案:
以防有人谷歌和土地在这里。如果把你的文件 共享示例到support文件夹中没有修复以下内容 错误...确保您的文件名不以
结尾_spec.rb.
答案 1 :(得分:0)
作为对此的后续处理,我在包含的共享上下文中遇到了问题,文件名不以 _spec.rb
结尾,并且是通过 require_relative
手动加载的,而不是自动加载。就我而言,问题是复制粘贴问题。测试如下:
RSpec.shared_examples 'foo' do
RSpec.shared_examples 'bar' do
it ... do... end
it ... do... end
# etc.
end
context 'first "foo" scenario' do
let ...
include_examples 'bar'
end
context 'second "foo" scenario' do
let ...
include_examples 'bar'
end
end
目的是提供一组单一的共享示例,这些示例在多个操作上下文中进行了良好的覆盖,所有示例都通过内部共享示例列表运行。
这个错误很简单但很微妙。由于我关闭了 RSpec 猴子补丁 (disable_monkey_patching!
),因此我必须在顶层使用 RSpec.<foo>
。但是在任何其他 RSpec 块中,使用 RSpec.<foo>
定义 RSpec 的顶级 :main
上下文中的实体。因此,第二组共享的“内部”示例没有在 'foo' 中定义,而是在顶级定义。一旦超过一个其他文件require_relative
执行了上述代码,这足以使事情变得混乱,足以触发 RSpec 警告。
解决方法是在嵌套集中只执行 shared_examples 'bar'
,而不是 RSpec.shared_examples 'bar'
,以便在内部上下文中正确描述内部示例。
(旁白:这是一个有趣的例子,说明关闭猴子补丁比乍一看更重要 - 这不仅仅是为了名称空间的纯度。它允许在声明之间进行更清晰的区分“这是顶级”和“这是嵌套的”。)