diff --git a/lib/inferno/test_runner.rb b/lib/inferno/test_runner.rb index 4d3258047..c92be9e78 100644 --- a/lib/inferno/test_runner.rb +++ b/lib/inferno/test_runner.rb @@ -59,44 +59,56 @@ def existing_test_result(runnable) end def run_test(test, scratch) - inputs = load_inputs(test) - input_json_string = inputs_as_json(test, inputs) - - test_instance = - test.new( - inputs:, - test_session_id: test_session.id, - scratch:, - suite_options: test_session.suite_options_hash - ) + around_test(test) do + inputs = load_inputs(test) + input_json_string = inputs_as_json(test, inputs) - result = evaluate_runnable_result(test, test_instance, inputs) + test_instance = + test.new( + inputs:, + test_session_id: test_session.id, + scratch:, + suite_options: test_session.suite_options_hash + ) - outputs = save_outputs(test_instance) - output_json_string = JSON.generate(outputs) + result = evaluate_runnable_result(test, test_instance, inputs) - if result == 'wait' - test_runs_repo.mark_as_waiting(test_run.id, test_instance.identifier, test_instance.wait_timeout) - end + outputs = save_outputs(test_instance) + output_json_string = JSON.generate(outputs) - test_result = persist_result( - { - messages: test_instance.messages, - requests: test_instance.requests, - result:, - result_message: test_instance.result_message, - input_json: input_json_string, - output_json: output_json_string - }.merge(test.reference_hash) - ) + if result == 'wait' + test_runs_repo.mark_as_waiting(test_run.id, test_instance.identifier, test_instance.wait_timeout) + end - # If running a single test, update its parents' results. If running a - # group or suite, #run_group handles updating the parents. - return test_result if test_run.test_id.blank? + test_result = persist_result( + { + messages: test_instance.messages, + requests: test_instance.requests, + result:, + result_message: test_instance.result_message, + input_json: input_json_string, + output_json: output_json_string + }.merge(test.reference_hash) + ) - update_parent_result(test.parent) + # If running a single test, update its parents' results. If running a + # group or suite, #run_group handles updating the parents. + update_parent_result(test.parent) if test_run.test_id.present? - test_result + test_result + end + end + + # Wraps the execution of a single test. Override or prepend this method to run + # instrumentation around each test, for example to emit a distinct trace, span, + # or timing metric per test instead of one that spans the whole run. The default + # implementation just yields. + # + # @param test [Class] the test being run (an Inferno::Entities::Test subclass) + # @yield executes the test and returns its result + # @return the value returned by the block + def around_test(_test) + yield end def check_inputs(test, _test_instance, inputs) diff --git a/spec/inferno/test_runner_spec.rb b/spec/inferno/test_runner_spec.rb index 3b384c7e9..b01ed30b7 100644 --- a/spec/inferno/test_runner_spec.rb +++ b/spec/inferno/test_runner_spec.rb @@ -93,6 +93,35 @@ def error_results_message(error_results) expect(output['type']).to be_present end end + + it 'wraps each test with #around_test' do + wrapped = [] + allow(runner).to receive(:around_test).and_wrap_original do |_original, test, &block| + wrapped << test + block.call + end + + results = runner.start + test_results = results.select { |result| result.runnable < Inferno::Entities::Test } + + expect(wrapped).to_not be_empty + expect(wrapped).to all(be < Inferno::Entities::Test) + expect(wrapped.length).to eq(test_results.length) + end + end + + describe '#around_test' do + let(:test_run) do + repo_create(:test_run, runnable: { test_group_id: 'demo-simple_group' }, test_session_id: test_session.id) + end + + it 'yields by default' do + expect { |block| runner.around_test(nil, &block) }.to yield_control + end + + it 'returns the value of the block by default' do + expect(runner.around_test(nil) { :test_result }).to eq(:test_result) + end end describe 'when running wait group' do