Ruby 将参数传递给rspec共享示例
我有一个返回结果集的过程,我想使用rspec测试结果集的有效性。该过程将根据参数返回不同的结果,但有许多示例对所有这些参数都是通用的,因此我想创建一组通用示例,可以针对所有参数运行 我知道首选的做法是使用let来构建结果。问题是每个过程需要一两分钟才能生成结果,我大概有30个例子。基于不同参数的所有排列,我正在运行大约500个示例。如果我必须为每个示例重建结果,测试将运行一天以上 因此,我在before(:all)块中生成一个结果,并将其指定给如下属性:Ruby 将参数传递给rspec共享示例,ruby,rspec,parameter-passing,Ruby,Rspec,Parameter Passing,我有一个返回结果集的过程,我想使用rspec测试结果集的有效性。该过程将根据参数返回不同的结果,但有许多示例对所有这些参数都是通用的,因此我想创建一组通用示例,可以针对所有参数运行 我知道首选的做法是使用let来构建结果。问题是每个过程需要一两分钟才能生成结果,我大概有30个例子。基于不同参数的所有排列,我正在运行大约500个示例。如果我必须为每个示例重建结果,测试将运行一天以上 因此,我在before(:all)块中生成一个结果,并将其指定给如下属性: RSpec.describe 'Test
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it 'Looks lik a result' do
expect(result.something).to ...
end
it 'Feels lik a result' do
expect(result.something).to ...
end
end
end
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it_behaves_like "A result" result
end
end
shared_examples_for "A result" do |argument|
# some tests with argument
end
it_behaves_like "A result", my_argument
也许有比使用属性更好的方法。我想这样做:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it 'Looks lik a result' do
expect(result.something).to ...
end
it 'Feels lik a result' do
expect(result.something).to ...
end
end
end
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it_behaves_like "A result" result
end
end
shared_examples_for "A result" do |argument|
# some tests with argument
end
it_behaves_like "A result", my_argument
在此上下文中使用属性失败。有其他方法吗?您可以使用
let
let(:result) { build_result({some_parameters}) }
这将创建一个实例变量,您可以在以后的测试中使用它
根据以下文件:
当您必须指定一个变量而不是使用before块
创建一个实例变量,使用let。使用让变量lazy
仅当它在测试中第一次使用并缓存时加载
直到特定测试完成
坏的
describe '#type_id' do
before { @resource = FactoryGirl.create :device }
before { @type = Type.find @resource.type_id }
it 'sets the type_id field' do
expect(@resource.type_id).to equal(@type.id)
end
end
describe '#type_id' do
let(:resource) { FactoryGirl.create :device }
let(:type) { Type.find resource.type_id }
it 'sets the type_id field' do
expect(resource.type_id).to equal(type.id)
end
end
好
describe '#type_id' do
before { @resource = FactoryGirl.create :device }
before { @type = Type.find @resource.type_id }
it 'sets the type_id field' do
expect(@resource.type_id).to equal(@type.id)
end
end
describe '#type_id' do
let(:resource) { FactoryGirl.create :device }
let(:type) { Type.find resource.type_id }
it 'sets the type_id field' do
expect(resource.type_id).to equal(type.id)
end
end
您可以将参数传递给以下共享示例:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it 'Looks lik a result' do
expect(result.something).to ...
end
it 'Feels lik a result' do
expect(result.something).to ...
end
end
end
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it_behaves_like "A result" result
end
end
shared_examples_for "A result" do |argument|
# some tests with argument
end
it_behaves_like "A result", my_argument
然后像这样传入my_参数
:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it 'Looks lik a result' do
expect(result.something).to ...
end
it 'Feels lik a result' do
expect(result.something).to ...
end
end
end
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it_behaves_like "A result" result
end
end
shared_examples_for "A result" do |argument|
# some tests with argument
end
it_behaves_like "A result", my_argument
您可以将所有关于结果的断言组合到一个示例中。这样,let只计算一次
RSpec.describe 'Test Description' do
context 'for params x and y' do
let(:expected_x) { 'x' }
let(:expected_y) { 'y' }
subject { build_result({x: 'x', y: 'y'}) }
specify :aggregate_failures do
expect(subject.x).to eq(expected_x)
expect(subject.y).to eq(expected_y)
end
end
end
这确实违反了“一次测试,一次断言”的指导方针,但如果操作成本非常高,我认为这是一种合理的方法。使用时,每个断言都会有单独的失败,因此您不会错过这一点。如果要将参数传递给共享的示例规范文件,您应该使用
it_behaves_like 'SHARED_EXAMPLE_NAME', { params1: param2, param2: param2 }
您还可以传递参数而不进行散列封装。这取决于您将如何在共享文件中使用该参数。
在我的例子中,我必须使用动态参数调用API
RSpec.shared_examples 'SHARED_EXAMPLE_NAME' do |params = {}|
仅供参考:您不能将工厂数据作为参数传递到共享规范文件中。您必须显式地将工厂调用到共享的\u示例规范文件中。您可以使用块传递参数:
功能“索引页”,js:true-do
上下文“筛选器”do
在{访问(统计数字\路径)}之前
它的行为类似于“选择输入的页面”,%i[create]do
鉴于(:date){date.treaty}
结束
结束
结束
带有选择输入的共享示例页面将接收包含的参数功能,[:创建]
:
shared_examples'页面,带有选择输入'do'功能|
上下文“带结果的表”,js:true-do
鉴于(:已存在的号码){‘号码_1’}
鉴于(:创建的号码){'number_2'}
鉴于(:search_regexp){numb}
场景“您可以选择已存在的号码”,跳过:!功能。包括?(:选择)do
编号选择器。选择编号选项(现有编号)
单击“查找”
期望(第页)有_css('.table tr td',文本:已存在_编号)
结束
场景“您可以使用新名称创建标记”,跳过:!功能。包括?(:创建)do
编号选择器。创建标记(创建编号)
单击“查找”
期望(第页)有_css('.table tr td',文本:created_number)
结束
场景“您可以通过正则表达式搜索”,跳过:!功能。包括?(:regexp)do
数字选择器。选择所有出现的(搜索\u regexp)
单击“查找”
期望(第页)有_css('.table tr td',文本:已存在_编号)
期望(第页)有_css('.table tr td',文本:created_number)
结束
结束
结束
使用let的问题在于,它只在示例期间被缓存。如果我在测试中有10个“it”,那么它将计算let变量的值10次。在我的例子中,我必须为整个上下文构建一次结果,而不是为每个“it”。否则,我的单元测试将运行一天以上,没有人会使用它们。您可以使用来防止这种行为,并在示例之间缓存let
。这不是我所希望的,但这是迄今为止最好的答案。这是您访问此页面时寻找的答案,如果my_参数
是用let
?这行不通。和@gamliela的问题一样。使用let
定义的变量是否可以传递给共享_示例?@gamliela,如果使用let
定义了my_参数
,则无需将其作为参数传递。您只需在共享\u示例中直接使用它即可
@gamliela您可以将factory bot参数作为参数传递,并在示例组中在中让
使用这些参数。