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,100 @@
1
+ module Mutant
2
+ class Subject
3
+ # Abstract base class for method subjects
4
+ class Method < self
5
+
6
+ # Test if method is public
7
+ #
8
+ # @return [true]
9
+ # if method is public
10
+ #
11
+ # @return [false]
12
+ # otherwise
13
+ #
14
+ # @api private
15
+ #
16
+ abstract_method :public?
17
+
18
+ # Return method name
19
+ #
20
+ # @return [Symbol]
21
+ #
22
+ # @api private
23
+ #
24
+ def name
25
+ node.children[self.class::NAME_INDEX]
26
+ end
27
+
28
+ private
29
+
30
+ # Return scope
31
+ #
32
+ # @return [Class, Module]
33
+ #
34
+ # @api private
35
+ #
36
+ def scope
37
+ context.scope
38
+ end
39
+
40
+ # Return subtype identifier
41
+ #
42
+ # @return [String]
43
+ #
44
+ # @api private
45
+ #
46
+ def subtype
47
+ "#{context.identification}#{self.class::SYMBOL}#{name}"
48
+ end
49
+
50
+ # Instance method subjects
51
+ class Instance < self
52
+
53
+ NAME_INDEX = 0
54
+ SYMBOL = '#'.freeze
55
+
56
+ # Test if method is public
57
+ #
58
+ # @return [true]
59
+ # if method is public
60
+ #
61
+ # @return [false]
62
+ # otherwise
63
+ #
64
+ # @api private
65
+ #
66
+ def public?
67
+ scope.public_method_defined?(name)
68
+ end
69
+ memoize :public?
70
+
71
+ private
72
+
73
+ end # Instance
74
+
75
+ # Singleton method subjects
76
+ class Singleton < self
77
+
78
+ NAME_INDEX = 1
79
+ SYMBOL = '.'.freeze
80
+
81
+ # Test if method is public
82
+ #
83
+ # @return [true]
84
+ # if method is public
85
+ #
86
+ # @return [false]
87
+ # otherwise
88
+ #
89
+ # @api private
90
+ #
91
+ def public?
92
+ scope.singleton_class.public_method_defined?(name)
93
+ end
94
+ memoize :public?
95
+
96
+ end # Singleton
97
+
98
+ end # Method
99
+ end # Subject
100
+ end # Mutant
@@ -1,31 +1,7 @@
1
1
  module Mutant
2
2
  # Subject of a mutation
3
3
  class Subject
4
- include Adamantium::Flat, Enumerable, Equalizer.new(:context, :matcher, :node)
5
-
6
- # Return context
7
- #
8
- # @return [Context]
9
- #
10
- # @api private
11
- #
12
- attr_reader :context
13
-
14
- # Return matcher
15
- #
16
- # @return [Matcher]
17
- #
18
- # @api private
19
- #
20
- attr_reader :matcher
21
-
22
- # Return AST node
23
- #
24
- # @return [Rubinius::AST::Node]
25
- #
26
- # @api private
27
- #
28
- attr_reader :node
4
+ include AbstractType, Adamantium::Flat, Enumerable, Concord::Public.new(:context, :node)
29
5
 
30
6
  # Enumerate possible mutations
31
7
  #
@@ -40,7 +16,7 @@ module Mutant
40
16
  def each
41
17
  return to_enum unless block_given?
42
18
  Mutator.each(node) do |mutant|
43
- yield Mutation.new(self, mutant)
19
+ yield Mutation::Evil.new(self, mutant)
44
20
  end
45
21
 
46
22
  self
@@ -53,7 +29,7 @@ module Mutant
53
29
  # @api private
54
30
  #
55
31
  def noop
56
- Mutation::Noop.new(self)
32
+ Mutation::Neutral.new(self, node)
57
33
  end
58
34
  memoize :noop
59
35
 
@@ -74,36 +50,36 @@ module Mutant
74
50
  # @api private
75
51
  #
76
52
  def source_line
