From ca69384e07463c7dfa47494700e834569fb7833b Mon Sep 17 00:00:00 2001 From: Markus Schirp Date: Tue, 4 Dec 2018 16:32:53 +0000 Subject: [PATCH] Change test selection to be cached --- lib/mutant/env.rb | 12 ++++- lib/mutant/runner/sink.rb | 2 +- spec/support/shared_context.rb | 31 ++++++++---- spec/unit/mutant/env_spec.rb | 92 ++++++++++++++++++---------------- 4 files changed, 82 insertions(+), 55 deletions(-) diff --git a/lib/mutant/env.rb b/lib/mutant/env.rb index 6dc2e7ea..a66859c5 100644 --- a/lib/mutant/env.rb +++ b/lib/mutant/env.rb @@ -31,6 +31,16 @@ module Mutant ) end + # The test selections + # + # @return Hash{Mutation => Enumerable} + def selections + subjects.map do |subject| + [subject, selector.call(subject)] + end.to_h + end + memoize :selections + private # Kill mutation under isolation with integration @@ -43,7 +53,7 @@ module Mutant # rubocop:disable MethodLength def run_mutation_tests(mutation) start = Timer.now - tests = selector.call(mutation.subject) + tests = selections.fetch(mutation.subject) config.isolation.call do mutation.insert(config.kernel) diff --git a/lib/mutant/runner/sink.rb b/lib/mutant/runner/sink.rb index 041c00df..de5ea4d7 100644 --- a/lib/mutant/runner/sink.rb +++ b/lib/mutant/runner/sink.rb @@ -43,7 +43,7 @@ module Mutant @subject_results[subject] = Result::Subject.new( subject: subject, mutation_results: previous_mutation_results(subject) + [mutation_result], - tests: mutation_result.test_result.tests + tests: env.selections.fetch(subject) ) self diff --git a/spec/support/shared_context.rb b/spec/support/shared_context.rb index 450455d8..9ff6d636 100644 --- a/spec/support/shared_context.rb +++ b/spec/support/shared_context.rb @@ -36,17 +36,26 @@ module SharedContext # rubocop:disable MethodLength # rubocop:disable AbcSize def setup_shared_context - let(:env) { instance_double(Mutant::Env, config: config, subjects: [subject_a], mutations: mutations) } - let(:job_a) { Mutant::Parallel::Job.new(index: 0, payload: mutation_a) } - let(:job_b) { Mutant::Parallel::Job.new(index: 1, payload: mutation_b) } - let(:test_a) { instance_double(Mutant::Test, identification: 'test-a') } - let(:output) { StringIO.new } - let(:mutations) { [mutation_a, mutation_b] } - let(:mutation_a_node) { s(:false) } - let(:mutation_b_node) { s(:nil) } - let(:mutation_b) { Mutant::Mutation::Evil.new(subject_a, mutation_b_node) } - let(:mutation_a) { Mutant::Mutation::Evil.new(subject_a, mutation_a_node) } - let(:subject_a_node) { s(:true) } + let(:job_a) { Mutant::Parallel::Job.new(index: 0, payload: mutation_a) } + let(:job_b) { Mutant::Parallel::Job.new(index: 1, payload: mutation_b) } + let(:mutation_a) { Mutant::Mutation::Evil.new(subject_a, mutation_a_node) } + let(:mutation_a_node) { s(:false) } + let(:mutation_b) { Mutant::Mutation::Evil.new(subject_a, mutation_b_node) } + let(:mutation_b_node) { s(:nil) } + let(:mutations) { [mutation_a, mutation_b] } + let(:output) { StringIO.new } + let(:subject_a_node) { s(:true) } + let(:test_a) { instance_double(Mutant::Test, identification: 'test-a') } + + let(:env) do + instance_double( + Mutant::Env, + config: config, + mutations: mutations, + selections: { subject_a => [test_a] }, + subjects: [subject_a] + ) + end let(:status) do Mutant::Parallel::Status.new( diff --git a/spec/unit/mutant/env_spec.rb b/spec/unit/mutant/env_spec.rb index 2eda2984..54e7cd90 100644 --- a/spec/unit/mutant/env_spec.rb +++ b/spec/unit/mutant/env_spec.rb @@ -1,44 +1,52 @@ # frozen_string_literal: true RSpec.describe Mutant::Env do - context '#kill' do - let(:object) do - described_class.new( - actor_env: Mutant::Actor::Env.new(Thread), - config: config, - integration: integration, - matchable_scopes: [], - mutations: [], - selector: selector, - subjects: [], - parser: Mutant::Parser.new - ) - end + let(:object) do + described_class.new( + actor_env: Mutant::Actor::Env.new(Thread), + config: config, + integration: integration, + matchable_scopes: [], + mutations: [], + selector: selector, + subjects: [mutation_subject], + parser: Mutant::Parser.new + ) + end - let(:integration) { instance_double(Mutant::Integration) } - let(:test_a) { instance_double(Mutant::Test) } - let(:test_b) { instance_double(Mutant::Test) } - let(:tests) { [test_a, test_b] } - let(:selector) { instance_double(Mutant::Selector) } - let(:integration_class) { Mutant::Integration::Null } - let(:isolation) { instance_double(Mutant::Isolation::Fork) } - let(:mutation_subject) { instance_double(Mutant::Subject) } + let(:integration) { instance_double(Mutant::Integration) } + let(:test_a) { instance_double(Mutant::Test) } + let(:test_b) { instance_double(Mutant::Test) } + let(:tests) { [test_a, test_b] } + let(:selector) { instance_double(Mutant::Selector) } + let(:integration_class) { Mutant::Integration::Null } + let(:isolation) { instance_double(Mutant::Isolation::Fork) } + let(:mutation_subject) { instance_double(Mutant::Subject) } - let(:mutation) do - instance_double( - Mutant::Mutation, - subject: mutation_subject - ) - end + let(:mutation) do + instance_double( + Mutant::Mutation, + subject: mutation_subject + ) + end - let(:config) do - Mutant::Config::DEFAULT.with( - isolation: isolation, - integration: integration_class, - kernel: class_double(Kernel) - ) - end + let(:config) do + Mutant::Config::DEFAULT.with( + isolation: isolation, + integration: integration_class, + kernel: class_double(Kernel) + ) + end + before do + expect(selector).to receive(:call) + .with(mutation_subject) + .and_return(tests) + + allow(Mutant::Timer).to receive(:now).and_return(2.0, 3.0) + end + + describe '#kill' do subject { object.kill(mutation) } shared_examples_for 'mutation kill' do @@ -52,14 +60,6 @@ RSpec.describe Mutant::Env do end end - before do - expect(selector).to receive(:call) - .with(mutation_subject) - .and_return(tests) - - allow(Mutant::Timer).to receive(:now).and_return(2.0, 3.0) - end - context 'when isolation does not raise error' do let(:test_result) { instance_double(Mutant::Result::Test) } @@ -99,4 +99,12 @@ RSpec.describe Mutant::Env do include_examples 'mutation kill' end end + + describe '#selections' do + subject { object.selections } + + it 'returns expected selections' do + expect(subject).to eql(mutation_subject => tests) + end + end end