mutant 0.2.20 → 0.3.0.beta2
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 +7 -0
- data/.travis.yml +10 -11
- data/Changelog.md +93 -38
- data/Gemfile +3 -1
- data/Gemfile.devtools +16 -20
- data/Guardfile +1 -1
- data/README.md +36 -16
- data/Rakefile +21 -2
- data/TODO +11 -7
- data/bin/mutant +4 -0
- data/bin/zombie +4 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/{site.reek → reek.yml} +94 -70
- data/lib/mutant/cli/classifier/method.rb +100 -0
- data/lib/mutant/cli/classifier/namespace.rb +47 -0
- data/lib/mutant/cli/classifier/scope.rb +35 -0
- data/lib/mutant/cli/classifier.rb +141 -0
- data/lib/mutant/cli.rb +115 -162
- data/lib/mutant/color.rb +2 -2
- data/lib/mutant/config.rb +27 -0
- data/lib/mutant/constants.rb +32 -17
- data/lib/mutant/context/scope.rb +33 -51
- data/lib/mutant/context.rb +8 -19
- data/lib/mutant/differ.rb +5 -5
- data/lib/mutant/helper.rb +2 -17
- data/lib/mutant/killer/forked.rb +44 -0
- data/lib/mutant/killer/forking.rb +3 -57
- data/lib/mutant/killer/rspec.rb +16 -20
- data/lib/mutant/killer/static.rb +6 -7
- data/lib/mutant/killer.rb +48 -74
- data/lib/mutant/loader.rb +6 -6
- data/lib/mutant/matcher/chain.rb +4 -25
- data/lib/mutant/matcher/method/instance.rb +14 -24
- data/lib/mutant/matcher/method/singleton.rb +35 -46
- data/lib/mutant/matcher/method.rb +95 -83
- data/lib/mutant/matcher/{scope_methods.rb → methods.rb} +53 -76
- data/lib/mutant/matcher/namespace.rb +71 -0
- data/lib/mutant/matcher/scope.rb +34 -0
- data/lib/mutant/matcher.rb +24 -34
- data/lib/mutant/mutation/evil.rb +35 -0
- data/lib/mutant/mutation/filter/code.rb +7 -28
- data/lib/mutant/mutation/filter/regexp.rb +6 -18
- data/lib/mutant/mutation/filter/whitelist.rb +5 -4
- data/lib/mutant/mutation/filter.rb +10 -9
- data/lib/mutant/mutation/neutral.rb +35 -0
- data/lib/mutant/mutation.rb +21 -61
- data/lib/mutant/mutator/node/argument.rb +88 -0
- data/lib/mutant/mutator/node/arguments.rb +52 -0
- data/lib/mutant/mutator/node/assignment.rb +34 -38
- data/lib/mutant/mutator/node/begin.rb +33 -0
- data/lib/mutant/mutator/node/block.rb +14 -14
- data/lib/mutant/mutator/node/case.rb +59 -0
- data/lib/mutant/mutator/node/define.rb +26 -22
- data/lib/mutant/mutator/node/if.rb +31 -71
- data/lib/mutant/mutator/node/literal/array.rb +25 -9
- data/lib/mutant/mutator/node/literal/boolean.rb +13 -30
- data/lib/mutant/mutator/node/literal/dynamic.rb +6 -5
- data/lib/mutant/mutator/node/literal/fixnum.rb +18 -7
- data/lib/mutant/mutator/node/literal/float.rb +15 -8
- data/lib/mutant/mutator/node/literal/hash.rb +33 -52
- data/lib/mutant/mutator/node/literal/nil.rb +8 -7
- data/lib/mutant/mutator/node/literal/range.rb +25 -50
- data/lib/mutant/mutator/node/literal/regex.rb +15 -23
- data/lib/mutant/mutator/node/literal/string.rb +7 -6
- data/lib/mutant/mutator/node/literal/symbol.rb +7 -6
- data/lib/mutant/mutator/node/literal.rb +4 -46
- data/lib/mutant/mutator/node/mlhs.rb +27 -0
- data/lib/mutant/mutator/node/noop.rb +18 -43
- data/lib/mutant/mutator/node/return.rb +8 -8
- data/lib/mutant/mutator/node/send/binary.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +106 -72
- data/lib/mutant/mutator/node/super.rb +15 -20
- data/lib/mutant/mutator/node/when.rb +32 -7
- data/lib/mutant/mutator/node/while.rb +9 -7
- data/lib/mutant/mutator/node.rb +116 -66
- data/lib/mutant/mutator/registry.rb +14 -11
- data/lib/mutant/mutator/util/array.rb +9 -9
- data/lib/mutant/mutator/util/symbol.rb +6 -20
- data/lib/mutant/mutator/util.rb +6 -3
- data/lib/mutant/mutator.rb +12 -28
- data/lib/mutant/node_helpers.rb +28 -0
- data/lib/mutant/random.rb +3 -2
- data/lib/mutant/reporter/cli/printer/config.rb +174 -0
- data/lib/mutant/reporter/cli/printer/killer.rb +42 -0
- data/lib/mutant/reporter/cli/printer/mutation.rb +55 -0
- data/lib/mutant/reporter/cli/printer/subject.rb +147 -0
- data/lib/mutant/reporter/cli/printer.rb +165 -0
- data/lib/mutant/reporter/cli.rb +9 -277
- data/lib/mutant/reporter/null.rb +6 -30
- data/lib/mutant/reporter.rb +6 -73
- data/lib/mutant/runner/config.rb +82 -0
- data/lib/mutant/runner/mutation.rb +58 -0
- data/lib/mutant/runner/subject.rb +81 -0
- data/lib/mutant/runner.rb +42 -92
- data/lib/mutant/singleton_methods.rb +2 -2
- data/lib/mutant/strategy/method_expansion.rb +51 -0
- data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +142 -0
- data/lib/mutant/strategy/rspec/dm2/lookup.rb +61 -0
- data/lib/mutant/strategy/rspec/dm2.rb +22 -0
- data/lib/mutant/strategy/rspec.rb +20 -22
- data/lib/mutant/strategy/static.rb +18 -0
- data/lib/mutant/strategy.rb +15 -50
- data/lib/mutant/subject/method.rb +100 -0
- data/lib/mutant/subject.rb +18 -49
- data/lib/mutant/support/method_object.rb +4 -2
- data/lib/mutant.rb +40 -35
- data/mutant.gemspec +9 -8
- data/spec/integration/mutant/rspec_killer_spec.rb +3 -3
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +9 -0
- data/spec/integration/mutant/zombie_spec.rb +1 -1
- data/spec/shared/method_matcher_behavior.rb +35 -0
- data/spec/shared/mutator_behavior.rb +63 -32
- data/spec/spec_helper.rb +13 -3
- data/spec/support/ice_nine_config.rb +8 -0
- data/spec/support/rspec.rb +1 -1
- data/spec/support/zombie.rb +1 -1
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +42 -28
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +15 -13
- data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +44 -0
- data/spec/unit/mutant/context/scope/root_spec.rb +4 -4
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -5
- data/spec/unit/mutant/killer/success_predicate_spec.rb +28 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/each_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +1 -1
- data/spec/unit/mutant/matcher/method/instance/each_spec.rb +112 -0
- data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +93 -0
- data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +59 -0
- data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +53 -0
- data/spec/unit/mutant/matcher/namespace/each_spec.rb +37 -0
- data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +33 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +42 -14
- data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +319 -0
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +31 -27
- data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +75 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -2
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +1 -3
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +1 -9
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +6 -2
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +111 -108
- data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +0 -33
- data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +2 -2
- data/spec/unit/mutant/runner/config/subjects_spec.rb +38 -0
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +53 -0
- data/spec/unit/mutant/runner/failed_predicte_spec.rb +33 -0
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +39 -0
- data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +49 -0
- data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +49 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +52 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +42 -0
- data/spec/unit/mutant/subject/context_spec.rb +6 -3
- data/spec/unit/mutant/subject/each_spec.rb +11 -8
- data/spec/unit/mutant/subject/node_spec.rb +6 -2
- data/test_app/spec/shared/method_filter_parse_behavior.rb +0 -2
- data/test_app/spec/shared/method_match_behavior.rb +1 -1
- data/test_app/spec/spec_helper.rb +4 -2
- metadata +101 -109
- data/config/roodi.yml +0 -26
- data/lib/mutant/matcher/method/classifier.rb +0 -141
- data/lib/mutant/matcher/object_space.rb +0 -114
- data/lib/mutant/mutator/node/actual_arguments.rb +0 -25
- data/lib/mutant/mutator/node/default_arguments.rb +0 -25
- data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +0 -33
- data/lib/mutant/mutator/node/formal_arguments_19/pattern_argument_expansion.rb +0 -35
- data/lib/mutant/mutator/node/formal_arguments_19/require_defaults.rb +0 -37
- data/lib/mutant/mutator/node/formal_arguments_19.rb +0 -41
- data/lib/mutant/mutator/node/iter_19.rb +0 -27
- data/lib/mutant/mutator/node/literal/empty_array.rb +0 -26
- data/lib/mutant/mutator/node/pattern_arguments.rb +0 -41
- data/lib/mutant/mutator/node/pattern_variable.rb +0 -23
- data/lib/mutant/mutator/node/receiver_case.rb +0 -122
- data/lib/mutant/mutator/node/send/binary_operator_method.rb +0 -61
- data/lib/mutant/mutator/node/send/with_arguments.rb +0 -81
- data/lib/mutant/reporter/stats.rb +0 -120
- data/lib/mutant/strategy/rspec/example_lookup.rb +0 -163
- data/spec/integration/mutant/method_matching_spec.rb +0 -269
- data/spec/shared/method_match_behavior.rb +0 -39
- data/spec/unit/mutant/killer/fail_ques_spec.rb +0 -39
- data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +0 -49
- data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +0 -12
- data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +0 -21
- data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +0 -52
- data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +0 -24
- data/spec/unit/mutant/matcher/object_space/each_spec.rb +0 -31
- data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +0 -60
- data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +0 -27
- data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +0 -236
- data/spec/unit/mutant/subject/class_methods/new_spec.rb +0 -13
- data/tasks/metrics/ci.rake +0 -7
- data/tasks/metrics/flay.rake +0 -41
- data/tasks/metrics/flog.rake +0 -43
- data/tasks/metrics/heckle.rake +0 -216
- data/tasks/metrics/metric_fu.rake +0 -31
- data/tasks/metrics/reek.rake +0 -15
- data/tasks/metrics/roodi.rake +0 -15
- data/tasks/metrics/yardstick.rake +0 -23
- data/tasks/spec.rake +0 -45
- data/tasks/yard.rake +0 -9
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
class CLI
|
|
4
|
+
class Printer
|
|
5
|
+
|
|
6
|
+
# Printer for configuration
|
|
7
|
+
class Config < self
|
|
8
|
+
|
|
9
|
+
handle(Mutant::Config)
|
|
10
|
+
|
|
11
|
+
# Report configuration
|
|
12
|
+
#
|
|
13
|
+
# @param [Mutant::Config] config
|
|
14
|
+
#
|
|
15
|
+
# @return [self]
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
#
|
|
19
|
+
def run
|
|
20
|
+
info 'Mutant configuration:'
|
|
21
|
+
info 'Matcher: %s', object.matcher.inspect
|
|
22
|
+
info 'Filter: %s', object.filter.inspect
|
|
23
|
+
info 'Strategy: %s', object.strategy.inspect
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Config results printer
|
|
28
|
+
class Runner < self
|
|
29
|
+
|
|
30
|
+
handle(Mutant::Runner::Config)
|
|
31
|
+
|
|
32
|
+
# Run printer
|
|
33
|
+
#
|
|
34
|
+
# @return [self]
|
|
35
|
+
#
|
|
36
|
+
# @api private
|
|
37
|
+
#
|
|
38
|
+
def run
|
|
39
|
+
print_mutations
|
|
40
|
+
info 'Subjects: %s', amount_subjects
|
|
41
|
+
info 'Mutations: %s', amount_mutations
|
|
42
|
+
info 'Kills: %s', amount_kills
|
|
43
|
+
info 'Runtime: %0.2fs', runtime
|
|
44
|
+
info 'Killtime: %0.2fs', killtime
|
|
45
|
+
info 'Overhead: %0.2f%%', overhead
|
|
46
|
+
status 'Coverage: %0.2f%%', coverage
|
|
47
|
+
status 'Alive: %s', amount_alive
|
|
48
|
+
self
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# Return subjects
|
|
54
|
+
#
|
|
55
|
+
# @return [Array<Subject>]
|
|
56
|
+
#
|
|
57
|
+
# @api private
|
|
58
|
+
#
|
|
59
|
+
def subjects
|
|
60
|
+
object.subjects
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Return amount of subjects
|
|
64
|
+
#
|
|
65
|
+
# @return [Fixnum]
|
|
66
|
+
#
|
|
67
|
+
# @api private
|
|
68
|
+
#
|
|
69
|
+
def amount_subjects
|
|
70
|
+
subjects.length
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Print mutations
|
|
74
|
+
#
|
|
75
|
+
# @return [undefined]
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
#
|
|
79
|
+
def print_mutations
|
|
80
|
+
object.failed_subjects.each do |subject|
|
|
81
|
+
Subject::Runner::Details.run(subject, output)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Return mutations
|
|
86
|
+
#
|
|
87
|
+
# @return [Array<Mutation>]
|
|
88
|
+
#
|
|
89
|
+
# @api private
|
|
90
|
+
#
|
|
91
|
+
def mutations
|
|
92
|
+
subjects.map(&:mutations).flatten
|
|
93
|
+
end
|
|
94
|
+
memoize :mutations
|
|
95
|
+
|
|
96
|
+
# Return amount of mutations
|
|
97
|
+
#
|
|
98
|
+
# @return [Fixnum]
|
|
99
|
+
#
|
|
100
|
+
# @api private
|
|
101
|
+
#
|
|
102
|
+
def amount_mutations
|
|
103
|
+
mutations.length
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Return amount of time in killers
|
|
107
|
+
#
|
|
108
|
+
# @return [Float]
|
|
109
|
+
#
|
|
110
|
+
# @api private
|
|
111
|
+
#
|
|
112
|
+
def killtime
|
|
113
|
+
mutations.map(&:runtime).inject(0, :+)
|
|
114
|
+
end
|
|
115
|
+
memoize :killtime
|
|
116
|
+
|
|
117
|
+
# Return amount of kills
|
|
118
|
+
#
|
|
119
|
+
# @return [Fixnum]
|
|
120
|
+
#
|
|
121
|
+
# @api private
|
|
122
|
+
#
|
|
123
|
+
def amount_kills
|
|
124
|
+
mutations.select(&:success?).length
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Return mutant overhead
|
|
128
|
+
#
|
|
129
|
+
# @return [Float]
|
|
130
|
+
#
|
|
131
|
+
# @api private
|
|
132
|
+
#
|
|
133
|
+
def overhead
|
|
134
|
+
return 0 if runtime.zero?
|
|
135
|
+
Rational(runtime - killtime, runtime) * 100
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Return runtime
|
|
139
|
+
#
|
|
140
|
+
# @return [Float]
|
|
141
|
+
#
|
|
142
|
+
# @api private
|
|
143
|
+
#
|
|
144
|
+
def runtime
|
|
145
|
+
object.runtime
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Return coverage
|
|
149
|
+
#
|
|
150
|
+
# @return [Float]
|
|
151
|
+
#
|
|
152
|
+
# @api private
|
|
153
|
+
#
|
|
154
|
+
def coverage
|
|
155
|
+
return 0 if amount_mutations.zero?
|
|
156
|
+
Rational(amount_kills, amount_mutations) * 100
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Return amount of alive mutations
|
|
160
|
+
#
|
|
161
|
+
# @return [Fixnum]
|
|
162
|
+
#
|
|
163
|
+
# @api private
|
|
164
|
+
#
|
|
165
|
+
def amount_alive
|
|
166
|
+
amount_mutations - amount_kills
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end # Runner
|
|
170
|
+
end # Config
|
|
171
|
+
end # Printer
|
|
172
|
+
end # Cli
|
|
173
|
+
end # Reporter
|
|
174
|
+
end # Mutant
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
class CLI
|
|
4
|
+
class Printer
|
|
5
|
+
|
|
6
|
+
# Printer for killer results
|
|
7
|
+
class Killer < self
|
|
8
|
+
|
|
9
|
+
handle(Mutant::Killer::Forked)
|
|
10
|
+
|
|
11
|
+
# Run printer
|
|
12
|
+
#
|
|
13
|
+
# @return [undefined]
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
def run
|
|
18
|
+
if success?
|
|
19
|
+
char('.', Color::GREEN)
|
|
20
|
+
return
|
|
21
|
+
end
|
|
22
|
+
char('F', Color::RED)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Write colorized char
|
|
26
|
+
#
|
|
27
|
+
# @param [String] char
|
|
28
|
+
# @param [Color]
|
|
29
|
+
#
|
|
30
|
+
# @return [undefined]
|
|
31
|
+
#
|
|
32
|
+
# @api private
|
|
33
|
+
#
|
|
34
|
+
def char(char, color)
|
|
35
|
+
output.write(colorize(color, char))
|
|
36
|
+
output.flush
|
|
37
|
+
end
|
|
38
|
+
end # Killer
|
|
39
|
+
end # Printer
|
|
40
|
+
end # CLI
|
|
41
|
+
end # Reporter
|
|
42
|
+
end # Mutant
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
class CLI
|
|
4
|
+
class Printer
|
|
5
|
+
# Mutation printer
|
|
6
|
+
class Mutation < self
|
|
7
|
+
|
|
8
|
+
# Run mutation printer
|
|
9
|
+
#
|
|
10
|
+
# @return [undefined]
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
#
|
|
14
|
+
def run
|
|
15
|
+
status(mutation.identification)
|
|
16
|
+
puts(colorized_diff)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
# Return mutation
|
|
22
|
+
#
|
|
23
|
+
# @return [Mutation]
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
26
|
+
#
|
|
27
|
+
def mutation
|
|
28
|
+
object.mutation
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Return colorized diff
|
|
32
|
+
#
|
|
33
|
+
# @param [Mutation] mutation
|
|
34
|
+
#
|
|
35
|
+
# @return [undefined]
|
|
36
|
+
#
|
|
37
|
+
# @api private
|
|
38
|
+
#
|
|
39
|
+
def colorized_diff
|
|
40
|
+
original, current = mutation.original_source, mutation.source
|
|
41
|
+
differ = Differ.new(original, current)
|
|
42
|
+
diff = color? ? differ.colorized_diff : differ.diff
|
|
43
|
+
|
|
44
|
+
if diff.empty?
|
|
45
|
+
raise 'Unable to create a diff, so ast mutant or unparser does something strange!!'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
diff
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end # Mutantion
|
|
52
|
+
end # Printer
|
|
53
|
+
end # CLI
|
|
54
|
+
end # Reporter
|
|
55
|
+
end # Mutant
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
class CLI
|
|
4
|
+
class Printer
|
|
5
|
+
|
|
6
|
+
# Subject results printer
|
|
7
|
+
class Subject < self
|
|
8
|
+
|
|
9
|
+
handle(Mutant::Subject::Method::Instance)
|
|
10
|
+
handle(Mutant::Subject::Method::Singleton)
|
|
11
|
+
|
|
12
|
+
# Run subject results printer
|
|
13
|
+
#
|
|
14
|
+
# @return [undefined]
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
#
|
|
18
|
+
def run
|
|
19
|
+
info(object.identification)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Prunter for subject runners
|
|
23
|
+
class Runner < self
|
|
24
|
+
|
|
25
|
+
handle(Mutant::Runner::Subject)
|
|
26
|
+
|
|
27
|
+
# Run printer
|
|
28
|
+
#
|
|
29
|
+
# @return [undefined]
|
|
30
|
+
#
|
|
31
|
+
# @api private
|
|
32
|
+
#
|
|
33
|
+
def run
|
|
34
|
+
print_progress_bar_finish
|
|
35
|
+
print_stats
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# Return mutation time on subject
|
|
42
|
+
#
|
|
43
|
+
# @return [Float]
|
|
44
|
+
#
|
|
45
|
+
# @api private
|
|
46
|
+
#
|
|
47
|
+
def time
|
|
48
|
+
mutations.map(&:runtime).inject(0, :+)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Return subject
|
|
52
|
+
#
|
|
53
|
+
# @return [Subject]
|
|
54
|
+
#
|
|
55
|
+
# @api private
|
|
56
|
+
#
|
|
57
|
+
def subject
|
|
58
|
+
object.subject
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Print stats
|
|
62
|
+
#
|
|
63
|
+
# @return [undefned
|
|
64
|
+
#
|
|
65
|
+
# @api private
|
|
66
|
+
#
|
|
67
|
+
def print_stats
|
|
68
|
+
status('(%02d/%02d) %3d%% - %0.02fs', amount_kills, amount_mutations, coverage, time)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Print progress bar finish
|
|
72
|
+
#
|
|
73
|
+
# @return [undefined]
|
|
74
|
+
#
|
|
75
|
+
# @api private
|
|
76
|
+
#
|
|
77
|
+
def print_progress_bar_finish
|
|
78
|
+
puts unless amount_mutations.zero?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Return kills
|
|
82
|
+
#
|
|
83
|
+
# @return [Fixnum]
|
|
84
|
+
#
|
|
85
|
+
# @api private
|
|
86
|
+
#
|
|
87
|
+
def amount_kills
|
|
88
|
+
fails = object.failed_mutations
|
|
89
|
+
fails = fails.length
|
|
90
|
+
amount_mutations - fails
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Return amount of mutations
|
|
94
|
+
#
|
|
95
|
+
# @return [Array<Mutation>]
|
|
96
|
+
#
|
|
97
|
+
# @api private
|
|
98
|
+
#
|
|
99
|
+
def amount_mutations
|
|
100
|
+
mutations.length
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Return mutations
|
|
104
|
+
#
|
|
105
|
+
# @return [Array<Mutation>]
|
|
106
|
+
#
|
|
107
|
+
# @api private
|
|
108
|
+
#
|
|
109
|
+
def mutations
|
|
110
|
+
object.mutations
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Return suject coverage
|
|
114
|
+
#
|
|
115
|
+
# @return [Float]
|
|
116
|
+
#
|
|
117
|
+
# @api private
|
|
118
|
+
#
|
|
119
|
+
def coverage
|
|
120
|
+
return 0 if amount_mutations.zero?
|
|
121
|
+
Rational(amount_kills, amount_mutations) * 100
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Detailed subject printer
|
|
125
|
+
class Details < self
|
|
126
|
+
|
|
127
|
+
# Run subject details printer
|
|
128
|
+
#
|
|
129
|
+
# @return [undefined]
|
|
130
|
+
#
|
|
131
|
+
# @api private
|
|
132
|
+
#
|
|
133
|
+
def run
|
|
134
|
+
puts(subject.identification)
|
|
135
|
+
object.failed_mutations.each do |mutation|
|
|
136
|
+
Mutation.run(mutation, output)
|
|
137
|
+
end
|
|
138
|
+
print_stats
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end # Details
|
|
142
|
+
end # Runner
|
|
143
|
+
end # Subject
|
|
144
|
+
end # Printer
|
|
145
|
+
end # CLI
|
|
146
|
+
end # Reporter
|
|
147
|
+
end # Mutant
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
class CLI
|
|
4
|
+
|
|
5
|
+
# CLI runner status printer base class
|
|
6
|
+
class Printer
|
|
7
|
+
include AbstractType, Adamantium::Flat, Concord.new(:object, :output)
|
|
8
|
+
|
|
9
|
+
REGISTRY = {}
|
|
10
|
+
|
|
11
|
+
# Registre handler for class
|
|
12
|
+
#
|
|
13
|
+
# @param [Class] klass
|
|
14
|
+
#
|
|
15
|
+
# @return [undefined]
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
#
|
|
19
|
+
def self.handle(klass)
|
|
20
|
+
REGISTRY[klass] = self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Finalize CLI reporter
|
|
24
|
+
#
|
|
25
|
+
# @return [undefined]
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
def self.finalize
|
|
30
|
+
REGISTRY.freeze
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Run printer
|
|
34
|
+
#
|
|
35
|
+
# @return [self]
|
|
36
|
+
#
|
|
37
|
+
# @api private
|
|
38
|
+
#
|
|
39
|
+
def self.run(*args)
|
|
40
|
+
new(*args).run
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Visit object
|
|
45
|
+
#
|
|
46
|
+
# @param [Object] object
|
|
47
|
+
# @param [IO] output
|
|
48
|
+
#
|
|
49
|
+
# @return [undefined]
|
|
50
|
+
#
|
|
51
|
+
# @api private
|
|
52
|
+
#
|
|
53
|
+
def self.visit(object, output)
|
|
54
|
+
printer = REGISTRY.fetch(object.class)
|
|
55
|
+
printer.run(object, output)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
abstract_method :run
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Return status color
|
|
64
|
+
#
|
|
65
|
+
# @return [Color]
|
|
66
|
+
#
|
|
67
|
+
# @api private
|
|
68
|
+
#
|
|
69
|
+
def color
|
|
70
|
+
success? ? Color::GREEN : Color::RED
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Print an info line to output
|
|
74
|
+
#
|
|
75
|
+
# @return [undefined]
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
#
|
|
79
|
+
def info(string, *arguments)
|
|
80
|
+
puts(sprintf(string, *arguments))
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Print a status line to output
|
|
84
|
+
#
|
|
85
|
+
# @return [undefined]
|
|
86
|
+
#
|
|
87
|
+
# @api private
|
|
88
|
+
#
|
|
89
|
+
def status(string, *arguments)
|
|
90
|
+
puts(colorize(color, sprintf(string, *arguments)))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Print a line to output
|
|
94
|
+
#
|
|
95
|
+
# @return [undefined]
|
|
96
|
+
#
|
|
97
|
+
# @api private
|
|
98
|
+
#
|
|
99
|
+
def puts(string = NL)
|
|
100
|
+
output.puts(string)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Test if runner was successful
|
|
104
|
+
#
|
|
105
|
+
# @return [true]
|
|
106
|
+
# if runner is successful
|
|
107
|
+
#
|
|
108
|
+
# @return [false]
|
|
109
|
+
# otherwise
|
|
110
|
+
#
|
|
111
|
+
# @api private
|
|
112
|
+
#
|
|
113
|
+
def success?
|
|
114
|
+
object.success?
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Test for colored output
|
|
118
|
+
#
|
|
119
|
+
# @return [true]
|
|
120
|
+
# returns true if output is colored
|
|
121
|
+
#
|
|
122
|
+
# @return [false]
|
|
123
|
+
# returns false otherwise
|
|
124
|
+
#
|
|
125
|
+
# @api private
|
|
126
|
+
#
|
|
127
|
+
def color?
|
|
128
|
+
tty?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Colorize message
|
|
132
|
+
#
|
|
133
|
+
# @param [Color] color
|
|
134
|
+
# @param [String] message
|
|
135
|
+
#
|
|
136
|
+
# @api private
|
|
137
|
+
#
|
|
138
|
+
# @return [String]
|
|
139
|
+
# returns colorized string if color is enabled
|
|
140
|
+
# returns unmodified message otherwise
|
|
141
|
+
#
|
|
142
|
+
def colorize(color, message)
|
|
143
|
+
color = Color::NONE unless tty?
|
|
144
|
+
color.format(message)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Test for output to tty
|
|
148
|
+
#
|
|
149
|
+
# @return [true]
|
|
150
|
+
# returns true if output is a tty
|
|
151
|
+
#
|
|
152
|
+
# @return [false]
|
|
153
|
+
# returns false otherwise
|
|
154
|
+
#
|
|
155
|
+
# @api private
|
|
156
|
+
#
|
|
157
|
+
def tty?
|
|
158
|
+
output.respond_to?(:tty?) && output.tty?
|
|
159
|
+
end
|
|
160
|
+
memoize :tty?
|
|
161
|
+
|
|
162
|
+
end # Printer
|
|
163
|
+
end # CLI
|
|
164
|
+
end # Reporter
|
|
165
|
+
end # Mutant
|