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.
Files changed (201) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +10 -11
  3. data/Changelog.md +93 -38
  4. data/Gemfile +3 -1
  5. data/Gemfile.devtools +16 -20
  6. data/Guardfile +1 -1
  7. data/README.md +36 -16
  8. data/Rakefile +21 -2
  9. data/TODO +11 -7
  10. data/bin/mutant +4 -0
  11. data/bin/zombie +4 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +2 -2
  14. data/config/flog.yml +1 -1
  15. data/config/{site.reek → reek.yml} +94 -70
  16. data/lib/mutant/cli/classifier/method.rb +100 -0
  17. data/lib/mutant/cli/classifier/namespace.rb +47 -0
  18. data/lib/mutant/cli/classifier/scope.rb +35 -0
  19. data/lib/mutant/cli/classifier.rb +141 -0
  20. data/lib/mutant/cli.rb +115 -162
  21. data/lib/mutant/color.rb +2 -2
  22. data/lib/mutant/config.rb +27 -0
  23. data/lib/mutant/constants.rb +32 -17
  24. data/lib/mutant/context/scope.rb +33 -51
  25. data/lib/mutant/context.rb +8 -19
  26. data/lib/mutant/differ.rb +5 -5
  27. data/lib/mutant/helper.rb +2 -17
  28. data/lib/mutant/killer/forked.rb +44 -0
  29. data/lib/mutant/killer/forking.rb +3 -57
  30. data/lib/mutant/killer/rspec.rb +16 -20
  31. data/lib/mutant/killer/static.rb +6 -7
  32. data/lib/mutant/killer.rb +48 -74
  33. data/lib/mutant/loader.rb +6 -6
  34. data/lib/mutant/matcher/chain.rb +4 -25
  35. data/lib/mutant/matcher/method/instance.rb +14 -24
  36. data/lib/mutant/matcher/method/singleton.rb +35 -46
  37. data/lib/mutant/matcher/method.rb +95 -83
  38. data/lib/mutant/matcher/{scope_methods.rb → methods.rb} +53 -76
  39. data/lib/mutant/matcher/namespace.rb +71 -0
  40. data/lib/mutant/matcher/scope.rb +34 -0
  41. data/lib/mutant/matcher.rb +24 -34
  42. data/lib/mutant/mutation/evil.rb +35 -0
  43. data/lib/mutant/mutation/filter/code.rb +7 -28
  44. data/lib/mutant/mutation/filter/regexp.rb +6 -18
  45. data/lib/mutant/mutation/filter/whitelist.rb +5 -4
  46. data/lib/mutant/mutation/filter.rb +10 -9
  47. data/lib/mutant/mutation/neutral.rb +35 -0
  48. data/lib/mutant/mutation.rb +21 -61
  49. data/lib/mutant/mutator/node/argument.rb +88 -0
  50. data/lib/mutant/mutator/node/arguments.rb +52 -0
  51. data/lib/mutant/mutator/node/assignment.rb +34 -38
  52. data/lib/mutant/mutator/node/begin.rb +33 -0
  53. data/lib/mutant/mutator/node/block.rb +14 -14
  54. data/lib/mutant/mutator/node/case.rb +59 -0
  55. data/lib/mutant/mutator/node/define.rb +26 -22
  56. data/lib/mutant/mutator/node/if.rb +31 -71
  57. data/lib/mutant/mutator/node/literal/array.rb +25 -9
  58. data/lib/mutant/mutator/node/literal/boolean.rb +13 -30
  59. data/lib/mutant/mutator/node/literal/dynamic.rb +6 -5
  60. data/lib/mutant/mutator/node/literal/fixnum.rb +18 -7
  61. data/lib/mutant/mutator/node/literal/float.rb +15 -8
  62. data/lib/mutant/mutator/node/literal/hash.rb +33 -52
  63. data/lib/mutant/mutator/node/literal/nil.rb +8 -7
  64. data/lib/mutant/mutator/node/literal/range.rb +25 -50
  65. data/lib/mutant/mutator/node/literal/regex.rb +15 -23
  66. data/lib/mutant/mutator/node/literal/string.rb +7 -6
  67. data/lib/mutant/mutator/node/literal/symbol.rb +7 -6
  68. data/lib/mutant/mutator/node/literal.rb +4 -46
  69. data/lib/mutant/mutator/node/mlhs.rb +27 -0
  70. data/lib/mutant/mutator/node/noop.rb +18 -43
  71. data/lib/mutant/mutator/node/return.rb +8 -8
  72. data/lib/mutant/mutator/node/send/binary.rb +31 -0
  73. data/lib/mutant/mutator/node/send.rb +106 -72
  74. data/lib/mutant/mutator/node/super.rb +15 -20
  75. data/lib/mutant/mutator/node/when.rb +32 -7
  76. data/lib/mutant/mutator/node/while.rb +9 -7
  77. data/lib/mutant/mutator/node.rb +116 -66
  78. data/lib/mutant/mutator/registry.rb +14 -11
  79. data/lib/mutant/mutator/util/array.rb +9 -9
  80. data/lib/mutant/mutator/util/symbol.rb +6 -20
  81. data/lib/mutant/mutator/util.rb +6 -3
  82. data/lib/mutant/mutator.rb +12 -28
  83. data/lib/mutant/node_helpers.rb +28 -0
  84. data/lib/mutant/random.rb +3 -2
  85. data/lib/mutant/reporter/cli/printer/config.rb +174 -0
  86. data/lib/mutant/reporter/cli/printer/killer.rb +42 -0
  87. data/lib/mutant/reporter/cli/printer/mutation.rb +55 -0
  88. data/lib/mutant/reporter/cli/printer/subject.rb +147 -0
  89. data/lib/mutant/reporter/cli/printer.rb +165 -0
  90. data/lib/mutant/reporter/cli.rb +9 -277
  91. data/lib/mutant/reporter/null.rb +6 -30
  92. data/lib/mutant/reporter.rb +6 -73
  93. data/lib/mutant/runner/config.rb +82 -0
  94. data/lib/mutant/runner/mutation.rb +58 -0
  95. data/lib/mutant/runner/subject.rb +81 -0
  96. data/lib/mutant/runner.rb +42 -92
  97. data/lib/mutant/singleton_methods.rb +2 -2
  98. data/lib/mutant/strategy/method_expansion.rb +51 -0
  99. data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +142 -0
  100. data/lib/mutant/strategy/rspec/dm2/lookup.rb +61 -0
  101. data/lib/mutant/strategy/rspec/dm2.rb +22 -0
  102. data/lib/mutant/strategy/rspec.rb +20 -22
  103. data/lib/mutant/strategy/static.rb +18 -0
  104. data/lib/mutant/strategy.rb +15 -50
  105. data/lib/mutant/subject/method.rb +100 -0
  106. data/lib/mutant/subject.rb +18 -49
  107. data/lib/mutant/support/method_object.rb +4 -2
  108. data/lib/mutant.rb +40 -35
  109. data/mutant.gemspec +9 -8
  110. data/spec/integration/mutant/rspec_killer_spec.rb +3 -3
  111. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +9 -0
  112. data/spec/integration/mutant/zombie_spec.rb +1 -1
  113. data/spec/shared/method_matcher_behavior.rb +35 -0
  114. data/spec/shared/mutator_behavior.rb +63 -32
  115. data/spec/spec_helper.rb +13 -3
  116. data/spec/support/ice_nine_config.rb +8 -0
  117. data/spec/support/rspec.rb +1 -1
  118. data/spec/support/zombie.rb +1 -1
  119. data/spec/unit/mutant/cli/class_methods/new_spec.rb +42 -28
  120. data/spec/unit/mutant/cli/class_methods/run_spec.rb +15 -13
  121. data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +44 -0
  122. data/spec/unit/mutant/context/scope/root_spec.rb +4 -4
  123. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -5
  124. data/spec/unit/mutant/killer/success_predicate_spec.rb +28 -0
  125. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
  126. data/spec/unit/mutant/matcher/chain/each_spec.rb +1 -1
  127. data/spec/unit/mutant/matcher/chain/matchers_spec.rb +1 -1
  128. data/spec/unit/mutant/matcher/method/instance/each_spec.rb +112 -0
  129. data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +93 -0
  130. data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +59 -0
  131. data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +53 -0
  132. data/spec/unit/mutant/matcher/namespace/each_spec.rb +37 -0
  133. data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +33 -0
  134. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +42 -14
  135. data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +319 -0
  136. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +31 -27
  137. data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +75 -0
  138. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
  139. data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -2
  140. data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +1 -3
  141. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +1 -9
  142. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +6 -2
  143. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +111 -108
  144. data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +0 -33
  145. data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +2 -2
  146. data/spec/unit/mutant/runner/config/subjects_spec.rb +38 -0
  147. data/spec/unit/mutant/runner/config/success_predicate_spec.rb +53 -0
  148. data/spec/unit/mutant/runner/failed_predicte_spec.rb +33 -0
  149. data/spec/unit/mutant/runner/mutation/killer_spec.rb +39 -0
  150. data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +49 -0
  151. data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +49 -0
  152. data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +52 -0
  153. data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +42 -0
  154. data/spec/unit/mutant/subject/context_spec.rb +6 -3
  155. data/spec/unit/mutant/subject/each_spec.rb +11 -8
  156. data/spec/unit/mutant/subject/node_spec.rb +6 -2
  157. data/test_app/spec/shared/method_filter_parse_behavior.rb +0 -2
  158. data/test_app/spec/shared/method_match_behavior.rb +1 -1
  159. data/test_app/spec/spec_helper.rb +4 -2
  160. metadata +101 -109
  161. data/config/roodi.yml +0 -26
  162. data/lib/mutant/matcher/method/classifier.rb +0 -141
  163. data/lib/mutant/matcher/object_space.rb +0 -114
  164. data/lib/mutant/mutator/node/actual_arguments.rb +0 -25
  165. data/lib/mutant/mutator/node/default_arguments.rb +0 -25
  166. data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +0 -33
  167. data/lib/mutant/mutator/node/formal_arguments_19/pattern_argument_expansion.rb +0 -35
  168. data/lib/mutant/mutator/node/formal_arguments_19/require_defaults.rb +0 -37
  169. data/lib/mutant/mutator/node/formal_arguments_19.rb +0 -41
  170. data/lib/mutant/mutator/node/iter_19.rb +0 -27
  171. data/lib/mutant/mutator/node/literal/empty_array.rb +0 -26
  172. data/lib/mutant/mutator/node/pattern_arguments.rb +0 -41
  173. data/lib/mutant/mutator/node/pattern_variable.rb +0 -23
  174. data/lib/mutant/mutator/node/receiver_case.rb +0 -122
  175. data/lib/mutant/mutator/node/send/binary_operator_method.rb +0 -61
  176. data/lib/mutant/mutator/node/send/with_arguments.rb +0 -81
  177. data/lib/mutant/reporter/stats.rb +0 -120
  178. data/lib/mutant/strategy/rspec/example_lookup.rb +0 -163
  179. data/spec/integration/mutant/method_matching_spec.rb +0 -269
  180. data/spec/shared/method_match_behavior.rb +0 -39
  181. data/spec/unit/mutant/killer/fail_ques_spec.rb +0 -39
  182. data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +0 -49
  183. data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +0 -12
  184. data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +0 -21
  185. data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +0 -52
  186. data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +0 -24
  187. data/spec/unit/mutant/matcher/object_space/each_spec.rb +0 -31
  188. data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +0 -60
  189. data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +0 -27
  190. data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +0 -236
  191. data/spec/unit/mutant/subject/class_methods/new_spec.rb +0 -13
  192. data/tasks/metrics/ci.rake +0 -7
  193. data/tasks/metrics/flay.rake +0 -41
  194. data/tasks/metrics/flog.rake +0 -43
  195. data/tasks/metrics/heckle.rake +0 -216
  196. data/tasks/metrics/metric_fu.rake +0 -31
  197. data/tasks/metrics/reek.rake +0 -15
  198. data/tasks/metrics/roodi.rake +0 -15
  199. data/tasks/metrics/yardstick.rake +0 -23
  200. data/tasks/spec.rake +0 -45
  201. 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