gpt4 book ai didi

ruby - 使用不同的参数重复 RSpec 示例组

转载 作者:数据小太阳 更新时间:2023-10-29 07:16:20 25 4
gpt4 key购买 nike

我试图保持我的规范干净和干燥,但我对 API 进行了一些测试,除了正在测试的 API 版本之外,它们是相同的。我可以简单地使用这样的东西来重复规范:

%w( v1 v2 ).each do |version|
describe "Query #{version} API" do
it "responds with JSON"
# make the call using the version
end
end
end

但是我想要一些更简洁的东西,所以我写了这个方法:

module RepetitivelyDescribe
def repetitively_describe(*args, &example_group_block)
options = args.extract_options!
options.delete(:for).each do |item|
item_args = args.collect(&:dup) + [options.dup]
item_args[0] << " [#{item}]"

describe(*item_args) do
example_group_block.call item
end
end
end
end

RSpec::Core::ExampleGroup.extend RepetitivelyDescribe

然后我的测试看起来更像这样:

repetitively_describe "Query API", :for => %( v1 v2 ) do |version|
it "responds with JSON"
# make the call using the version
end
end

我意识到这有点迂腐,但它的缩进程度降低了一个级别,如果我要经常进行此调用,我希望它更简洁。

当然,它并没有像我希望的那样工作。在我的 repetitively_describe 中对 describe 的调用没有记录到 RSpec 输出(当使用文档格式输出时),尽管其中的示例确实得到重复并使用版本如预期的那样阻止参数。从本质上讲,该级别的上下文丢失了(保留了 repetitively_describe block 外部和内部的 describe block )。

a gist 中有更详细的示例代码如果需要的话。关于为什么这不太正常的任何线索?

最佳答案

所以(如果我在重复你已经知道的东西,我深表歉意)但是每次你调用 describe/context rspec 都会创建一个新类,它是当前示例组类的子类(最终是 RSpec 的子类)::Core::ExampleGroup),然后使用 module_eval 在该类的上下文中评估 block 。如果我跑

describe "foo" do
puts "#{self}; #{self.superclass}"
describe "behaviour 1" do
puts "#{self}; #{self.superclass}"
context "with x" do
puts "#{self}; #{self.superclass}"
end
end
end

那么输出是

#<Class:0x007fb772bfbc70>; RSpec::Core::ExampleGroup
#<Class:0x007fb772bfb180>; #<Class:0x007fb772bfbc70>
#<Class:0x007fb772bfa5f0>; #<Class:0x007fb772bfb180>

当你调用 it 时,rspec 创建一个 Example 对象并将它附加到 self(当前示例组)上的类实例变量。 rspec 还将当前示例组粘贴到示例的元数据中,沿着这个示例组树向上走就是为您提供示例的完整描述。

您的repetitively_describe 方法调用describe,因此在您调用example_group_block.call item 时,self 确实是新创建的示例组。当 proc 被评估时,它当然会记住调用它时 self 的值是什么,因此您对 it 的调用是针对在 repeatingly_describe 时当前的示例组(通过散布一些调用来检查整个代码中 self 的值,可以轻松验证)。类似地,对 describe 的调用将示例组添加为外部示例组的子组,而不是 repetitively_describe 创建的示例组。

您当然需要做的是调用 example_group_block 保留 self 的正确值。

module RepetitivelyDescribe
def repetitively_describe(*args, &example_group_block)
options = args.extract_options!
options.delete(:for).each do |item|
item_args = args.collect(&:dup) + [options.dup]
item_args[0] << " [#{item}]"

describe(*item_args) do
class_exec(item, &example_group_block)
end
end
end
end

有了这个改变

describe('foo') do
repetitively_describe "Query API", :for => %w( v1 v2 ) do |version|
it "responds with JSON"
end
end.descendant_filtered_examples.collect(&:full_description)

输出 ["foo Query API [v1] 以 JSON 响应", "foo Query API [v2] 以 JSON 响应"] 而不是 ["foo 以 JSON 响应", "foo 在更改之前用 JSON"] 响应。

关于ruby - 使用不同的参数重复 RSpec 示例组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10861322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com