使用 RSpec 基本的简单方法构建 CSV 数据驱动测试?
Structuring a CSV data driven test with RSpec the basic simple way?
我是 Ruby 和 RSpec 的新手,做了一些研究,发现有几种方法可以从在线帖子中进行数据驱动的枚举测试,但他们没有进入很多细节就像一个完整的教程。因此,在我再次详细查看这些在线文章之前,我想先在这里问一下。
这是我根据使用 RSpec 的标准简单方法进行的设置(定义 describe & it 块,不导入 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 是 nil,因为它现在是结构化的(使用 "p @device_client" 语句调试以转储内容)。为了使它具有价值,我必须将散列包含在它在范围内的 it 块中(我通常将其包含在另一个 describe 块中,但假设我可以跳过额外的 describe)。
我如何将测试重构为 "read" 相同(测试的 reader)并按照我想要的方式运行?如果重组意味着我不能使用标准 RSpec 格式并且必须以不同的方式要求 RSpec 组件,那也没关系(网上的帖子似乎没有遵循 simple/basic RSpec格式)。
我认为我的代码解释起来相当简单。如果不是,目的是使用 CSV 输入动态构建测试。每个 CSV 行都是一个具有多个测试的场景 - 1 个测试因 CSV 字段值而异,因此 ifs,其余测试对所有场景都是通用的。我们对文件中的 CSV 场景行重复此设置。而 before all 块是我们处理 CSV 数据之前的全局设置。
在重组中,理想情况下,我想保留 describe & it 文本描述块(或与其等效的部分),以便在测试结果中显示它们描述测试,而不仅仅是一堆期望。
像这样的东西应该可以工作:
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)
在示例组 class 实例的上下文中挂钩 运行s,其中描述块 运行s class 本身的上下文——因此它们 运行 在不同的上下文中并且无法访问相同的实例变量。一旦我们将逻辑移动到 describe
块中,您就可以只使用简单的局部变量。
- 我在您的
before(:all)
逻辑的最后一行添加了 clients =
。您之前拥有的是丢弃 device_client.map { ... }
的结果,但我假设这就是您想要使用的结果。
有关 describe
和 before
块之间范围差异的更多信息,请参阅 section in the rspec-core README that discusses scope。
我是 Ruby 和 RSpec 的新手,做了一些研究,发现有几种方法可以从在线帖子中进行数据驱动的枚举测试,但他们没有进入很多细节就像一个完整的教程。因此,在我再次详细查看这些在线文章之前,我想先在这里问一下。
这是我根据使用 RSpec 的标准简单方法进行的设置(定义 describe & it 块,不导入 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 是 nil,因为它现在是结构化的(使用 "p @device_client" 语句调试以转储内容)。为了使它具有价值,我必须将散列包含在它在范围内的 it 块中(我通常将其包含在另一个 describe 块中,但假设我可以跳过额外的 describe)。
我如何将测试重构为 "read" 相同(测试的 reader)并按照我想要的方式运行?如果重组意味着我不能使用标准 RSpec 格式并且必须以不同的方式要求 RSpec 组件,那也没关系(网上的帖子似乎没有遵循 simple/basic RSpec格式)。
我认为我的代码解释起来相当简单。如果不是,目的是使用 CSV 输入动态构建测试。每个 CSV 行都是一个具有多个测试的场景 - 1 个测试因 CSV 字段值而异,因此 ifs,其余测试对所有场景都是通用的。我们对文件中的 CSV 场景行重复此设置。而 before all 块是我们处理 CSV 数据之前的全局设置。
在重组中,理想情况下,我想保留 describe & it 文本描述块(或与其等效的部分),以便在测试结果中显示它们描述测试,而不仅仅是一堆期望。
像这样的东西应该可以工作:
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)
在示例组 class 实例的上下文中挂钩 运行s,其中描述块 运行s class 本身的上下文——因此它们 运行 在不同的上下文中并且无法访问相同的实例变量。一旦我们将逻辑移动到describe
块中,您就可以只使用简单的局部变量。 - 我在您的
before(:all)
逻辑的最后一行添加了clients =
。您之前拥有的是丢弃device_client.map { ... }
的结果,但我假设这就是您想要使用的结果。
有关 describe
和 before
块之间范围差异的更多信息,请参阅 section in the rspec-core README that discusses scope。