2015-07-13 69 views
1

我是Ruby和RSpec的新手,做了一点研究,看到有几种方法可以在线发布数据驱动枚举测试,但他们并没有像完整的教程那样涉及很多细节。因此,在我再次详细回顾这些在线文章之前,我想先在这里问一下。使用RSpec构建CSV数据驱动测试的基本简单方法?

下面是我基于使用RSpec的标准简单方法的设置(定义描述&它阻止,不导入RSpec的部分以仅执行期望)。然后,我尝试在数据驱动的能力添加到它:

require 'rspec' 
require 'csv' 

describe "test suite name" do 
    before :all do 
    #this CSV mapping method found online... 
    @device_client = CSV.read path 
    @descriptor = @device_client.shift 
    @descriptor = @descriptor.map { |key| key.to_sym } 
    @device_client.map { |client| Hash[ @descriptor.zip(client) ] } 
    end 

    @device_client.each do |client| 
    describe "#{client[:test_scenario]}" do 
     if "match some CSV field value" 
     it "should run this kind of test" do 
      #additional code as needed 
      expect(some_actual).to eql(some_expected) 
     end 
     end 

     if "match some other CSV field value" 
     it "should run that kind of test" do 
      #additional code as needed 
      expect(some_actual).to eql(some_expected) 
     end 
     end 

     it "some other test common to all CSV rows" do 
     #stuff 
     end 
    end 
    end 

end 

我发现这里是@device_client是零,因为它的结构,现在(有“P @device_client”调试语句来转储内容出来) 。为了使它具有价值,我必须将散列放在它所在的范围内(我通常在另一个描述块内部,但假设我可以跳过额外的描述)。

我该如何重构测试以“读”相同的测试读者,并按照我的意图运行?如果重构意味着我不能使用标准的RSpec格式,并且需要不同的RSpec组件(在线帖子似乎没有遵循简单/基本的RSpec格式),那很好。

我认为我的代码是相当直接的解释。如果不是,则意图是使用CSV输入来动态构建测试。每个CSV行都是具有多个测试的场景 - 一个测试因CSV字段值而异,因此if,其余测试对所有场景都是通用的。我们重复这个集合以获取文件中的许多CSV场景行。在我们处理CSV数据之前,所有块都是全局设置。

在重构中,理想情况下,我想保留描述块(或与它们相当的一些文本描述块),以便在测试结果中显示描述测试的结果,而不仅仅是一堆期望。

回答

2

像这样的东西应该工作:

require 'csv' 

describe "test suite name" do 
    device_client = CSV.read path 
    descriptor = device_client.shift 
    descriptor = descriptor.map { |key| key.to_sym } 
    clients = device_client.map { |client| Hash[ descriptor.zip(client) ] } 

    clients.each do |client| 
    describe "#{client[:test_scenario]}" do 
     if "match some CSV field value" 
     it "should run this kind of test" do 
      #additional code as needed 
      expect(some_actual).to eql(some_expected) 
     end 
     end 

     if "match some other CSV field value" 
     it "should run that kind of test" do 
      #additional code as needed 
      expect(some_actual).to eql(some_expected) 
     end 
     end 

     it "some other test common to all CSV rows" do 
     #stuff 
     end 
    end 
    end 
end 

从您的版本显着的变化:

  • 没有必要要求rspec(当你运行rspec命令的RSpec将负载本身)。
  • 我将CSV逻辑从before(:all)中移出并转入describe正文。您之前所拥有的问题是before挂钩在之后运行所有示例和组都是在执行特定组之前定义的。您需要在规格定义时间期间(在此期间执行describe块)使用CSV文件内容。
  • 我从实例变量切换到局部变量。你以前没有工作,因为before(:all)挂钩在示例组类的实例的上下文中运行,其中describe块在类本身的上下文中运行 - 因此它们运行在不同的上下文中,并且不有权访问相同的实例变量。一旦我们将逻辑移动到describe块中,您就可以使用简单的局部变量。
  • 我将clients =添加到您的before(:all)逻辑的最后一行。你之前所得到的结果是丢掉了device_client.map { ... }的结果,但我假设这就是你想要使用的。

更多关于describe之间的范围差和before块,见section in the rspec-core README that discusses scope

+0

谢谢,感谢您的解答和有见地的信息。 – David