Merge pull request #799 from mbj/refactor/test-selection

Change test selection to be cached
This commit is contained in:
Markus Schirp 2018-12-04 16:44:37 +00:00 committed by GitHub
commit 71def0d587
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 55 deletions

View file

@ -31,6 +31,16 @@ module Mutant
)
end
# The test selections
#
# @return Hash{Mutation => Enumerable<Test>}
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)

View file

@ -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

View file

@ -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(

View file

@ -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