ruby – 使用不同的参数重复RSpec示例组
我正在尝试保持我的规格清洁和干燥,但我对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中描述的调用没有记录到RSpec输出(当使用文档格式输出时),虽然内部的示例会重复并按预期使用版本块参数.本质上,该上下文级别丢失(重复描述块的外部和内部的描述块被保留). 如果需要,在a gist中有更详细的示例代码.关于为什么这不太正常的任何线索? 解决方法
所以(道歉,如果我重复你已经知道的东西),但每次调用describe / context时,rspec都会创建一个新类,它是当前示例组类的子类(最终是RSpec :: Core :: ExampleGroup的子类)然后使用module_eval来评估该类上下文中的块.如果我跑
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> 当你调用它时,rspec创建一个Example对象并将它附加到self上的类实例变量(当前示例组). rspec还会在示例的元数据中粘贴当前示例组,向上走这个示例组树就可以获得示例的完整描述. 您的重复描述方法调用描述,因此,当您调用example_group_block.call项时,self确实是新创建的示例组.当proc被评估时,它当然会记住self被调用时的值是什么,因此你对它的调用是在重复_decribe时最新的示例组(通过调用一些调用来检查自我的值,可以轻松验证)你的代码).类似地,对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查询API [v1]用JSON响应”,“foo查询API [v2]用JSON响应”]而不是[“foo用JSON响应”,“foo用JSON响应”]在更改之前. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |