我有一个进程返回一个结果集,我希望使用rspec测试其有效性。该过程将根据参数返回不同的结果,但有许多示例对所有这些都是通用的,所以我想创建一组可以对所有这些示例运行的常见示例。
我知道首选做法是使用let来构建结果。问题是每个过程需要一两分钟来生成结果,我可能有30个例子。基于不同参数的所有排列,我运行了大约500个示例。如果我必须重建每个示例的结果,那么测试将运行超过一天。
所以相反,我在before(:all)块中构建一个结果,并将它分配给这样的属性:
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
在此上下文中使用属性失败。有没有不同的方法来做到这一点?
答案 0 :(得分:53)
您可以将参数传递给共享示例,如下所示:
my_argument
然后像这样传递it_behaves_like "A result", my_argument
:
ZoneId z = ZoneId.of( “America/Montreal” );
LocalDate today = LocalDate.now( z );
答案 1 :(得分:0)
您可以使用let
。
let(:result) { build_result({some_parameters}) }
这将创建一个您可以在以后的测试中使用的实例变量。
根据let
,
当您必须分配变量而不是使用before块时 创建一个实例变量,使用let。使用让变量懒惰 仅在测试中第一次使用并加载缓存时才加载 直到特定测试结束。
<强> BAD 强>
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
答案 2 :(得分:0)
您可以将结果中的所有断言分组到一个示例中。这样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
它确实违背了&#34;一个测试,一个断言&#34;指南,但如果操作成本很高,我认为这是一种合理的方法。使用:aggregate_failures
,每个断言都会出现单独的失败,因此您不会错过这个失败。
答案 3 :(得分:0)
如果要将参数传递给shared_example规范文件,则应使用
it_behaves_like 'SHARED_EXAMPLE_NAME', { params1: param2, param2: param2 }
您还可以传递参数而无需散列封装。这取决于您如何在共享文件中利用该参数。 就我而言,我必须使用动态参数来调用API。
RSpec.shared_examples 'SHARED_EXAMPLE_NAME' do |params = {}|
仅供参考::您不能将 Factory 数据作为参数传递给shared_example规范文件。您必须将工厂显式调用到shared_example规范文件中。
答案 4 :(得分:0)
您可以使用块传递参数:
feature 'Index page', js: true do
context 'Filter' do
before { visit(statistics_numbers_path) }
it_behaves_like 'Page with select input', %i[create] do
given!(:date) { Date.yesterday }
end
end
end
共享示例 Page with select input
将接收包含 features
的参数 [:create]
:
shared_examples 'Page with select input' do |features|
context 'Table with results', js: true do
given!(:existed_number) { 'number_1' }
given!(:created_number) { 'number_2' }
given!(:search_regexp) { 'numb' }
scenario 'You can select existed numbers', skip: !features.include?(:select) do
number_selector.choose_option(existed_number)
click_on 'Find'
expect(page).to have_css('.table tr td', text: existed_number)
end
scenario 'You can create tags with new names', skip: !features.include?(:create) do
number_selector.create_tag(created_number)
click_on 'Find'
expect(page).to have_css('.table tr td', text: created_number)
end
scenario 'You can search by regular expression', skip: !features.include?(:regexp) do
number_selector.choose_all_occurrences_of(search_regexp)
click_on 'Find'
expect(page).to have_css('.table tr td', text: existed_number)
expect(page).to have_css('.table tr td', text: created_number)
end
end
end