为了避免在我的Rspec测试中重复自己,我想写一个这样的函数
def with_each_partner(&block)
PARTNER_LIST.each do |partner|
context "with partner #{partner.name}" { yield partner }
end
end
我有这样一个功能,它的工作原理是所有测试都以正确的值提供给合作伙伴,但是他们不会在输出期间打印作为"与合作伙伴X&#的一部分34;上下文:相反,如果我有这样的测试:
describe Thing do
subject { Thing.new(partner) }
with_each_partner do |partner|
it 'does its thing' do
expect(subject.do).to eq 'its thing'
end
end
end
我最终输出如下:
Thing
does its thing
而不是所需的输出,如:
Thing
with partner X
does its thing
with partner Y
does its thing
如何让RSpec正确使用我的函数中创建的上下文?
答案 0 :(得分:7)
TL; DR:这样做:
def with_each_partner(&block)
PARTNER_LIST.each do |partner|
context "with partner #{partner.name}" do
class_exec(&block)
end
end
end
RSpec的DSL通过评估具有更改self
的块来工作 - 这是it
或describe
块中的方法的context
,但不是在它之外。当您yield
时,将使用原始self
评估提供的块,该self
在定义块的位置为with_each_partner
。这意味着使用原始describe Thing do
subject { Thing.new(partner) }
with_each_partner do |partner|
it 'does its thing' do
expect(subject.do).to eq 'its thing'
end
end
end
定义,此代码:
describe Thing do
subject { Thing.new(partner) }
outer_example_group = self
with_each_partner do |partner|
outer_example_group.it 'does its thing' do
expect(subject.do).to eq 'its thing'
end
end
end
真的像这样评估:
"with partner #{partner.name}"
...所以单个示例在外部示例组上定义,而不是在class_exec
嵌套组上定义。
class_exec
evaluates the provided block in the context of the class/module。在这种情况下,该类是RSpec为您的上下文生成的示例组子类。使用it
可确保在调用context
时,接收方是嵌套的{{1}}示例组,而不是外部示例组,从而创建所需的结果。