mutant 0.3.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/Changelog.md +13 -0
- data/Gemfile +1 -1
- data/Guardfile +7 -25
- data/LICENSE +1 -1
- data/README.md +16 -10
- data/config/flay.yml +1 -1
- data/config/reek.yml +11 -11
- data/config/rubocop.yml +1 -1
- data/lib/mutant.rb +3 -10
- data/lib/mutant/cli.rb +199 -80
- data/lib/mutant/config.rb +3 -3
- data/lib/mutant/killer.rb +20 -0
- data/lib/mutant/matcher/filter.rb +3 -8
- data/lib/mutant/matcher/method/instance.rb +1 -1
- data/lib/mutant/matcher/namespace.rb +31 -2
- data/lib/mutant/matcher/null.rb +26 -0
- data/lib/mutant/mutation.rb +0 -1
- data/lib/mutant/reporter/cli/printer.rb +29 -0
- data/lib/mutant/reporter/cli/printer/config.rb +16 -116
- data/lib/mutant/runner/config.rb +47 -1
- data/lib/mutant/strategy.rb +39 -1
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/walker.rb +51 -0
- data/mutant-rspec.gemspec +24 -0
- data/mutant.gemspec +7 -3
- data/spec/integration/mutant/rspec_spec.rb +11 -6
- data/spec/integration/mutant/zombie_spec.rb +2 -2
- data/spec/shared/method_matcher_behavior.rb +6 -6
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/mutant/cli_new_spec.rb +49 -34
- data/spec/unit/mutant/context/scope/root_spec.rb +1 -1
- data/spec/unit/mutant/loader/eval_spec.rb +2 -2
- data/spec/unit/mutant/matcher/chain_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +1 -1
- data/spec/unit/mutant/matcher/namespace_spec.rb +1 -1
- data/spec/unit/mutant/mutation_spec.rb +1 -1
- data/spec/unit/mutant/{killer/rspec_spec.rb → rspec/killer_spec.rb} +2 -1
- data/spec/unit/mutant/runner/config_spec.rb +36 -21
- data/spec/unit/mutant_spec.rb +7 -9
- metadata +25 -22
- data/lib/mutant/cli/builder.rb +0 -167
- data/lib/mutant/killer/rspec.rb +0 -95
- data/lib/mutant/predicate.rb +0 -70
- data/lib/mutant/predicate/attribute.rb +0 -68
- data/lib/mutant/predicate/blacklist.rb +0 -27
- data/lib/mutant/predicate/matcher.rb +0 -38
- data/lib/mutant/predicate/whitelist.rb +0 -28
- data/lib/mutant/strategy/rspec.rb +0 -76
- data/spec/unit/mutant/cli/builder/rspec_spec.rb +0 -38
- data/spec/unit/mutant/matcher/filter_spec.rb +0 -19
- data/spec/unit/mutant/predicate_spec.rb +0 -135
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e603e77505aa94ac731c26cf64c5b3f85453746a
|
4
|
+
data.tar.gz: 44f1fbd18eefabeb1770af343343fa5e0ab2a56c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a189701a6e9fee5573dfcd7ba638e9bf04219f38738a33a143d61cc6d58c26f0cf3369339b27716f71269b58f45a9f3328c14239431642b0c28d6997f2034fe
|
7
|
+
data.tar.gz: 71629135ffe50088a0ea524034df7af56ec43bb9a7cae9ab4ef900fa30877fe2aa5c403f86d62c7cee4607cce28b7ee16cebba5417ea0aab514073f19ea9504a
|
data/.travis.yml
CHANGED
data/Changelog.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# v0.5.0 2014-02-16
|
2
|
+
|
3
|
+
Changes:
|
4
|
+
|
5
|
+
* Add configurable coverage expectation via --coverage (default 100%)
|
6
|
+
* rspec integration was moved into a gem 'mutant-rspec'
|
7
|
+
* Replace filters implementation with morpher predicates
|
8
|
+
* Drop --rspec option use: --use rspec instead.
|
9
|
+
|
10
|
+
# v0.4.0 2014-02-16
|
11
|
+
|
12
|
+
Status: Yanked because of broken dependencies.
|
13
|
+
|
1
14
|
# v0.3.4 2014-01-11
|
2
15
|
|
3
16
|
Changes:
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -2,33 +2,15 @@
|
|
2
2
|
|
3
3
|
guard :bundler do
|
4
4
|
watch('Gemfile')
|
5
|
-
watch('Gemfile.lock')
|
6
|
-
watch(%w{.+.gemspec\z})
|
7
5
|
end
|
8
6
|
|
9
|
-
guard :rspec,
|
10
|
-
#
|
11
|
-
watch('.
|
12
|
-
watch(
|
13
|
-
watch('Gemfile.lock') { 'spec' }
|
14
|
-
watch('spec/spec_helper.rb') { 'spec' }
|
7
|
+
guard :rspec, :all_after_pass => false, :all_on_start => false, :cmd => 'bundle exec rspec --fail-fast --seed 0' do
|
8
|
+
# run all specs if the spec_helper or supporting files files are modified
|
9
|
+
watch('spec/spec_helper.rb') { 'spec/unit' }
|
10
|
+
watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec/unit' }
|
15
11
|
|
16
|
-
|
17
|
-
watch(%r{\Aspec/(?:fixtures|lib|support|shared)/.+\.rb\z}) { 'spec' }
|
12
|
+
watch(%r{lib/.*.rb}) { 'spec/unit' }
|
18
13
|
|
19
|
-
#
|
20
|
-
watch(%r{\
|
21
|
-
watch(%r{\Alib/(.+)/support/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}/#{m[2]}*"] }
|
22
|
-
watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' }
|
23
|
-
|
24
|
-
# Run a spec if it is modified
|
25
|
-
watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
|
14
|
+
# run a spec if it is modified
|
15
|
+
watch(%r{\Aspec/.+_spec\.rb\z})
|
26
16
|
end
|
27
|
-
|
28
|
-
# Deactivated for now. Somehow it disables the rspec guard.
|
29
|
-
#
|
30
|
-
# guard :rubocop, cli: %w[--config config/rubocop.yml] do
|
31
|
-
# watch(%r{.+\.(?:rb|rake)\z})
|
32
|
-
# watch(%r{\Aconfig/rubocop\.yml\z}) { |m| File.dirname(m[0]) }
|
33
|
-
# watch(%r{(?:.+/)?\.rubocop\.yml\z}) { |m| File.dirname(m[0]) }
|
34
|
-
# end
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -12,12 +12,14 @@ or it does not have a speced side effect.
|
|
12
12
|
|
13
13
|
A more readable introduction can be found under: http://solnic.eu/2013/01/23/mutation-testing-with-mutant.html
|
14
14
|
|
15
|
-
Mutant supports MRI and RBX 1.9 and 2.0, while support for jruby is planned.
|
16
|
-
any ruby engine that supports POSIX-fork(2) semantics.
|
15
|
+
Mutant supports MRI and RBX 1.9 and 2.0, while support for jruby is planned.
|
16
|
+
It should also work under any ruby engine that supports POSIX-fork(2) semantics.
|
17
|
+
Support for MRI 2.1 is unstable, because this MRI release segfaults on basic metaprogramming mutants dependencies do.
|
17
18
|
|
18
|
-
|
19
|
+
Integrations
|
20
|
+
------------
|
19
21
|
|
20
|
-
|
22
|
+
Only rspec2 is supported currently.
|
21
23
|
|
22
24
|
Projects using Mutant
|
23
25
|
---------------------
|
@@ -44,10 +46,14 @@ Installation
|
|
44
46
|
|
45
47
|
Install the gem `mutant` via your preferred method.
|
46
48
|
|
47
|
-
|
49
|
+
```ruby
|
50
|
+
gem install mutant
|
51
|
+
```
|
52
|
+
|
53
|
+
If you plan to use the rspec integration you'll have to install `mutant-rspec` also.
|
48
54
|
|
49
55
|
```ruby
|
50
|
-
gem install mutant
|
56
|
+
gem install mutant-rspec
|
51
57
|
```
|
52
58
|
|
53
59
|
Mutations
|
@@ -86,13 +92,13 @@ Examples
|
|
86
92
|
```
|
87
93
|
cd virtus
|
88
94
|
# Run mutant on virtus namespace
|
89
|
-
mutant --include lib --require virtus --rspec ::Virtus*
|
95
|
+
mutant --include lib --require virtus --use rspec ::Virtus*
|
90
96
|
# Run mutant on specific virtus class
|
91
|
-
mutant --include lib --require virtus --rspec ::Virtus::Attribute
|
97
|
+
mutant --include lib --require virtus --use rspec ::Virtus::Attribute
|
92
98
|
# Run mutant on specific virtus class method
|
93
|
-
mutant --include lib --require virtus --rspec ::Virtus::Attribute.build
|
99
|
+
mutant --include lib --require virtus --use rspec ::Virtus::Attribute.build
|
94
100
|
# Run mutant on specific virtus instance method
|
95
|
-
mutant --include lib --require virtus --rspec ::Virtus::Attribute#type
|
101
|
+
mutant --include lib --require virtus --use rspec ::Virtus::Attribute#type
|
96
102
|
```
|
97
103
|
|
98
104
|
Presentations:
|
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
@@ -24,14 +24,15 @@ DuplicateMethodCall:
|
|
24
24
|
FeatureEnvy:
|
25
25
|
enabled: true
|
26
26
|
exclude:
|
27
|
-
- Mutant::CLI#parse
|
28
|
-
- Mutant::CLI#add_strategies
|
29
27
|
- Mutant::Matcher::Method::Instance#match?
|
30
28
|
- Mutant::Matcher::Method::Singleton#receiver?
|
31
29
|
- Mutant::Mutation::Evil#success?
|
32
30
|
- Mutant::Mutation::Neutral#success?
|
33
31
|
- Mutant::Reporter::CLI#subject_results
|
34
|
-
- Mutant::Strategy
|
32
|
+
- Mutant::Rspec::Strategy#options
|
33
|
+
# Nature of OptionParser :(
|
34
|
+
- Mutant::CLI#add_environmental_options
|
35
|
+
- Mutant::CLI#parse
|
35
36
|
IrresponsibleModule:
|
36
37
|
enabled: true
|
37
38
|
exclude: []
|
@@ -80,14 +81,14 @@ TooManyStatements:
|
|
80
81
|
enabled: true
|
81
82
|
exclude:
|
82
83
|
- Mutant#self.singleton_subclass_instance
|
83
|
-
- Mutant::
|
84
|
-
- Mutant::CLI#add_options
|
85
|
-
- Mutant::CLI#add_strategies
|
86
|
-
- Mutant::Killer::Rspec#run
|
84
|
+
- Mutant::Rspec::Killer#run
|
87
85
|
- Mutant::Reporter::CLI#colorized_diff
|
88
86
|
- Mutant::Reporter::CLI::Printer::Config::Runner#run
|
89
87
|
- Mutant::Runner#dispatch
|
90
88
|
- Mutant::Zombifier::File#self.find_uncached
|
89
|
+
# How mutant does CLI parsing is shit
|
90
|
+
- Mutant::CLI#parse
|
91
|
+
- Mutant::CLI#initialize
|
91
92
|
max_statements: 6
|
92
93
|
UncommunicativeMethodName:
|
93
94
|
enabled: true
|
@@ -132,8 +133,7 @@ UtilityFunction:
|
|
132
133
|
- Mutant::Mutation::Evil#success?
|
133
134
|
- Mutant::Mutation::Neutral#success?
|
134
135
|
- Mutant::NodeHelpers#s
|
135
|
-
- Mutant::Strategy
|
136
|
-
- Mutant::Strategy
|
137
|
-
- Mutant::Strategy
|
138
|
-
|
136
|
+
- Mutant::Rspec::Strategy#configuration
|
137
|
+
- Mutant::Rspec::Strategy#options
|
138
|
+
- Mutant::Rspec::Strategy#world
|
139
139
|
max_helper_calls: 0
|
data/config/rubocop.yml
CHANGED
data/lib/mutant.rb
CHANGED
@@ -17,10 +17,9 @@ require 'unparser'
|
|
17
17
|
require 'ice_nine'
|
18
18
|
require 'diff/lcs'
|
19
19
|
require 'diff/lcs/hunk'
|
20
|
-
require 'rspec'
|
21
20
|
require 'anima'
|
22
21
|
require 'concord'
|
23
|
-
require '
|
22
|
+
require 'morpher'
|
24
23
|
|
25
24
|
# Library namespace
|
26
25
|
module Mutant
|
@@ -34,11 +33,7 @@ require 'mutant/node_helpers'
|
|
34
33
|
require 'mutant/singleton_methods'
|
35
34
|
require 'mutant/constants'
|
36
35
|
require 'mutant/random'
|
37
|
-
require 'mutant/
|
38
|
-
require 'mutant/predicate/attribute'
|
39
|
-
require 'mutant/predicate/whitelist'
|
40
|
-
require 'mutant/predicate/blacklist'
|
41
|
-
require 'mutant/predicate/matcher'
|
36
|
+
require 'mutant/walker'
|
42
37
|
require 'mutant/mutator'
|
43
38
|
require 'mutant/mutation'
|
44
39
|
require 'mutant/mutation/evil'
|
@@ -111,13 +106,12 @@ require 'mutant/matcher/methods'
|
|
111
106
|
require 'mutant/matcher/namespace'
|
112
107
|
require 'mutant/matcher/scope'
|
113
108
|
require 'mutant/matcher/filter'
|
109
|
+
require 'mutant/matcher/null'
|
114
110
|
require 'mutant/killer'
|
115
111
|
require 'mutant/killer/static'
|
116
|
-
require 'mutant/killer/rspec'
|
117
112
|
require 'mutant/killer/forking'
|
118
113
|
require 'mutant/killer/forked'
|
119
114
|
require 'mutant/strategy'
|
120
|
-
require 'mutant/strategy/rspec'
|
121
115
|
require 'mutant/runner'
|
122
116
|
require 'mutant/runner/config'
|
123
117
|
require 'mutant/runner/subject'
|
@@ -126,7 +120,6 @@ require 'mutant/cli'
|
|
126
120
|
require 'mutant/cli/classifier'
|
127
121
|
require 'mutant/cli/classifier/namespace'
|
128
122
|
require 'mutant/cli/classifier/method'
|
129
|
-
require 'mutant/cli/builder'
|
130
123
|
require 'mutant/color'
|
131
124
|
require 'mutant/differ'
|
132
125
|
require 'mutant/reporter'
|
data/lib/mutant/cli.rb
CHANGED
@@ -6,7 +6,7 @@ module Mutant
|
|
6
6
|
|
7
7
|
# Comandline parser
|
8
8
|
class CLI
|
9
|
-
include Adamantium::Flat, Equalizer.new(:config)
|
9
|
+
include Adamantium::Flat, Equalizer.new(:config), NodeHelpers
|
10
10
|
|
11
11
|
# Error raised when CLI argv is invalid
|
12
12
|
Error = Class.new(RuntimeError)
|
@@ -32,6 +32,132 @@ module Mutant
|
|
32
32
|
EXIT_FAILURE
|
33
33
|
end
|
34
34
|
|
35
|
+
# Builder for configuration components
|
36
|
+
class Builder
|
37
|
+
include NodeHelpers
|
38
|
+
|
39
|
+
# Initalize object
|
40
|
+
#
|
41
|
+
# @return [undefined]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
#
|
45
|
+
def initialize
|
46
|
+
@matchers = []
|
47
|
+
@subject_ignores = []
|
48
|
+
@subject_selectors = []
|
49
|
+
end
|
50
|
+
|
51
|
+
# Add a subject ignore
|
52
|
+
#
|
53
|
+
# @param [Matcher]
|
54
|
+
#
|
55
|
+
# @return [self]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
#
|
59
|
+
def add_subject_ignore(matcher)
|
60
|
+
@subject_ignores << matcher
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Add a subject selector
|
65
|
+
#
|
66
|
+
# @param [#call] selector
|
67
|
+
#
|
68
|
+
# @return [self]
|
69
|
+
def add_subject_selector(selector)
|
70
|
+
@subject_selectors << selector
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
# Add a subject matcher
|
75
|
+
#
|
76
|
+
# @param [#call] selector
|
77
|
+
#
|
78
|
+
# @return [self]
|
79
|
+
#
|
80
|
+
# @api private
|
81
|
+
#
|
82
|
+
def add_matcher(matcher)
|
83
|
+
@matchers << matcher
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def matcher
|
88
|
+
if @matchers.empty?
|
89
|
+
raise(Error, 'No patterns given')
|
90
|
+
end
|
91
|
+
|
92
|
+
matcher = Matcher::Chain.build(@matchers)
|
93
|
+
|
94
|
+
if predicate
|
95
|
+
Matcher::Filter.new(matcher, predicate)
|
96
|
+
else
|
97
|
+
matcher
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
# Return subject selector
|
104
|
+
#
|
105
|
+
# @return [#call]
|
106
|
+
# if selector is present
|
107
|
+
#
|
108
|
+
# @return [nil]
|
109
|
+
# otherwise
|
110
|
+
#
|
111
|
+
# @api private
|
112
|
+
#
|
113
|
+
def subject_selector
|
114
|
+
if @subject_selectors.any?
|
115
|
+
Morpher::Evaluator::Predicate::Or.new(@subject_selectors)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Return predicate
|
120
|
+
#
|
121
|
+
# @return [#call]
|
122
|
+
# if filter is needed
|
123
|
+
#
|
124
|
+
# @return [nil]
|
125
|
+
# othrwise
|
126
|
+
#
|
127
|
+
# @api private
|
128
|
+
#
|
129
|
+
def predicate
|
130
|
+
if subject_selector && subject_rejector
|
131
|
+
Morpher::Evaluator::Predicate::And.new([
|
132
|
+
subject_selector,
|
133
|
+
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
|
134
|
+
])
|
135
|
+
elsif subject_selector
|
136
|
+
subject_selector
|
137
|
+
elsif subject_rejector
|
138
|
+
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
|
139
|
+
else
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return subject rejector
|
145
|
+
#
|
146
|
+
# @return [#call]
|
147
|
+
#
|
148
|
+
# @api private
|
149
|
+
#
|
150
|
+
def subject_rejector
|
151
|
+
rejectors = @subject_ignores.flat_map(&:to_a).map do |subject|
|
152
|
+
Morpher.evaluator(s(:eql, s(:attribute, :identification), s(:static, subject.identification)))
|
153
|
+
end
|
154
|
+
|
155
|
+
if rejectors.any?
|
156
|
+
Morpher::Evaluator::Predicate::Or.new(rejectors)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
35
161
|
# Initialize objecct
|
36
162
|
#
|
37
163
|
# @param [Array<String>]
|
@@ -41,10 +167,11 @@ module Mutant
|
|
41
167
|
# @api private
|
42
168
|
#
|
43
169
|
def initialize(arguments = [])
|
44
|
-
@
|
170
|
+
@builder = Builder.new
|
45
171
|
@debug = @fail_fast = @zombie = false
|
172
|
+
@expect_coverage = 100.0
|
173
|
+
@strategy = Strategy::Null.new
|
46
174
|
@cache = Mutant::Cache.new
|
47
|
-
@strategy_builder = nil
|
48
175
|
parse(arguments)
|
49
176
|
config # trigger lazyness now
|
50
177
|
end
|
@@ -60,56 +187,17 @@ module Mutant
|
|
60
187
|
cache: @cache,
|
61
188
|
zombie: @zombie,
|
62
189
|
debug: @debug,
|
63
|
-
matcher: matcher,
|
64
|
-
|
65
|
-
strategy: @strategy.output,
|
190
|
+
matcher: @builder.matcher,
|
191
|
+
strategy: @strategy,
|
66
192
|
fail_fast: @fail_fast,
|
67
|
-
reporter:
|
193
|
+
reporter: Reporter::CLI.new($stdout),
|
194
|
+
expected_coverage: @expect_coverage
|
68
195
|
)
|
69
196
|
end
|
70
197
|
memoize :config
|
71
198
|
|
72
199
|
private
|
73
200
|
|
74
|
-
# Return reporter
|
75
|
-
#
|
76
|
-
# @return [Mutant::Reporter::CLI]
|
77
|
-
#
|
78
|
-
# @api private
|
79
|
-
#
|
80
|
-
def reporter
|
81
|
-
Reporter::CLI.new($stdout)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Return matcher
|
85
|
-
#
|
86
|
-
# @return [Mutant::Matcher]
|
87
|
-
#
|
88
|
-
# @raise [CLI::Error]
|
89
|
-
# raises error when matcher is not given
|
90
|
-
#
|
91
|
-
# @api private
|
92
|
-
#
|
93
|
-
def matcher
|
94
|
-
if @matchers.empty?
|
95
|
-
raise(Error, 'No matchers given')
|
96
|
-
end
|
97
|
-
|
98
|
-
Matcher::Chain.build(@matchers)
|
99
|
-
end
|
100
|
-
|
101
|
-
# Add mutation filter
|
102
|
-
#
|
103
|
-
# @param [Class<Predicate>] klass
|
104
|
-
#
|
105
|
-
# @return [undefined]
|
106
|
-
#
|
107
|
-
# @api private
|
108
|
-
#
|
109
|
-
def add_filter(klass, *arguments)
|
110
|
-
@filters << klass.new(*arguments)
|
111
|
-
end
|
112
|
-
|
113
201
|
# Parse the command-line options
|
114
202
|
#
|
115
203
|
# @param [Array<String>] arguments
|
@@ -124,11 +212,12 @@ module Mutant
|
|
124
212
|
#
|
125
213
|
def parse(arguments)
|
126
214
|
opts = OptionParser.new do |builder|
|
127
|
-
builder.banner = 'usage: mutant STRATEGY [options]
|
215
|
+
builder.banner = 'usage: mutant STRATEGY [options] PATTERN ...'
|
128
216
|
builder.separator('')
|
129
|
-
add_strategies(builder)
|
130
217
|
add_environmental_options(builder)
|
131
|
-
|
218
|
+
add_mutation_options(builder)
|
219
|
+
add_filter_options(builder)
|
220
|
+
add_debug_options(builder)
|
132
221
|
end
|
133
222
|
|
134
223
|
patterns =
|
@@ -152,28 +241,7 @@ module Mutant
|
|
152
241
|
def parse_matchers(patterns)
|
153
242
|
patterns.each do |pattern|
|
154
243
|
matcher = Classifier.run(@cache, pattern)
|
155
|
-
@
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
# Add strategies
|
160
|
-
#
|
161
|
-
# @param [OptionParser] parser
|
162
|
-
#
|
163
|
-
# @return [undefined]
|
164
|
-
#
|
165
|
-
# @api private
|
166
|
-
#
|
167
|
-
def add_strategies(parser)
|
168
|
-
parser.separator(EMPTY_STRING)
|
169
|
-
parser.separator('Strategies:')
|
170
|
-
|
171
|
-
{
|
172
|
-
Builder::Rspec => :@strategy,
|
173
|
-
Builder::Predicate::Subject => :@subject_predicate,
|
174
|
-
}.each do |builder, instance_variable_name|
|
175
|
-
builder = builder.new(@cache, parser)
|
176
|
-
instance_variable_set(instance_variable_name, builder)
|
244
|
+
@builder.add_matcher(matcher)
|
177
245
|
end
|
178
246
|
end
|
179
247
|
|
@@ -186,6 +254,8 @@ module Mutant
|
|
186
254
|
# @api private
|
187
255
|
#
|
188
256
|
def add_environmental_options(opts)
|
257
|
+
opts.separator('')
|
258
|
+
opts.separator('Environment:')
|
189
259
|
opts.on('--zombie', 'Run mutant zombified') do
|
190
260
|
@zombie = true
|
191
261
|
end.on('-I', '--include DIRECTORY', 'Add DIRECTORY to $LOAD_PATH') do |directory|
|
@@ -195,25 +265,74 @@ module Mutant
|
|
195
265
|
end
|
196
266
|
end
|
197
267
|
|
268
|
+
# Use plugin
|
269
|
+
#
|
270
|
+
# FIXME: For now all plugins are strategies. Later they could be anything that allows "late integration".
|
271
|
+
#
|
272
|
+
# @param [String] name
|
273
|
+
#
|
274
|
+
# @return [undefined]
|
275
|
+
#
|
276
|
+
# @api private
|
277
|
+
#
|
278
|
+
def use(name)
|
279
|
+
require "mutant-#{name}"
|
280
|
+
@strategy = Strategy.lookup(name).new
|
281
|
+
rescue LoadError
|
282
|
+
$stderr.puts("Cannot load plugin: #{name.inspect}")
|
283
|
+
raise
|
284
|
+
end
|
285
|
+
|
198
286
|
# Add options
|
199
287
|
#
|
200
|
-
# @param [
|
288
|
+
# @param [OptionParser] opts
|
201
289
|
#
|
202
290
|
# @return [undefined]
|
203
291
|
#
|
204
292
|
# @api private
|
205
293
|
#
|
206
|
-
def
|
207
|
-
opts.separator
|
208
|
-
opts.separator
|
294
|
+
def add_mutation_options(opts)
|
295
|
+
opts.separator(EMPTY_STRING)
|
296
|
+
opts.separator('Options:')
|
297
|
+
|
298
|
+
opts.on('--score COVERAGE', 'Fail unless COVERAGE is not reached exactly') do |coverage|
|
299
|
+
@expected_coverage = Float(coverage)
|
300
|
+
end.on('--use STRATEGY', 'Use STRATEGY for killing mutations') do |runner|
|
301
|
+
use(runner)
|
302
|
+
end
|
303
|
+
end
|
209
304
|
|
210
|
-
|
305
|
+
# Add filter options
|
306
|
+
#
|
307
|
+
# @param [OptionParser] opts
|
308
|
+
#
|
309
|
+
# @return [undefined]
|
310
|
+
#
|
311
|
+
# @api private
|
312
|
+
#
|
313
|
+
def add_filter_options(opts)
|
314
|
+
opts.on('--ignore-subject PATTERN', 'Ignore subjects that match PATTERN') do |pattern|
|
315
|
+
@builder.add_subject_ignore(Classifier.run(@cache, pattern))
|
316
|
+
end
|
317
|
+
opts.on('--code CODE', 'Scope execution to subjects with CODE') do |code|
|
318
|
+
@builder.add_subject_selector(Morpher.evaluator(s(:eql, s(:attribute, :code), s(:static, code))))
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# Add debug options
|
323
|
+
#
|
324
|
+
# @param [OptionParser] opts
|
325
|
+
#
|
326
|
+
# @return [undefined]
|
327
|
+
#
|
328
|
+
# @api private
|
329
|
+
#
|
330
|
+
def add_debug_options(opts)
|
331
|
+
opts.on('--fail-fast', 'Fail fast') do
|
332
|
+
@fail_fast = true
|
333
|
+
end.on('--version', 'Print mutants version') do |name|
|
211
334
|
puts("mutant-#{Mutant::VERSION}")
|
212
335
|
Kernel.exit(0)
|
213
|
-
end.on('--code FILTER', 'Adds a code filter') do |filter|
|
214
|
-
add_filter(Predicate::Attribute, :code, filter)
|
215
|
-
end.on('--fail-fast', 'Fail fast') do
|
216
|
-
@fail_fast = true
|
217
336
|
end.on('-d', '--debug', 'Enable debugging output') do
|
218
337
|
@debug = true
|
219
338
|
end.on_tail('-h', '--help', 'Show this message') do
|