mutant 0.5.12 → 0.5.13
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/Changelog.md +10 -0
- data/circle.yml +1 -1
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/mutant.yml +1 -2
- data/config/reek.yml +12 -3
- data/config/rubocop.yml +4 -0
- data/lib/mutant.rb +45 -16
- data/lib/mutant/constants.rb +11 -11
- data/lib/mutant/delegator.rb +50 -0
- data/lib/mutant/{differ.rb → diff.rb} +5 -5
- data/lib/mutant/killer.rb +29 -106
- data/lib/mutant/matcher/method.rb +2 -11
- data/lib/mutant/mutation.rb +17 -3
- data/lib/mutant/mutation/evil.rb +2 -10
- data/lib/mutant/mutation/neutral.rb +4 -30
- data/lib/mutant/mutator/node/literal/fixnum.rb +0 -1
- data/lib/mutant/mutator/node/literal/float.rb +0 -1
- data/lib/mutant/mutator/node/literal/string.rb +0 -1
- data/lib/mutant/mutator/node/literal/symbol.rb +6 -2
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +8 -3
- data/lib/mutant/mutator/util/symbol.rb +3 -1
- data/lib/mutant/node_helpers.rb +1 -3
- data/lib/mutant/reporter.rb +10 -0
- data/lib/mutant/reporter/cli.rb +15 -2
- data/lib/mutant/reporter/cli/printer.rb +12 -105
- data/lib/mutant/reporter/cli/progress.rb +12 -0
- data/lib/mutant/reporter/cli/progress/config.rb +32 -0
- data/lib/mutant/reporter/cli/{printer/killer.rb → progress/mutation.rb} +9 -16
- data/lib/mutant/reporter/cli/progress/noop.rb +22 -0
- data/lib/mutant/reporter/cli/progress/subject.rb +118 -0
- data/lib/mutant/reporter/cli/registry.rb +77 -0
- data/lib/mutant/reporter/cli/report.rb +12 -0
- data/lib/mutant/reporter/cli/report/config.rb +118 -0
- data/lib/mutant/reporter/cli/report/mutation.rb +112 -0
- data/lib/mutant/reporter/cli/report/subject.rb +33 -0
- data/lib/mutant/reporter/null.rb +13 -0
- data/lib/mutant/reporter/trace.rb +41 -0
- data/lib/mutant/runner.rb +22 -20
- data/lib/mutant/runner/config.rb +6 -5
- data/lib/mutant/runner/killer.rb +59 -0
- data/lib/mutant/runner/mutation.rb +17 -10
- data/lib/mutant/runner/subject.rb +14 -4
- data/lib/mutant/strategy.rb +30 -16
- data/lib/mutant/subject/method/instance.rb +1 -1
- data/lib/mutant/test.rb +86 -0
- data/lib/mutant/version.rb +1 -1
- data/spec/integration/mutant/null_spec.rb +18 -0
- data/spec/integration/mutant/rspec_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -2
- data/spec/unit/mutant/diff_spec.rb +162 -0
- data/spec/unit/mutant/mutation_spec.rb +8 -5
- data/spec/unit/mutant/mutator/node/and_asgn_spec.rb +1 -9
- data/spec/unit/mutant/mutator/node/block_spec.rb +6 -18
- data/spec/unit/mutant/mutator/node/case_spec.rb +10 -16
- data/spec/unit/mutant/mutator/node/define_spec.rb +5 -17
- data/spec/unit/mutant/mutator/node/dstr_spec.rb +0 -6
- data/spec/unit/mutant/mutator/node/dsym_spec.rb +0 -5
- data/spec/unit/mutant/mutator/node/if_spec.rb +13 -17
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -7
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +0 -9
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +0 -10
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +1 -5
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +1 -5
- data/spec/unit/mutant/mutator/node/named_value/access_spec.rb +4 -7
- data/spec/unit/mutant/mutator/node/named_value/constant_assignment_spec.rb +1 -5
- data/spec/unit/mutant/mutator/node/named_value/variable_assignment_spec.rb +4 -8
- data/spec/unit/mutant/mutator/node/op_assgn_spec.rb +0 -7
- data/spec/unit/mutant/mutator/node/or_asgn_spec.rb +1 -9
- data/spec/unit/mutant/mutator/node/rescue_spec.rb +0 -4
- data/spec/unit/mutant/reporter/null_spec.rb +11 -0
- data/spec/unit/mutant/runner/config_spec.rb +6 -7
- data/spec/unit/mutant/runner/mutation_spec.rb +101 -0
- data/spec/unit/mutant/runner/subject_spec.rb +10 -7
- data/spec/unit/mutant_spec.rb +53 -0
- metadata +65 -62
- data/lib/mutant/killer/forked.rb +0 -46
- data/lib/mutant/killer/forking.rb +0 -46
- data/lib/mutant/killer/static.rb +0 -34
- data/lib/mutant/mutator/node/literal/dynamic.rb +0 -27
- data/lib/mutant/random.rb +0 -38
- data/lib/mutant/reporter/cli/printer/config.rb +0 -154
- data/lib/mutant/reporter/cli/printer/mutation.rb +0 -103
- data/lib/mutant/reporter/cli/printer/subject.rb +0 -150
- data/spec/unit/mutant/differ/diff_spec.rb +0 -123
- data/spec/unit/mutant/differ_spec.rb +0 -42
- data/spec/unit/mutant/killer/success_predicate_spec.rb +0 -30
- data/spec/unit/mutant/rspec/killer_spec.rb +0 -57
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +0 -44
@@ -0,0 +1,112 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Reporter
|
5
|
+
class CLI
|
6
|
+
class Report
|
7
|
+
|
8
|
+
# Reporter for mutations
|
9
|
+
class Mutation < self
|
10
|
+
|
11
|
+
# Run report printer
|
12
|
+
#
|
13
|
+
# @return [self]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
def run
|
18
|
+
puts(object.identification)
|
19
|
+
puts(details)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# Reporter for noop mutations
|
24
|
+
class Noop < self
|
25
|
+
handle(Mutant::Mutation::Neutral::Noop)
|
26
|
+
|
27
|
+
MESSAGE = [
|
28
|
+
'Parsed subject AST:',
|
29
|
+
'%s',
|
30
|
+
'Unparsed source:',
|
31
|
+
'%s'
|
32
|
+
].join("\n").freeze
|
33
|
+
|
34
|
+
delegate :killers
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Return details
|
39
|
+
#
|
40
|
+
# @return [self]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
#
|
44
|
+
def details
|
45
|
+
info(MESSAGE, object.subject.node.inspect, object.original_source)
|
46
|
+
end
|
47
|
+
|
48
|
+
end # Noop
|
49
|
+
|
50
|
+
# Reporter for mutations producing a diff
|
51
|
+
class Diff < self
|
52
|
+
handle(Mutant::Mutation::Evil)
|
53
|
+
handle(Mutant::Mutation::Neutral)
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Run report printer
|
58
|
+
#
|
59
|
+
# @return [self]
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
#
|
63
|
+
def details
|
64
|
+
original, current = object.original_source, object.source
|
65
|
+
diff = Mutant::Diff.build(original, current)
|
66
|
+
color? ? diff.colorized_diff : diff.diff
|
67
|
+
end
|
68
|
+
|
69
|
+
end # Diff
|
70
|
+
end # Mutation
|
71
|
+
|
72
|
+
# Subject report printer
|
73
|
+
class MutationRunner < self
|
74
|
+
handle(Mutant::Runner::Mutation)
|
75
|
+
|
76
|
+
# Run report printer
|
77
|
+
#
|
78
|
+
# @return [self]
|
79
|
+
#
|
80
|
+
# @api private
|
81
|
+
#
|
82
|
+
def run
|
83
|
+
visit(object.mutation)
|
84
|
+
if object.mutation.kind_of?(Mutant::Mutation::Neutral::Noop)
|
85
|
+
report_noop
|
86
|
+
end
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
delegate :killers
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Report noop output
|
95
|
+
#
|
96
|
+
# @return [undefined]
|
97
|
+
#
|
98
|
+
# @api private
|
99
|
+
#
|
100
|
+
def report_noop
|
101
|
+
info('NOOP MUTATION TESTS FAILED!')
|
102
|
+
killers.reject(&:success?).map(&:report).map(&:test_report).each do |report|
|
103
|
+
puts(report.test.identification)
|
104
|
+
puts(report.output)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end # Mutation
|
109
|
+
end # Report
|
110
|
+
end # CLI
|
111
|
+
end # Reporter
|
112
|
+
end # Mutant
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Reporter
|
5
|
+
class CLI
|
6
|
+
class Report
|
7
|
+
|
8
|
+
# Subject report printer
|
9
|
+
class Subject < self
|
10
|
+
handle(Mutant::Runner::Subject)
|
11
|
+
|
12
|
+
delegate :subject, :failed_mutations
|
13
|
+
|
14
|
+
# Run report printer
|
15
|
+
#
|
16
|
+
# @return [self]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
def run
|
21
|
+
status(subject.identification)
|
22
|
+
object.tests.each do |test|
|
23
|
+
puts("- #{test.identification}")
|
24
|
+
end
|
25
|
+
object.failed_mutations.each(&method(:visit))
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
end # Subject
|
30
|
+
end # Report
|
31
|
+
end # CLI
|
32
|
+
end # Reporter
|
33
|
+
end # Mutant
|
data/lib/mutant/reporter/null.rb
CHANGED
@@ -5,6 +5,7 @@ module Mutant
|
|
5
5
|
|
6
6
|
# Null reporter
|
7
7
|
class Null < self
|
8
|
+
include Equalizer.new
|
8
9
|
|
9
10
|
# Report object
|
10
11
|
#
|
@@ -18,6 +19,18 @@ module Mutant
|
|
18
19
|
self
|
19
20
|
end
|
20
21
|
|
22
|
+
# Report progress on object
|
23
|
+
#
|
24
|
+
# @param [Object] _object
|
25
|
+
#
|
26
|
+
# @return [self]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
def progress(_object)
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
21
34
|
end # Null
|
22
35
|
end # Reporter
|
23
36
|
end # Mutant
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Reporter
|
3
|
+
# Reporter to trace report calls, used as a spec adapter
|
4
|
+
class Trace
|
5
|
+
include Concord::Public.new(:progress_calls, :report_calls)
|
6
|
+
|
7
|
+
# Return new trace reporter
|
8
|
+
#
|
9
|
+
# @return [Tracer]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
def self.new
|
14
|
+
super([], [])
|
15
|
+
end
|
16
|
+
|
17
|
+
# Report object
|
18
|
+
#
|
19
|
+
# @param [Object] object
|
20
|
+
#
|
21
|
+
# @return [self]
|
22
|
+
#
|
23
|
+
def report(object)
|
24
|
+
report_calls << object
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
# Report new progress on object
|
29
|
+
#
|
30
|
+
# @param [Object] object
|
31
|
+
#
|
32
|
+
# @return [self]
|
33
|
+
#
|
34
|
+
def progress(object)
|
35
|
+
progress_calls << object
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
end # Tracker
|
40
|
+
end # reporter
|
41
|
+
end # Mutant
|
data/lib/mutant/runner.rb
CHANGED
@@ -48,9 +48,9 @@ module Mutant
|
|
48
48
|
#
|
49
49
|
# @api private
|
50
50
|
#
|
51
|
-
def self.run(config, object)
|
51
|
+
def self.run(config, object, *arguments)
|
52
52
|
handler = lookup(object.class)
|
53
|
-
handler.new(config, object)
|
53
|
+
handler.new(config, object, *arguments)
|
54
54
|
end
|
55
55
|
|
56
56
|
# Return config
|
@@ -101,16 +101,6 @@ module Mutant
|
|
101
101
|
(@end || Time.now) - @start
|
102
102
|
end
|
103
103
|
|
104
|
-
# Return reporter
|
105
|
-
#
|
106
|
-
# @return [Reporter]
|
107
|
-
#
|
108
|
-
# @api private
|
109
|
-
#
|
110
|
-
def reporter
|
111
|
-
config.reporter
|
112
|
-
end
|
113
|
-
|
114
104
|
# Test if runner is successful
|
115
105
|
#
|
116
106
|
# @return [true]
|
@@ -133,7 +123,7 @@ module Mutant
|
|
133
123
|
#
|
134
124
|
abstract_method :run
|
135
125
|
|
136
|
-
#
|
126
|
+
# Run reporter on object
|
137
127
|
#
|
138
128
|
# @param [Object] object
|
139
129
|
#
|
@@ -141,20 +131,32 @@ module Mutant
|
|
141
131
|
#
|
142
132
|
# @api private
|
143
133
|
#
|
144
|
-
def
|
145
|
-
reporter.
|
134
|
+
def progress(object)
|
135
|
+
reporter.progress(object)
|
146
136
|
end
|
147
137
|
|
148
|
-
#
|
138
|
+
# Return reporter
|
139
|
+
#
|
140
|
+
# @return [Reporter]
|
141
|
+
#
|
142
|
+
# @api private
|
143
|
+
#
|
144
|
+
def reporter
|
145
|
+
config.reporter
|
146
|
+
end
|
147
|
+
|
148
|
+
# Perform dispatch on multiple inputs
|
149
|
+
#
|
150
|
+
# @param [Enumerable<Object>] input
|
149
151
|
#
|
150
152
|
# @return [Enumerable<Runner>]
|
151
153
|
#
|
152
154
|
# @api private
|
153
155
|
#
|
154
|
-
def
|
156
|
+
def visit_collection(input, *arguments)
|
155
157
|
collection = []
|
156
158
|
input.each do |object|
|
157
|
-
runner = visit(object)
|
159
|
+
runner = visit(object, *arguments)
|
158
160
|
collection << runner
|
159
161
|
@stop = runner.stop?
|
160
162
|
break if @stop
|
@@ -170,8 +172,8 @@ module Mutant
|
|
170
172
|
#
|
171
173
|
# @api private
|
172
174
|
#
|
173
|
-
def visit(object)
|
174
|
-
Runner.run(config, object)
|
175
|
+
def visit(object, *arguments)
|
176
|
+
Runner.run(config, object, *arguments)
|
175
177
|
end
|
176
178
|
|
177
179
|
end # Runner
|
data/lib/mutant/runner/config.rb
CHANGED
@@ -5,6 +5,9 @@ module Mutant
|
|
5
5
|
# Runner for object config
|
6
6
|
class Config < self
|
7
7
|
|
8
|
+
# The expected coverage precision
|
9
|
+
COVERAGE_PRECISION = 1
|
10
|
+
|
8
11
|
register Mutant::Config
|
9
12
|
|
10
13
|
# Run runner for object
|
@@ -40,8 +43,6 @@ module Mutant
|
|
40
43
|
end
|
41
44
|
memoize :failed_subjects
|
42
45
|
|
43
|
-
COVERAGE_PRECISION = 1
|
44
|
-
|
45
46
|
# Test if run was successful
|
46
47
|
#
|
47
48
|
# @return [true]
|
@@ -122,7 +123,7 @@ module Mutant
|
|
122
123
|
def run_subjects
|
123
124
|
strategy = self.strategy
|
124
125
|
strategy.setup
|
125
|
-
@subjects =
|
126
|
+
@subjects = visit_collection(config.subjects)
|
126
127
|
strategy.teardown
|
127
128
|
end
|
128
129
|
|
@@ -133,10 +134,10 @@ module Mutant
|
|
133
134
|
# @api private
|
134
135
|
#
|
135
136
|
def run
|
136
|
-
|
137
|
+
progress(config)
|
137
138
|
run_subjects
|
138
139
|
@end = Time.now
|
139
|
-
report(self)
|
140
|
+
reporter.report(self)
|
140
141
|
end
|
141
142
|
|
142
143
|
end # Config
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Runner
|
3
|
+
# Killer runner
|
4
|
+
class Killer < self
|
5
|
+
include Equalizer.new(:config, :killer)
|
6
|
+
|
7
|
+
register Mutant::Killer
|
8
|
+
|
9
|
+
# Return killer
|
10
|
+
#
|
11
|
+
# @return [Killer]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
attr_reader :killer
|
16
|
+
protected :killer
|
17
|
+
|
18
|
+
# Return kill report
|
19
|
+
#
|
20
|
+
# @return [Killer::Report]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
attr_reader :report
|
25
|
+
|
26
|
+
# Test if killer ran successfully
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
def success?
|
32
|
+
@report.success?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Initialize object
|
36
|
+
#
|
37
|
+
# @param [Config] config
|
38
|
+
# @param [Mutation] mutation
|
39
|
+
#
|
40
|
+
# @return [undefined]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
#
|
44
|
+
def initialize(config, killer)
|
45
|
+
@killer = killer
|
46
|
+
super(config)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Run killer
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
def run
|
54
|
+
@report = killer.run
|
55
|
+
end
|
56
|
+
|
57
|
+
end # Killer
|
58
|
+
end # Runner
|
59
|
+
end # Mutant
|
@@ -4,7 +4,7 @@ module Mutant
|
|
4
4
|
class Runner
|
5
5
|
# Mutation runner
|
6
6
|
class Mutation < self
|
7
|
-
include Equalizer.new(:config, :mutation)
|
7
|
+
include Equalizer.new(:config, :mutation, :tests)
|
8
8
|
|
9
9
|
register Mutant::Mutation
|
10
10
|
|
@@ -16,26 +16,28 @@ module Mutant
|
|
16
16
|
#
|
17
17
|
attr_reader :mutation
|
18
18
|
|
19
|
-
# Return
|
19
|
+
# Return killers
|
20
20
|
#
|
21
|
-
# @return [Killer]
|
21
|
+
# @return [Enumerable<Runner::Killer>]
|
22
22
|
#
|
23
23
|
# @api private
|
24
24
|
#
|
25
|
-
attr_reader :
|
25
|
+
attr_reader :killers
|
26
26
|
|
27
27
|
# Initialize object
|
28
28
|
#
|
29
29
|
# @param [Config] config
|
30
30
|
# @param [Mutation] mutation
|
31
|
+
# @param [Enumerable<Test>] tests
|
31
32
|
#
|
32
33
|
# @return [undefined]
|
33
34
|
#
|
34
35
|
# @api private
|
35
36
|
#
|
36
|
-
def initialize(config, mutation)
|
37
|
-
@mutation = mutation
|
37
|
+
def initialize(config, mutation, tests)
|
38
|
+
@mutation, @tests = mutation, tests
|
38
39
|
super(config)
|
40
|
+
@stop = config.fail_fast && !success?
|
39
41
|
end
|
40
42
|
|
41
43
|
# Test if mutation was handeled successfully
|
@@ -49,7 +51,7 @@ module Mutant
|
|
49
51
|
# @api private
|
50
52
|
#
|
51
53
|
def success?
|
52
|
-
|
54
|
+
killers.any?(&:success?)
|
53
55
|
end
|
54
56
|
|
55
57
|
private
|
@@ -61,9 +63,14 @@ module Mutant
|
|
61
63
|
# @api private
|
62
64
|
#
|
63
65
|
def run
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
progress(mutation)
|
67
|
+
@killers = @tests.map do |test|
|
68
|
+
Mutant::Killer.new(
|
69
|
+
mutation: mutation,
|
70
|
+
test: test
|
71
|
+
)
|
72
|
+
end.map(&method(:visit))
|
73
|
+
progress(self)
|
67
74
|
end
|
68
75
|
|
69
76
|
end # Mutation
|