Передача параметров в общий пример rspec
у меня есть процесс, который возвращает результирующий набор, который я хочу проверить на валидность с помощью rspec. Процесс вернет различные результаты на основе параметров, но есть много примеров, которые являются общими для всех из них, поэтому я хотел бы создать набор общих примеров, которые я могу запустить против всех из них.
Я знаю, что предпочтительной практикой является использование в результате. Проблема в том, что каждый процесс занимает минуту или две, чтобы генерировать результат и у меня, наверное, 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
С помощью атрибута в этом контексте не удается. Есть ли другой способ сделать это?
3 ответов
вы можете сгруппировать все ваши утверждения по результату в один пример. Таким образом, 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
это идет вразрез с руководством "один тест, одно утверждение", но если операция очень дорогостоящая, я думаю, что это разумный подход. С :aggregate_failures
вы получите отдельные неудачи для каждого утверждения, поэтому вы не пропустите это.
вы можете передавать аргументы в общие примеры, такие как:
shared_examples_for "A result" do |argument|
# some tests with argument
end
и затем пройти в my_argument
такой:
it_behaves_like "A result", my_argument
можно использовать let
.
let(:result) { build_result({some_parameters}) }
Это создает переменную экземпляра, который вы можете использовать в вашем тесте.
согласно документации на let
,
когда вам нужно назначить переменную вместо использования блока before создайте переменную экземпляра, используйте let. Использование 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