Merge pull request #491 from mbj/fix/kill-mutations-in-env
Kill mutations in env
This commit is contained in:
commit
9001f5e1f5
22 changed files with 95 additions and 141 deletions
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
threshold: 18
|
||||
total_score: 1222
|
||||
total_score: 1177
|
||||
|
|
|
@ -168,7 +168,6 @@ require 'mutant/runner/sink'
|
|||
require 'mutant/result'
|
||||
require 'mutant/reporter'
|
||||
require 'mutant/reporter/null'
|
||||
require 'mutant/reporter/trace'
|
||||
require 'mutant/reporter/cli'
|
||||
require 'mutant/reporter/cli/printer'
|
||||
require 'mutant/reporter/cli/printer/config'
|
||||
|
|
|
@ -16,18 +16,6 @@ module Mutant
|
|||
"Fix your lib to follow normal ruby semantics!\n" \
|
||||
'{Module,Class}#name should return resolvable constant name as String or nil'.freeze
|
||||
|
||||
# Print warning message
|
||||
#
|
||||
# @param [String]
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
def warn(message)
|
||||
config.reporter.warn(message)
|
||||
self
|
||||
end
|
||||
|
||||
# Kill mutation
|
||||
#
|
||||
# @param [Mutation] mutation
|
||||
|
|
|
@ -5,7 +5,7 @@ module Mutant
|
|||
|
||||
# Call matcher
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -6,7 +6,7 @@ module Mutant
|
|||
|
||||
# Call matcher
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -6,7 +6,7 @@ module Mutant
|
|||
|
||||
# Enumerate matches
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -18,7 +18,7 @@ module Mutant
|
|||
|
||||
# Matched subjects
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -14,7 +14,7 @@ module Mutant
|
|||
|
||||
# Enumerate subjects
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -6,7 +6,7 @@ module Mutant
|
|||
|
||||
# Enumerate subjects
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -6,7 +6,7 @@ module Mutant
|
|||
|
||||
# Enumerate subjects
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -18,7 +18,7 @@ module Mutant
|
|||
|
||||
# Matched subjects
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [Enumerable<Subject>]
|
||||
#
|
||||
|
|
|
@ -24,7 +24,7 @@ module Mutant
|
|||
|
||||
# Report start
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
|
|
|
@ -7,7 +7,7 @@ module Mutant
|
|||
|
||||
# Start representation
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [String]
|
||||
#
|
||||
|
@ -116,7 +116,7 @@ module Mutant
|
|||
|
||||
# Format start
|
||||
#
|
||||
# @param [Env] env
|
||||
# @param [Env::Bootstrap] env
|
||||
#
|
||||
# @return [String]
|
||||
#
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
module Mutant
|
||||
class Reporter
|
||||
# Reporter to trace report calls, used as a spec adapter
|
||||
class Trace
|
||||
include Adamantium::Mutable, Anima.new(:start_calls, :progress_calls, :report_calls, :warn_calls)
|
||||
|
||||
# New trace reporter
|
||||
#
|
||||
# @return [Trace]
|
||||
#
|
||||
# @api private
|
||||
def self.new
|
||||
super(Hash[anima.attribute_names.map { |name| [name, []] }])
|
||||
end
|
||||
|
||||
%w[start progress report warn].each do |name|
|
||||
define_method(name) do |object|
|
||||
public_send(:"#{name}_calls") << object
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
REPORT_DELAY = 0.0
|
||||
|
||||
# Report delay
|
||||
#
|
||||
# @return [Float]
|
||||
#
|
||||
# @api private
|
||||
def delay
|
||||
REPORT_DELAY
|
||||
end
|
||||
|
||||
end # Tracker
|
||||
end # reporter
|
||||
end # Mutant
|
|
@ -33,13 +33,13 @@ RSpec.shared_examples_for 'a method matcher' do
|
|||
end
|
||||
|
||||
RSpec.shared_examples_for 'skipped candidate' do
|
||||
before do
|
||||
expected_warnings.each do |warning|
|
||||
expect(env).to receive(:warn).with(warning).and_return(env)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not emit matcher' do
|
||||
expect(subject).to eql([])
|
||||
end
|
||||
|
||||
it 'does warn' do
|
||||
subject
|
||||
|
||||
expect(env.config.reporter.warn_calls).to eql(expected_warnings)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,7 +33,7 @@ $LOAD_PATH << File.join(TestApp.root, 'lib')
|
|||
require 'test_app'
|
||||
|
||||
module Fixtures
|
||||
TEST_CONFIG = Mutant::Config::DEFAULT.with(reporter: Mutant::Reporter::Trace.new)
|
||||
TEST_CONFIG = Mutant::Config::DEFAULT.with(reporter: Mutant::Reporter::Null.new)
|
||||
TEST_ENV = Mutant::Env::Bootstrap.(TEST_CONFIG)
|
||||
end # Fixtures
|
||||
|
||||
|
@ -42,12 +42,6 @@ module ParserHelper
|
|||
Unparser.unparse(node)
|
||||
end
|
||||
|
||||
def test_env
|
||||
Fixtures::TEST_ENV.with(
|
||||
config: Mutant::Config::DEFAULT.with(reporter: Mutant::Reporter::Trace.new)
|
||||
)
|
||||
end
|
||||
|
||||
def parse(string)
|
||||
Unparser::Preprocessor.run(Parser::CurrentRuby.parse(string))
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ module SharedContext
|
|||
let(:config) do
|
||||
Mutant::Config::DEFAULT.with(
|
||||
jobs: 1,
|
||||
reporter: Mutant::Reporter::Trace.new
|
||||
reporter: Mutant::Reporter::Null.new
|
||||
)
|
||||
end
|
||||
|
||||
|
|
55
spec/unit/mutant/env/boostrap_spec.rb
vendored
55
spec/unit/mutant/env/boostrap_spec.rb
vendored
|
@ -16,7 +16,7 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
let(:config) do
|
||||
Mutant::Config::DEFAULT.with(
|
||||
jobs: 1,
|
||||
reporter: Mutant::Reporter::Trace.new,
|
||||
reporter: instance_double(Mutant::Reporter),
|
||||
includes: [],
|
||||
requires: [],
|
||||
integration: integration_class,
|
||||
|
@ -41,12 +41,18 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
it { should eql(expected_env) }
|
||||
end
|
||||
|
||||
def expect_warning
|
||||
expect(config.reporter).to receive(:warn)
|
||||
.with(expected_warning)
|
||||
.and_return(config.reporter)
|
||||
end
|
||||
|
||||
before do
|
||||
expect(integration_class).to receive(:new)
|
||||
.with(config)
|
||||
.and_return(integration)
|
||||
|
||||
expect(integration).to receive(:setup).and_return(integration)
|
||||
expect(integration).to receive_messages(setup: integration)
|
||||
|
||||
expect(ObjectSpace).to receive(:each_object)
|
||||
.with(Module)
|
||||
|
@ -54,17 +60,12 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
end
|
||||
|
||||
describe '#warn' do
|
||||
let(:object) { described_class.new(config) }
|
||||
let(:message) { instance_double(String) }
|
||||
let(:object) { described_class.new(config) }
|
||||
let(:expected_warning) { instance_double(String) }
|
||||
|
||||
subject { object.warn(message) }
|
||||
subject { object.warn(expected_warning) }
|
||||
|
||||
it 'reports a warning' do
|
||||
expect { subject }
|
||||
.to change { config.reporter.warn_calls }
|
||||
.from([])
|
||||
.to([message])
|
||||
end
|
||||
before { expect_warning }
|
||||
|
||||
it_behaves_like 'a command method'
|
||||
end
|
||||
|
@ -75,6 +76,11 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
context 'when Module#name calls result in exceptions' do
|
||||
let(:object_space_modules) { [invalid_class] }
|
||||
|
||||
let(:expected_warning) do
|
||||
"Class#name from: #{invalid_class} raised an error: " \
|
||||
"RuntimeError. #{Mutant::Env::SEMANTICS_MESSAGE}"
|
||||
end
|
||||
|
||||
let(:invalid_class) do
|
||||
Class.new do
|
||||
def self.name
|
||||
|
@ -92,17 +98,7 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
end
|
||||
end
|
||||
|
||||
it 'warns via reporter' do
|
||||
expected_warnings = [
|
||||
"Class#name from: #{invalid_class} raised an error: " \
|
||||
"RuntimeError. #{Mutant::Env::SEMANTICS_MESSAGE}"
|
||||
]
|
||||
|
||||
expect { subject }
|
||||
.to change { config.reporter.warn_calls }
|
||||
.from([])
|
||||
.to(expected_warnings)
|
||||
end
|
||||
before { expect_warning }
|
||||
|
||||
include_examples 'bootstrap call'
|
||||
end
|
||||
|
@ -146,6 +142,11 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
end
|
||||
end
|
||||
|
||||
let(:expected_warning) do
|
||||
"Class#name from: #{invalid_class} " \
|
||||
"returned Object. #{Mutant::Env::SEMANTICS_MESSAGE}"
|
||||
end
|
||||
|
||||
after do
|
||||
# Fix Class#name so other specs do not see this one
|
||||
class << invalid_class
|
||||
|
@ -155,15 +156,7 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|||
end
|
||||
end
|
||||
|
||||
it 'warns via reporter' do
|
||||
expected_warnings = [
|
||||
"Class#name from: #{invalid_class.inspect} returned Object. #{Mutant::Env::SEMANTICS_MESSAGE}"
|
||||
]
|
||||
|
||||
expect { subject }
|
||||
.to change { config.reporter.warn_calls }
|
||||
.from([]).to(expected_warnings)
|
||||
end
|
||||
before { expect_warning }
|
||||
|
||||
include_examples 'bootstrap call'
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ RSpec.describe Mutant::Env do
|
|||
)
|
||||
end
|
||||
|
||||
let(:integration) { integration_class.new(config) }
|
||||
let(:integration) { instance_double(Mutant::Integration) }
|
||||
|
||||
let(:config) do
|
||||
Mutant::Config::DEFAULT.with(isolation: isolation, integration: integration_class)
|
||||
|
@ -45,18 +45,38 @@ RSpec.describe Mutant::Env do
|
|||
end
|
||||
|
||||
before do
|
||||
expect(selector).to receive(:call).with(mutation_subject).and_return(tests)
|
||||
allow(Time).to receive(:now).and_return(Time.at(0))
|
||||
expect(selector).to receive(:call)
|
||||
.with(mutation_subject)
|
||||
.and_return(tests)
|
||||
|
||||
allow(Time).to receive_messages(now: Time.at(0))
|
||||
end
|
||||
|
||||
context 'when isolation does not raise error' do
|
||||
let(:test_result) { instance_double(Mutant::Result::Test, passed: false) }
|
||||
|
||||
before do
|
||||
expect(isolation).to receive(:call).and_yield.and_return(test_result)
|
||||
expect(mutation_subject).to receive(:prepare).and_return(mutation_subject).ordered
|
||||
expect(context).to receive(:root).with(s(:nil)).and_return(wrapped_node).ordered
|
||||
expect(Mutant::Loader::Eval).to receive(:call).with(wrapped_node, mutation_subject).and_return(nil).ordered
|
||||
expect(isolation).to receive(:call)
|
||||
.ordered
|
||||
.and_yield
|
||||
|
||||
expect(mutation_subject).to receive(:prepare)
|
||||
.ordered
|
||||
.and_return(mutation_subject)
|
||||
|
||||
expect(context).to receive(:root)
|
||||
.with(s(:nil))
|
||||
.and_return(wrapped_node)
|
||||
|
||||
expect(Mutant::Loader::Eval).to receive(:call)
|
||||
.ordered
|
||||
.with(wrapped_node, mutation_subject)
|
||||
.and_return(Mutant::Loader::Eval)
|
||||
|
||||
expect(integration).to receive(:call)
|
||||
.ordered
|
||||
.with(tests)
|
||||
.and_return(test_result)
|
||||
end
|
||||
|
||||
include_examples 'mutation kill'
|
||||
|
@ -64,10 +84,18 @@ RSpec.describe Mutant::Env do
|
|||
|
||||
context 'when isolation does raise error' do
|
||||
before do
|
||||
expect(isolation).to receive(:call).and_raise(Mutant::Isolation::Error, 'test-error')
|
||||
expect(isolation).to receive(:call)
|
||||
.and_raise(Mutant::Isolation::Error, 'test-error')
|
||||
end
|
||||
|
||||
let(:test_result) { Mutant::Result::Test.new(tests: tests, output: 'test-error', passed: false, runtime: 0.0) }
|
||||
let(:test_result) do
|
||||
Mutant::Result::Test.new(
|
||||
tests: tests,
|
||||
output: 'test-error',
|
||||
passed: false,
|
||||
runtime: 0.0
|
||||
)
|
||||
end
|
||||
|
||||
include_examples 'mutation kill'
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@ RSpec.describe Mutant::Matcher::Method::Instance, '#call' do
|
|||
subject { object.call(env) }
|
||||
|
||||
let(:object) { described_class.new(scope, method) }
|
||||
let(:env) { test_env }
|
||||
let(:method_name) { :foo }
|
||||
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
||||
let(:method) { scope.instance_method(method_name) }
|
||||
|
@ -11,6 +10,13 @@ RSpec.describe Mutant::Matcher::Method::Instance, '#call' do
|
|||
let(:method_arity) { 0 }
|
||||
let(:base) { TestApp::InstanceMethodTests }
|
||||
|
||||
let(:env) do
|
||||
instance_double(
|
||||
Mutant::Env::Bootstrap,
|
||||
parser: Fixtures::TEST_ENV.parser
|
||||
)
|
||||
end
|
||||
|
||||
def name
|
||||
node.children.fetch(0)
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#call' do
|
|||
subject { object.call(env) }
|
||||
|
||||
let(:object) { described_class.new(scope, method) }
|
||||
let(:env) { test_env }
|
||||
let(:method) { scope.method(method_name) }
|
||||
let(:type) { :defs }
|
||||
let(:method_name) { :foo }
|
||||
|
@ -10,6 +9,13 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#call' do
|
|||
let(:base) { TestApp::SingletonMethodTests }
|
||||
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
||||
|
||||
let(:env) do
|
||||
instance_double(
|
||||
Mutant::Env::Bootstrap,
|
||||
parser: Fixtures::TEST_ENV.parser
|
||||
)
|
||||
end
|
||||
|
||||
def name
|
||||
node.children.fetch(1)
|
||||
end
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
RSpec.describe Mutant::Reporter::Trace do
|
||||
let(:object) { described_class.new }
|
||||
|
||||
describe '#delay' do
|
||||
subject { object.delay }
|
||||
|
||||
it { should eql(0.0) }
|
||||
end
|
||||
|
||||
let(:value) { instance_double(Object) }
|
||||
|
||||
%i[report start progress].each do |name|
|
||||
describe "##{name}" do
|
||||
subject { object.public_send(name, value) }
|
||||
|
||||
it 'logs the value' do
|
||||
expect { subject }
|
||||
.to change { object.public_send("#{name}_calls") }
|
||||
.from([])
|
||||
.to([value])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue