Merge pull request #376 from mbj/fix/refactor-matcher-config

Refactor matcher config
This commit is contained in:
Dan Kubb 2015-07-10 12:20:43 -07:00
commit 5ff5936ff6
13 changed files with 123 additions and 119 deletions

View file

@ -1,3 +1,3 @@
---
threshold: 18
total_score: 1185
total_score: 1178

View file

@ -153,7 +153,7 @@ module Mutant
# @api private
def add_filter_options(opts)
opts.on('--ignore-subject PATTERN', 'Ignore subjects that match PATTERN') do |pattern|
add_matcher(:subject_ignores, config.expression_parser.(pattern))
add_matcher(:ignore_expressions, config.expression_parser.(pattern))
end
end

View file

@ -13,7 +13,7 @@ module Mutant
def result
Filter.new(
Chain.build(config.match_expressions.map(&method(:matcher))),
predicate
ignored_subjects
)
end
@ -34,60 +34,23 @@ module Mutant
private
# Predicate constraining matches
# Predicate returning false on ignored subject
#
# @return [#call]
#
# rubocop:disable MethodLength
#
# @api private
def predicate
if subject_selector && subject_rejector
Morpher::Evaluator::Predicate::Boolean::And.new([
subject_selector,
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
])
elsif subject_selector
subject_selector
elsif subject_rejector
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
def ignored_subjects
rejectors = config.ignore_expressions.map(&SubjectPrefix.method(:new))
if rejectors.any?
Morpher::Evaluator::Predicate::Boolean::Negation.new(
Morpher::Evaluator::Predicate::Boolean::Or.new(rejectors)
)
else
Morpher::Evaluator::Predicate::Tautology.new
end
end
# the subject selector predicate
#
# @return [#call]
# if selector is present
#
# @return [nil]
# otherwise
#
# @api private
def subject_selector
selectors = config.subject_selects.map do |attribute, value|
Morpher.compile(s(:eql, s(:attribute, attribute), s(:static, value)))
end
Morpher::Evaluator::Predicate::Boolean::Or.new(selectors) if selectors.any?
end
# Subject rejector predicate
#
# @return [#call]
# if there is a subject rejector
#
# @return [nil]
# otherwise
#
# @api private
def subject_rejector
rejectors = config.subject_ignores.map(&SubjectPrefix.method(:new))
Morpher::Evaluator::Predicate::Boolean::Or.new(rejectors) if rejectors.any?
end
# Matcher for expression on env
#
# @param [Mutant::Expression] expression

View file

@ -1,15 +1,31 @@
module Mutant
class Matcher
# Match configuration
# Subject matcher configuration
class Config
include Adamantium, Anima::Update, Anima.new(
:match_expressions,
:subject_ignores,
:subject_selects
:ignore_expressions
)
INSPECT_FORMAT = "#<#{self} %s>".freeze
ATTRIBUTE_DELIMITER = ' '.freeze
ATTRIBUTE_FORMAT = '%s: [%s]'.freeze
ENUM_DELIMITER = ','.freeze
EMPTY_ATTRIBUTES = 'empty'.freeze
private_constant(*constants(false))
DEFAULT = new(Hash[anima.attribute_names.map { |name| [name, []] }])
# Inspection string
#
# @return [String]
#
# @api private
def inspect
INSPECT_FORMAT % inspect_attributes
end
memoize :inspect
# Add value to configurable collection
#
# @param [Symbol] attribute
@ -22,6 +38,43 @@ module Mutant
update(attribute => public_send(attribute).dup << value)
end
private
# Present attributes
#
# @return [Array<Symbol>]
#
# @api private
def present_attributes
to_h.reject { |_key, value| value.empty? }.keys
end
# Formatted attributes
#
# @return [String]
#
# @api private
def inspect_attributes
attributes = present_attributes
.map(&method(:format_attribute))
.join(ATTRIBUTE_DELIMITER)
attributes.empty? ? EMPTY_ATTRIBUTES : attributes
end
# Format attribute
#
# @param [Symbol] attribute_name
#
# @return [String]
def format_attribute(attribute_name)
ATTRIBUTE_FORMAT %
[
attribute_name,
public_send(attribute_name).map(&:syntax).join(ENUM_DELIMITER)
]
end
end # Config
end # Matcher
end # Mutant

View file

@ -11,13 +11,11 @@ module Mutant
#
# @return [undefined]
#
# rubocop:disable AbcSize
#
# @api private
def run
info 'Mutant configuration:'
info 'Matcher: %s', object.matcher.inspect
info 'Integration: %s', object.integration.name
info 'Integration: %s', object.integration
info 'Expect Coverage: %0.2f%%', (object.expected_coverage * 100)
info 'Jobs: %d', object.jobs
info 'Includes: %s', object.includes

View file

@ -234,7 +234,7 @@ Options:
let(:flags) { %w[--ignore-subject Foo::Bar] }
let(:expected_matcher_config) do
default_matcher_config.update(subject_ignores: [parse_expression('Foo::Bar')])
default_matcher_config.update(ignore_expressions: [parse_expression('Foo::Bar')])
end
it_should_behave_like 'a cli parser'

View file

@ -41,11 +41,11 @@ RSpec.describe Mutant::Matcher::Compiler do
it { should eql(expected_matcher) }
end
context 'and a subject filter' do
context 'and a subject ignore' do
let(:attributes) do
{
match_expressions: [expression_a],
subject_ignores: [expression_b]
match_expressions: [expression_a],
ignore_expressions: [expression_b]
}
end
@ -61,52 +61,6 @@ RSpec.describe Mutant::Matcher::Compiler do
it { should eql(expected_matcher) }
end
context 'and an attribute filter' do
let(:attributes) do
{
match_expressions: [expression_a],
subject_selects: [[:code, 'foo']]
}
end
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a]) }
let(:expected_predicate) do
Morpher::Evaluator::Predicate::Boolean::Or.new([
Morpher.compile(s(:eql, s(:attribute, :code), s(:static, 'foo')))
])
end
it { should eql(expected_matcher) }
end
context 'and subject and attribute filter' do
let(:attributes) do
{
match_expressions: [expression_a],
subject_ignores: [expression_b],
subject_selects: [[:code, 'foo']]
}
end
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a]) }
let(:expected_predicate) do
Morpher::Evaluator::Predicate::Boolean::And.new([
Morpher::Evaluator::Predicate::Boolean::Or.new([
Morpher.compile(s(:eql, s(:attribute, :code), s(:static, 'foo')))
]),
Morpher::Evaluator::Predicate::Negation.new(
Morpher::Evaluator::Predicate::Boolean::Or.new([
described_class::SubjectPrefix.new(expression_b)
])
)
])
end
it { should eql(expected_matcher) }
end
end
context 'on config with multiple match expressions' do

View file

@ -0,0 +1,36 @@
RSpec.describe Mutant::Matcher::Config do
describe '#inspect' do
subject { object.inspect }
context 'on default config' do
let(:object) { described_class::DEFAULT }
it { should eql('#<Mutant::Matcher::Config empty>') }
end
context 'with one expression' do
let(:object) { described_class::DEFAULT.add(:match_expressions, parse_expression('Foo')) }
it { should eql('#<Mutant::Matcher::Config match_expressions: [Foo]>') }
end
context 'with many expressions' do
let(:object) do
described_class::DEFAULT
.add(:match_expressions, parse_expression('Foo'))
.add(:match_expressions, parse_expression('Bar'))
end
it { should eql('#<Mutant::Matcher::Config match_expressions: [Foo,Bar]>') }
end
context 'with match and ignore expression' do
let(:object) do
described_class::DEFAULT
.add(:match_expressions, parse_expression('Foo'))
.add(:ignore_expressions, parse_expression('Bar'))
end
it { should eql('#<Mutant::Matcher::Config match_expressions: [Foo] ignore_expressions: [Bar]>') }
end
end
end

View file

@ -7,7 +7,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Config do
context 'on default config' do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1
@ -21,7 +21,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Config do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 10.00%
Jobs: 1

View file

@ -11,7 +11,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::EnvProgress do
it_reports <<-'STR'
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 10.00%
Jobs: 1
@ -32,7 +32,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::EnvProgress do
context 'on full coverage' do
it_reports <<-'STR'
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 10.00%
Jobs: 1
@ -55,7 +55,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::EnvProgress do
it_reports <<-'STR'
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 10.00%
Jobs: 1

View file

@ -15,7 +15,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::EnvResult do
+false
-----------------------
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1

View file

@ -9,7 +9,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
it_reports <<-REPORT
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1
@ -32,7 +32,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
it_reports <<-REPORT
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 10.00%
Jobs: 1
@ -58,7 +58,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1
@ -85,7 +85,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1
@ -114,7 +114,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
context 'on success' do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1

View file

@ -121,7 +121,7 @@ RSpec.describe Mutant::Reporter::CLI do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1
@ -136,7 +136,7 @@ RSpec.describe Mutant::Reporter::CLI do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 10.00%
Jobs: 1
@ -155,7 +155,7 @@ RSpec.describe Mutant::Reporter::CLI do
it_reports(<<-REPORT)
Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1
@ -181,7 +181,7 @@ RSpec.describe Mutant::Reporter::CLI do
it_reports(<<-REPORT)
[tput-restore]Mutant configuration:
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
Matcher: #<Mutant::Matcher::Config empty>
Integration: Mutant::Integration::Null
Expect Coverage: 100.00%
Jobs: 1