77
- node.line
53
+ node.location.expression.line
78
54
  end
79
55
 
80
- # Return subject identicication
56
+ # Return subject identification
81
57
  #
82
58
  # @return [String]
83
59
  #
84
60
  # @api private
85
61
  #
86
62
  def identification
87
- "#{matcher.identification}:#{source_path}:#{source_line}"
63
+ "#{subtype}:#{source_path}:#{source_line}"
88
64
  end
89
65
  memoize :identification
90
66
 
91
67
  # Return source representation of ast
92
68
  #
93
- # @return [Source]
69
+ # @return [String]
94
70
  #
95
71
  # @api private
96
- #
72
+ #
97
73
  def source
98
- ToSource.to_source(node)
74
+ Unparser.unparse(node)
99
75
  end
100
76
  memoize :source
101
77
 
102
78
  # Return root AST for node
103
79
  #
104
- # @param [Rubinius::AST::Node] node
80
+ # @param [Parser::AST::Node] node
105
81
  #
106
- # @return [Rubinius::AST::Node]
82
+ # @return [Parser::AST::Node]
107
83
  #
108
84
  # @api private
109
85
  #
@@ -113,7 +89,7 @@ module Mutant
113
89
 
114
90
  # Return root AST node for original AST ndoe
115
91
  #
116
- # @return [Rubinius::AST::Node]
92
+ # @return [Parser::AST::Node]
117
93
  #
118
94
  # @api private
119
95
  #
@@ -124,21 +100,14 @@ module Mutant
124
100
 
125
101
  private
126
102
 
127
- # Initialize subject
128
- #
129
- # @param [Matcher] matcher
130
- # the context of mutations
131
- #
132
- # @param [Rubinius::AST::Node] node
133
- # the node to be mutated
103
+ # Return subtype identifier
134
104
  #
135
- # @return [unkown]
105
+ # @return [String]
136
106
  #
137
107
  # @api private
138
108
  #
139
- def initialize(matcher, context, node)
140
- @matcher, @context, @node = matcher, context, node
141
- end
109
+ abstract_method :subtype
110
+ private :subtype
142
111
 
143
- end
144
- end
112
+ end # Subject
113
+ end # Mutant
@@ -1,6 +1,7 @@
1
1
  module Mutant
2
2
  # A mixing to create method object semantics
3
3
  module MethodObject
4
+
4
5
  # Hook called when descendant is extended
5
6
  #
6
7
  # @param [Module|Class] descendant
@@ -27,5 +28,6 @@ module Mutant
27
28
  def run(*args)
28
29
  new(*args)
29
30
  end
30
- end
31
- end
31
+
32
+ end # MethodObject
33
+ end # Mutant
data/lib/mutant.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'backports'
1
+ require 'benchmark'
2
2
  require 'set'
3
3
  require 'adamantium'
4
4
  require 'ice_nine'
@@ -8,29 +8,21 @@ require 'securerandom'
8
8
  require 'equalizer'
9
9
  require 'digest/sha1'
10
10
  require 'inflecto'
11
- require 'to_source'
11
+ require 'parser'
12
+ require 'parser/current'
13
+ require 'unparser'
12
14
  require 'ice_nine'
13
15
  require 'diff/lcs'
14
16
  require 'diff/lcs/hunk'
15
17
  require 'rspec'
16
-
17
- # Patch ice none to freeze nodes correctly
18
- class IceNine::Freezer
19
- # Rubinius namsepace
20
- class Rubinius
21
- # AST namespace
22
- class AST < IceNine::Freezer::Object
23
- # Node configuration
24
- class Node < IceNine::Freezer::Object
25
- end
26
- end
27
- end
28
- end
18
+ require 'anima'
19
+ require 'concord'
29
20
 
30
21
  # Library namespace
31
22
  module Mutant
32
23
  end
33
24
 
25
+ require 'mutant/node_helpers'
34
26
  require 'mutant/singleton_methods'
35
27
  require 'mutant/constants'
36
28
  require 'mutant/support/method_object'
@@ -38,6 +30,8 @@ require 'mutant/helper'
38
30
  require 'mutant/random'
39
31
  require 'mutant/mutator'
40
32
  require 'mutant/mutation'
33
+ require 'mutant/mutation/evil'
34
+ require 'mutant/mutation/neutral'
41
35
  require 'mutant/mutation/filter'
42
36
  require 'mutant/mutation/filter/code'
43
37
  require 'mutant/mutation/filter/whitelist'
@@ -55,55 +49,66 @@ require 'mutant/mutator/node/literal/string'
55
49
  require 'mutant/mutator/node/literal/fixnum'
56
50
  require 'mutant/mutator/node/literal/float'
57
51
  require 'mutant/mutator/node/literal/array'
58
- require 'mutant/mutator/node/literal/empty_array'
59
52
  require 'mutant/mutator/node/literal/hash'
60
53
  require 'mutant/mutator/node/literal/regex'
61
54
  require 'mutant/mutator/node/literal/nil'
62
- require 'mutant/mutator/node/block'
55
+ require 'mutant/mutator/node/assignment'
56
+ require 'mutant/mutator/node/argument'
57
+ require 'mutant/mutator/node/arguments'
58
+ require 'mutant/mutator/node/begin'
63
59
  require 'mutant/mutator/node/while'
64
60
  require 'mutant/mutator/node/super'
65
61
  require 'mutant/mutator/node/send'
66
- require 'mutant/mutator/node/send/with_arguments'
67
- require 'mutant/mutator/node/send/binary_operator_method'
62
+ require 'mutant/mutator/node/send/binary'
68
63
  require 'mutant/mutator/node/when'
69
64
  require 'mutant/mutator/node/assignment'
70
65
  require 'mutant/mutator/node/define'
71
- require 'mutant/mutator/node/formal_arguments_19'
72
- require 'mutant/mutator/node/formal_arguments_19/default_mutations'
73
- require 'mutant/mutator/node/formal_arguments_19/require_defaults'
74
- require 'mutant/mutator/node/formal_arguments_19/pattern_argument_expansion'
75
- require 'mutant/mutator/node/actual_arguments'
76
- require 'mutant/mutator/node/pattern_arguments'
77
- require 'mutant/mutator/node/pattern_variable'
78
- require 'mutant/mutator/node/default_arguments'
66
+ require 'mutant/mutator/node/mlhs'
79
67
  require 'mutant/mutator/node/return'
80
- require 'mutant/mutator/node/iter_19'
68
+ require 'mutant/mutator/node/block'
81
69
  require 'mutant/mutator/node/if'
82
- require 'mutant/mutator/node/receiver_case'
83
- require 'mutant/loader'
70
+ require 'mutant/mutator/node/case'
71
+ require 'mutant/config'
72
+ require 'mutant/loader'
84
73
  require 'mutant/context'
85
74
  require 'mutant/context/scope'
86
75
  require 'mutant/subject'
76
+ require 'mutant/subject/method'
87
77
  require 'mutant/matcher'
88
78
  require 'mutant/matcher/chain'
89
- require 'mutant/matcher/object_space'
90
79
  require 'mutant/matcher/method'
91
80
  require 'mutant/matcher/method/singleton'
92
81
  require 'mutant/matcher/method/instance'
93
- require 'mutant/matcher/scope_methods'
94
- require 'mutant/matcher/method/classifier'
82
+ require 'mutant/matcher/methods'
83
+ require 'mutant/matcher/namespace'
84
+ require 'mutant/matcher/scope'
95
85
  require 'mutant/killer'
96
86
  require 'mutant/killer/static'
97
87
  require 'mutant/killer/rspec'
98
88
  require 'mutant/killer/forking'
89
+ require 'mutant/killer/forked'
99
90
  require 'mutant/strategy'
91
+ require 'mutant/strategy/static'
92
+ require 'mutant/strategy/method_expansion'
100
93
  require 'mutant/strategy/rspec'
101
- require 'mutant/strategy/rspec/example_lookup'
94
+ require 'mutant/strategy/rspec/dm2'
95
+ require 'mutant/strategy/rspec/dm2/lookup'
96
+ require 'mutant/strategy/rspec/dm2/lookup/method'
102
97
  require 'mutant/runner'
98
+ require 'mutant/runner/config'
99
+ require 'mutant/runner/subject'
100
+ require 'mutant/runner/mutation'
103
101
  require 'mutant/cli'
102
+ require 'mutant/cli/classifier'
103
+ require 'mutant/cli/classifier/namespace'
104
+ require 'mutant/cli/classifier/method'
104
105
  require 'mutant/color'
105
106
  require 'mutant/differ'
106
107
  require 'mutant/reporter'
107
- require 'mutant/reporter/stats'
108
108
  require 'mutant/reporter/null'
109
109
  require 'mutant/reporter/cli'
110
+ require 'mutant/reporter/cli/printer'
111
+ require 'mutant/reporter/cli/printer/config'
112
+ require 'mutant/reporter/cli/printer/subject'
113
+ require 'mutant/reporter/cli/printer/killer'
114
+ require 'mutant/reporter/cli/printer/mutation'
data/mutant.gemspec CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'mutant'
5
- gem.version = '0.2.20'
5
+ gem.version = '0.3.0.beta2'
6
6
  gem.authors = [ 'Markus Schirp' ]
7
- gem.email = [ 'mbj@seonic.net' ]
7
+ gem.email = [ 'mbj@schirp-dso.com' ]
8
+
8
9
  gem.description = 'Mutation testing for ruby'
9
10
  gem.summary = 'Mutation testing tool for ruby under MRI and Rubinius'
10
11
  gem.homepage = 'https://github.com/mbj/mutant'
@@ -15,14 +16,14 @@ Gem::Specification.new do |gem|
15
16
  gem.extra_rdoc_files = %w[TODO LICENSE]
16
17
  gem.executables = [ 'mutant' ]
17
18
 
18
- gem.add_runtime_dependency('backports', [ '~> 3.0', '>= 3.0.3' ])
19
- gem.add_runtime_dependency('to_source', '~> 0.2.19')
20
- gem.add_runtime_dependency('ice_nine', '~> 0.7.0')
19
+ gem.add_runtime_dependency('parser', '~> 2.0.beta7')
20
+ gem.add_runtime_dependency('unparser', '~> 0.0.4')
21
+ gem.add_runtime_dependency('ice_nine', '~> 0.8.0')
21
22
  gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
22
- gem.add_runtime_dependency('adamantium', '~> 0.0.7')
23
+ gem.add_runtime_dependency('adamantium', '~> 0.0.8')
23
24
  gem.add_runtime_dependency('equalizer', '~> 0.0.5')
24
25
  gem.add_runtime_dependency('inflecto', '~> 0.0.2')
25
- gem.add_runtime_dependency('abstract_type', '~> 0.0.3')
26
- gem.add_runtime_dependency('diff-lcs', '~> 1.2.1')
26
+ gem.add_runtime_dependency('anima', '~> 0.0.6')
27
+ gem.add_runtime_dependency('concord', '~> 0.1.1')
27
28
  gem.add_runtime_dependency('rspec', '~> 2.13.0')
28
29
  end
@@ -11,14 +11,14 @@ describe Mutant,'rspec integration' do
11
11
  let(:strategy) { Mutant::Strategy::Rspec::DM2 }
12
12
 
13
13
  specify 'allows to kill mutations' do
14
- Kernel.system("bundle exec mutant -I lib -r test_app --rspec-dm2 ::TestApp::Literal#string").should be(true)
14
+ Kernel.system('bundle exec mutant --rspec-dm2 ::TestApp::Literal#string').should be(true)
15
15
  end
16
16
 
17
17
  specify 'fails to kill mutations when they are not covered' do
18
- Kernel.system("bundle exec mutant -I lib -r test_app --rspec-dm2 ::TestApp::Literal#uncovered_string").should be(false)
18
+ Kernel.system('bundle exec mutant --rspec-dm2 ::TestApp::Literal#uncovered_string').should be(false)
19
19
  end
20
20
 
21
21
  specify 'fails when some mutations when are not covered' do
22
- Kernel.system("bundle exec mutant -I lib -r test_app --rspec-dm2 ::TestApp::Literal").should be(false)
22
+ Kernel.system('bundle exec mutant --rspec-dm2 ::TestApp::Literal').should be(false)
23
23
  end
24
24
  end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant do
4
+ specify 'mutant should not crash for any node parser can generate' do
5
+ Mutant::NODE_TYPES.each do |type|
6
+ Mutant::Mutator::Node::Registry.lookup(Mutant::NodeHelpers.s(type))
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mutant, 'as a zombie' do
4
- specify 'allows to create zombie from mutant' do
4
+ pending 'allows to create zombie from mutant' do
5
5
  Zombie.setup
6
6
  Zombie::Runner
7
7
  end
@@ -0,0 +1,35 @@
1
+ shared_examples_for 'a method matcher' do
2
+ before do
3
+ subject
4
+ end
5
+
6
+ let(:node) { mutation_subject.node }
7
+ let(:context) { mutation_subject.context }
8
+ let(:mutation_subject) { yields.first }
9
+
10
+ it 'should return one subject' do
11
+ yields.size.should be(1)
12
+ end
13
+
14
+ it_should_behave_like 'an #each method'
15
+
16
+ it 'should have correct method name' do
17
+ name.should eql(method_name)
18
+ end
19
+
20
+ it 'should have correct line number' do
21
+ (node.location.expression.line - base).should eql(method_line)
22
+ end
23
+
24
+ it 'should have correct arity' do
25
+ arguments.children.length.should eql(method_arity)
26
+ end
27
+
28
+ it 'should have correct scope in context' do
29
+ context.send(:scope).should eql(scope)
30
+ end
31
+
32
+ it 'should have the correct node type' do
33
+ node.type.should be(type)
34
+ end
35
+ end
@@ -1,11 +1,51 @@
1
+ class Subject
2
+
3
+ include Equalizer.new(:source)
4
+
5
+ Undefined = Object.new.freeze
6
+
7
+ attr_reader :source
8
+
9
+ def self.coerce(input)
10
+ case input
11
+ when Parser::AST::Node
12
+ new(input)
13
+ when String
14
+ new(Parser::CurrentRuby.parse(input))
15
+ else
16
+ raise
17
+ end
18
+ end
19
+
20
+ def to_s
21
+ "#{@node.inspect}\n#{@source}"
22
+ end
23
+
24
+ def initialize(node)
25
+ source = Unparser.unparse(node)
26
+ @node, @source = node, source
27
+ end
28
+
29
+ def assert_transitive!
30
+ generated = Unparser.generate(@node)
31
+ parsed = Parser::CurrentRuby.parse(generated)
32
+ again = Unparser.generate(parsed)
33
+ unless generated == again
34
+ # mostly an unparser bug!
35
+ fail "Untransitive:\n%s\n---\n%s" % [generated, again]
36
+ end
37
+ self
38
+ end
39
+ end
40
+
1
41
  shared_examples_for 'a mutator' do
2
42
  subject { object.each(node) { |item| yields << item } }
3
43
 
4
- let(:yields) { [] }
5
- let(:object) { described_class }
44
+ let(:yields) { [] }
45
+ let(:object) { described_class }
6
46
 
7
47
  unless instance_methods.map(&:to_s).include?('node')
8
- let(:node) { source.to_ast }
48
+ let(:node) { parse(source) }
9
49
  end
10
50
 
11
51
  it_should_behave_like 'a command method'
@@ -15,44 +55,35 @@ shared_examples_for 'a mutator' do
15
55
 
16
56
  it { should be_instance_of(to_enum.class) }
17
57
 
18
- def assert_transitive(ast)
19
- generated = ToSource.to_source(ast)
20
- parsed = generated.to_ast
21
- again = ToSource.to_source(parsed)
22
- unless generated == again
23
- fail "Untransitive:\n%s\n---\n%s" % [generated, again]
58
+ let(:expected_mutations) do
59
+ mutations.map do |mutation|
60
+ Subject.coerce(mutation)
24
61
  end
25
62
  end
26
63
 
27
- unless instance_methods.include?(:expected_mutations)
28
- let(:expected_mutations) do
29
- mutations.map do |mutation|
30
- case mutation
31
- when String
32
- ast = mutation.to_ast
33
- assert_transitive(ast)
34
- ast
35
- when Rubinius::AST::Node
36
- assert_transitive(mutation)
37
- mutation
38
- else
39
- raise
40
- end
41
- end.map do |node|
42
- ToSource.to_source(node)
43
- end.to_set
44
- end
64
+ let(:generated_mutations) do
45
65
  end
46
66
 
47
67
  it 'generates the expected mutations' do
48
- generated = self.subject.map { |mutation| ToSource.to_source(mutation) }.to_set
49
68
 
50
- missing = (expected_mutations - generated).to_a
51
- unexpected = (generated - expected_mutations).to_a
69
+ generated = subject.map { |node| Subject.new(node) }
52
70
 
53
- unless generated == expected_mutations
54
- fail "Missing mutations:\n%s\nUnexpected mutations:\n%s" % [missing.join("\n----\n"), unexpected.join("\n----\n")]
71
+ missing = expected_mutations - generated
72
+ unexpected = generated - expected_mutations
73
+
74
+ message = []
75
+
76
+ if missing.any?
77
+ message << 'Missing mutations (%i):' % missing.length
78
+ message.concat(missing)
55
79
  end
80
+
81
+ if unexpected.any?
82
+ message << 'Unexpected mutations (%i):' % unexpected.length
83
+ message.concat(unexpected)
84
+ end
85
+
86
+ fail "Original:\n#{generate(node)}\n-----\n#{message.join("\n-----\n")}" if message.any?
56
87
  end
57
88
  end
58
89
  end
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,23 @@
1
- # encoding: utf-8
2
-
1
+ require 'mutant'
3
2
  require 'devtools'
4
3
  Devtools.init_spec_helper
5
4
 
6
5
  $: << File.join(TestApp.root,'lib')
7
6
 
8
7
  require 'test_app'
9
- require 'mutant'
8
+
9
+ module ParserHelper
10
+ def generate(node)
11
+ Unparser.unparse(node)
12
+ end
13
+
14
+ def parse(string)
15
+ Parser::CurrentRuby.parse(string)
16
+ end
17
+ end
10
18
 
11
19
  RSpec.configure do |config|
12
20
  config.include(CompressHelper)
21
+ config.include(ParserHelper)
22
+ config.include(Mutant::NodeHelpers)
13
23
  end
@@ -0,0 +1,8 @@
1
+ require 'ice_nine'
2
+
3
+ module IceNine
4
+ class Freezer
5
+ class RSpec < NoFreeze
6
+ end
7
+ end
8
+ end
@@ -8,7 +8,7 @@ module Rspec
8
8
  # @api private
9
9
  #
10
10
  def self.nest
11
- original_world, original_configuration =
11
+ original_world, original_configuration =
12
12
  ::RSpec.instance_variable_get(:@world),
13
13
  ::RSpec.instance_variable_get(:@configuration)
14
14
 
@@ -151,7 +151,7 @@ module Zombie
151
151
  #
152
152
  # @api private
153
153
  #
154
- # FIXME:
154
+ # FIXME:
155
155
  # Yeah looks very ugly but im currently to exited to do a cleanup.
156
156
  #
157
157
  def self.files