Merge pull request #491 from mbj/fix/kill-mutations-in-env

Kill mutations in env
This commit is contained in:
Dan Kubb 2015-11-22 09:57:53 -08:00
commit 9001f5e1f5
22 changed files with 95 additions and 141 deletions

View file

@ -1,3 +1,3 @@
---
threshold: 18
total_score: 1222
total_score: 1177

View file

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

View file

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

View file

@ -5,7 +5,7 @@ module Mutant
# Call matcher
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -6,7 +6,7 @@ module Mutant
# Call matcher
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -6,7 +6,7 @@ module Mutant
# Enumerate matches
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -18,7 +18,7 @@ module Mutant
# Matched subjects
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -14,7 +14,7 @@ module Mutant
# Enumerate subjects
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -6,7 +6,7 @@ module Mutant
# Enumerate subjects
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -6,7 +6,7 @@ module Mutant
# Enumerate subjects
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -18,7 +18,7 @@ module Mutant
# Matched subjects
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [Enumerable<Subject>]
#

View file

@ -24,7 +24,7 @@ module Mutant
# Report start
#
# @param [Env] env
# @param [Env::Bootstrap] env
#
# @return [self]
#

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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)
@ -55,16 +61,11 @@ RSpec.describe Mutant::Env::Bootstrap do
describe '#warn' do
let(:object) { described_class.new(config) }
let(:message) { instance_double(String) }
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

View file

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

View file

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

View file

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

View file

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