mutant 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. data/.gitignore +5 -11
  2. data/.rspec +0 -1
  3. data/.travis.yml +14 -3
  4. data/Changelog.md +3 -0
  5. data/Gemfile +5 -1
  6. data/Gemfile.devtools +49 -0
  7. data/Guardfile +18 -0
  8. data/README.md +67 -0
  9. data/Rakefile +4 -1
  10. data/TODO +13 -0
  11. data/bin/mutant +14 -0
  12. data/bin/zombie +14 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/roodi.yml +26 -0
  16. data/config/site.reek +93 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/inflector.rb +7 -0
  19. data/lib/inflector/defaults.rb +62 -0
  20. data/lib/inflector/inflections.rb +209 -0
  21. data/lib/inflector/methods.rb +149 -0
  22. data/lib/inflector/version.rb +3 -0
  23. data/lib/mutant.rb +96 -21
  24. data/lib/mutant/cli.rb +309 -0
  25. data/lib/mutant/color.rb +61 -0
  26. data/lib/mutant/context.rb +36 -0
  27. data/lib/mutant/context/scope.rb +138 -0
  28. data/lib/mutant/differ.rb +100 -0
  29. data/lib/mutant/helper.rb +38 -0
  30. data/lib/mutant/killer.rb +136 -0
  31. data/lib/mutant/killer/forking.rb +41 -0
  32. data/lib/mutant/killer/rspec.rb +49 -0
  33. data/lib/mutant/killer/static.rb +19 -0
  34. data/lib/mutant/loader.rb +129 -0
  35. data/lib/mutant/matcher.rb +55 -0
  36. data/lib/mutant/matcher/chain.rb +66 -0
  37. data/lib/mutant/matcher/method.rb +173 -0
  38. data/lib/mutant/matcher/method/classifier.rb +126 -0
  39. data/lib/mutant/matcher/method/instance.rb +67 -0
  40. data/lib/mutant/matcher/method/singleton.rb +141 -0
  41. data/lib/mutant/matcher/object_space.rb +114 -0
  42. data/lib/mutant/matcher/scope_methods.rb +127 -0
  43. data/lib/mutant/mutation.rb +101 -12
  44. data/lib/mutant/mutation/filter.rb +75 -0
  45. data/lib/mutant/mutation/filter/code.rb +68 -0
  46. data/lib/mutant/mutation/filter/regexp.rb +39 -0
  47. data/lib/mutant/mutation/filter/whitelist.rb +47 -0
  48. data/lib/mutant/mutator.rb +134 -30
  49. data/lib/mutant/mutator/node.rb +163 -0
  50. data/lib/mutant/mutator/node/arguments.rb +24 -0
  51. data/lib/mutant/mutator/node/block.rb +24 -0
  52. data/lib/mutant/mutator/node/define.rb +24 -0
  53. data/lib/mutant/mutator/node/if_statement.rb +93 -0
  54. data/lib/mutant/mutator/node/literal.rb +54 -0
  55. data/lib/mutant/mutator/node/literal/array.rb +28 -0
  56. data/lib/mutant/mutator/node/literal/boolean.rb +49 -0
  57. data/lib/mutant/mutator/node/literal/dynamic.rb +24 -0
  58. data/lib/mutant/mutator/node/literal/empty_array.rb +26 -0
  59. data/lib/mutant/mutator/node/literal/fixnum.rb +37 -0
  60. data/lib/mutant/mutator/node/literal/float.rb +48 -0
  61. data/lib/mutant/mutator/node/literal/hash.rb +89 -0
  62. data/lib/mutant/mutator/node/literal/nil.rb +25 -0
  63. data/lib/mutant/mutator/node/literal/range.rb +94 -0
  64. data/lib/mutant/mutator/node/literal/regex.rb +43 -0
  65. data/lib/mutant/mutator/node/literal/string.rb +26 -0
  66. data/lib/mutant/mutator/node/literal/symbol.rb +26 -0
  67. data/lib/mutant/mutator/node/noop.rb +55 -0
  68. data/lib/mutant/mutator/node/receiver_case.rb +140 -0
  69. data/lib/mutant/mutator/node/return.rb +31 -0
  70. data/lib/mutant/mutator/node/send.rb +112 -0
  71. data/lib/mutant/mutator/registry.rb +48 -0
  72. data/lib/mutant/mutator/util.rb +87 -0
  73. data/lib/mutant/random.rb +24 -27
  74. data/lib/mutant/reporter.rb +48 -30
  75. data/lib/mutant/reporter/cli.rb +221 -0
  76. data/lib/mutant/reporter/null.rb +42 -0
  77. data/lib/mutant/reporter/stats.rb +64 -0
  78. data/lib/mutant/runner.rb +112 -0
  79. data/lib/mutant/strategy.rb +42 -0
  80. data/lib/mutant/strategy/rspec.rb +59 -0
  81. data/lib/mutant/strategy/rspec/example_lookup.rb +122 -0
  82. data/lib/mutant/subject.rb +115 -0
  83. data/lib/mutant/support/method_object.rb +31 -0
  84. data/locator.rb +87 -0
  85. data/mutant.gemspec +21 -21
  86. data/spec/integration/mutant/differ_spec.rb +15 -0
  87. data/spec/integration/mutant/loader_spec.rb +21 -0
  88. data/spec/integration/mutant/method_matching_spec.rb +269 -0
  89. data/spec/integration/mutant/rspec_killer_spec.rb +24 -0
  90. data/spec/integration/mutant/runner_spec.rb +26 -0
  91. data/spec/integration/mutant/zombie_spec.rb +8 -0
  92. data/spec/rcov.opts +7 -0
  93. data/spec/shared/command_method_behavior.rb +7 -0
  94. data/spec/shared/each_method_behaviour.rb +15 -0
  95. data/spec/shared/hash_method_behavior.rb +17 -0
  96. data/spec/shared/idempotent_method_behavior.rb +7 -0
  97. data/spec/shared/invertible_method_behaviour.rb +9 -0
  98. data/spec/shared/method_filter_parse_behavior.rb +16 -0
  99. data/spec/shared/method_match_behavior.rb +39 -0
  100. data/spec/shared/mutator_behavior.rb +46 -0
  101. data/spec/spec_helper.rb +11 -14
  102. data/spec/support/compress_helper.rb +10 -0
  103. data/spec/support/rspec.rb +22 -0
  104. data/spec/support/test_app.rb +5 -0
  105. data/spec/support/zombie.rb +141 -0
  106. data/spec/unit/mutant/cli/class_methods/new_spec.rb +87 -0
  107. data/spec/unit/mutant/cli/class_methods/run_spec.rb +38 -0
  108. data/spec/unit/mutant/context/root_spec.rb +11 -0
  109. data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +29 -0
  110. data/spec/unit/mutant/context/scope/root_spec.rb +22 -0
  111. data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +27 -0
  112. data/spec/unit/mutant/killer/fail_ques_spec.rb +39 -0
  113. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +32 -0
  114. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +33 -0
  115. data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +42 -0
  116. data/spec/unit/mutant/matcher/chain/each_spec.rb +37 -0
  117. data/spec/unit/mutant/matcher/chain/matchers_spec.rb +12 -0
  118. data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +49 -0
  119. data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +12 -0
  120. data/spec/unit/mutant/matcher/each_spec.rb +14 -0
  121. data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +21 -0
  122. data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +34 -0
  123. data/spec/unit/mutant/matcher/method/method_spec.rb +11 -0
  124. data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +24 -0
  125. data/spec/unit/mutant/matcher/object_space/each_spec.rb +31 -0
  126. data/spec/unit/mutant/mutator/each_spec.rb +25 -0
  127. data/spec/unit/mutant/mutator/emit_new_spec.rb +51 -0
  128. data/spec/unit/mutant/mutator/emit_spec.rb +52 -0
  129. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +36 -0
  130. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +47 -0
  131. data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +30 -0
  132. data/spec/unit/mutant/mutator/node/literal/array_spec.rb +30 -0
  133. data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +23 -0
  134. data/spec/unit/mutant/mutator/node/literal/empty_array_spec.rb +17 -0
  135. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +17 -0
  136. data/spec/unit/mutant/mutator/node/literal/float_spec.rb +25 -0
  137. data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +34 -0
  138. data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +13 -0
  139. data/spec/unit/mutant/mutator/node/literal/range_spec.rb +35 -0
  140. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +23 -0
  141. data/spec/unit/mutant/mutator/node/literal/string_spec.rb +17 -0
  142. data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +17 -0
  143. data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +27 -0
  144. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +21 -0
  145. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +78 -0
  146. data/spec/unit/mutant/mutator/self_spec.rb +7 -0
  147. data/spec/unit/mutant/subject/class_methods/new_spec.rb +13 -0
  148. data/spec/unit/mutant/subject/context_spec.rb +14 -0
  149. data/spec/unit/mutant/subject/each_spec.rb +35 -0
  150. data/spec/unit/mutant/subject/node_spec.rb +13 -0
  151. data/tasks/metrics/ci.rake +7 -0
  152. data/tasks/metrics/flay.rake +41 -0
  153. data/tasks/metrics/flog.rake +43 -0
  154. data/tasks/metrics/heckle.rake +216 -0
  155. data/tasks/metrics/metric_fu.rake +31 -0
  156. data/tasks/metrics/reek.rake +15 -0
  157. data/tasks/metrics/roodi.rake +15 -0
  158. data/tasks/metrics/yardstick.rake +23 -0
  159. data/tasks/spec.rake +45 -0
  160. data/tasks/yard.rake +9 -0
  161. data/test_app/.rspec +1 -0
  162. data/test_app/lib/test_app.rb +5 -0
  163. data/test_app/lib/test_app/literal.rb +32 -0
  164. data/test_app/spec/shared/command_method_behavior.rb +7 -0
  165. data/test_app/spec/shared/each_method_behaviour.rb +15 -0
  166. data/test_app/spec/shared/hash_method_behavior.rb +17 -0
  167. data/test_app/spec/shared/idempotent_method_behavior.rb +7 -0
  168. data/test_app/spec/shared/invertible_method_behaviour.rb +9 -0
  169. data/test_app/spec/shared/method_filter_parse_behavior.rb +16 -0
  170. data/test_app/spec/shared/method_match_behavior.rb +39 -0
  171. data/test_app/spec/shared/mutator_behavior.rb +44 -0
  172. data/test_app/spec/spec_helper.rb +7 -0
  173. data/test_app/spec/unit/test_app/literal/command_spec.rb +9 -0
  174. data/test_app/spec/unit/test_app/literal/string_spec.rb +9 -0
  175. metadata +346 -124
  176. data/.rvmrc +0 -1
  177. data/Readme.md +0 -13
  178. data/exe/mutate +0 -6
  179. data/lib/mutant/extensions.rb +0 -8
  180. data/lib/mutant/formatter.rb +0 -19
  181. data/lib/mutant/implementation.rb +0 -70
  182. data/lib/mutant/literal.rb +0 -147
  183. data/lib/mutant/method.rb +0 -31
  184. data/lib/mutant/mutatee.rb +0 -61
  185. data/lib/mutant/node.rb +0 -26
  186. data/lib/mutant/runners/rspec.rb +0 -34
  187. data/lib/mutant/version.rb +0 -3
  188. data/spec/functional/class_spec.rb +0 -46
  189. data/spec/functional/instance_method/array_spec.rb +0 -53
  190. data/spec/functional/instance_method/boolean_spec.rb +0 -101
  191. data/spec/functional/instance_method/call_spec.rb +0 -161
  192. data/spec/functional/instance_method/fixnum_spec.rb +0 -53
  193. data/spec/functional/instance_method/float_spec.rb +0 -53
  194. data/spec/functional/instance_method/hash_spec.rb +0 -53
  195. data/spec/functional/instance_method/if_spec.rb +0 -57
  196. data/spec/functional/instance_method/ivar_assign_spec.rb +0 -62
  197. data/spec/functional/instance_method/range_spec.rb +0 -53
  198. data/spec/functional/instance_method/regex_spec.rb +0 -55
  199. data/spec/functional/instance_method/string_spec.rb +0 -53
  200. data/spec/functional/instance_method/symbol_spec.rb +0 -53
  201. data/spec/functional/reporter/method_loaded_spec.rb +0 -62
  202. data/spec/functional/reporter/running_mutations_spec.rb +0 -60
  203. data/spec/functional/runners/rspec_spec.rb +0 -26
  204. data/spec/functional/singleton_method/array_spec.rb +0 -53
  205. data/spec/functional/singleton_method/boolean_spec.rb +0 -101
  206. data/spec/functional/singleton_method/call_spec.rb +0 -161
  207. data/spec/functional/singleton_method/fixnum_spec.rb +0 -53
  208. data/spec/functional/singleton_method/float_spec.rb +0 -53
  209. data/spec/functional/singleton_method/hash_spec.rb +0 -53
  210. data/spec/functional/singleton_method/if_spec.rb +0 -57
  211. data/spec/functional/singleton_method/ivar_assign_spec.rb +0 -60
  212. data/spec/functional/singleton_method/range_spec.rb +0 -53
  213. data/spec/functional/singleton_method/regex_spec.rb +0 -55
  214. data/spec/functional/singleton_method/string_spec.rb +0 -53
  215. data/spec/functional/singleton_method/symbol_spec.rb +0 -53
  216. data/spec/mutant/extensions_spec.rb +0 -13
  217. data/spec/mutant/implementation_spec.rb +0 -223
  218. data/spec/mutant/literal_spec.rb +0 -129
  219. data/spec/mutant/mutatee_spec.rb +0 -28
  220. data/spec/mutant/node_spec.rb +0 -41
  221. data/spec/mutant/random_spec.rb +0 -33
  222. data/spec/mutant/reporter_spec.rb +0 -17
  223. data/spec/mutant_spec.rb +0 -28
  224. data/spec/support/example_group_helpers.rb +0 -11
  225. data/spec/support/example_helpers.rb +0 -5
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'empty array' do
4
+ let(:source) { '[]' }
5
+
6
+ let(:mutations) do
7
+ mutations = []
8
+
9
+ # Literal replaced with nil
10
+ mutations << [:nil]
11
+
12
+ # Extra element
13
+ mutations << '[nil]'
14
+ end
15
+
16
+ it_should_behave_like 'a mutator'
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'fixnum' do
4
+ let(:random_fixnum) { 5 }
5
+
6
+ let(:source) { '10' }
7
+
8
+ let(:mutations) do
9
+ %W(nil 0 1 #{random_fixnum}) << [:lit, -10]
10
+ end
11
+
12
+ before do
13
+ Mutant::Random.stub(:fixnum => random_fixnum)
14
+ end
15
+
16
+ it_should_behave_like 'a mutator'
17
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'float' do
4
+ let(:source) { '10.0' }
5
+
6
+ let(:mutations) do
7
+ mutations = []
8
+ mutations << 'nil'
9
+ mutations << '0.0'
10
+ mutations << '1.0'
11
+ mutations << random_float.to_s
12
+ mutations << '0.0/0.0'
13
+ mutations << '1.0/0.0'
14
+ mutations << [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]]
15
+ mutations << [:lit, -10.0]
16
+ end
17
+
18
+ let(:random_float) { 7.123 }
19
+
20
+ before do
21
+ Mutant::Random.stub(:float => random_float)
22
+ end
23
+
24
+ it_should_behave_like 'a mutator'
25
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'hash' do
4
+ let(:source) { '{true => true, false => false}' }
5
+
6
+ let(:mutations) do
7
+ mutations = []
8
+
9
+ # Literal replaced with nil
10
+ mutations << [:nil]
11
+
12
+ # Mutation of each key and value in hash
13
+ mutations << [:hash, [:false ], [:true ], [:false], [:false]]
14
+ mutations << [:hash, [:nil ], [:true ], [:false], [:false]]
15
+ mutations << [:hash, [:true ], [:false], [:false], [:false]]
16
+ mutations << [:hash, [:true ], [:nil ], [:false], [:false]]
17
+ mutations << [:hash, [:true ], [:true ], [:true ], [:false]]
18
+ mutations << [:hash, [:true ], [:true ], [:nil ], [:false]]
19
+ mutations << [:hash, [:true ], [:true ], [:false], [:true ]]
20
+ mutations << [:hash, [:true ], [:true ], [:false], [:nil ]]
21
+
22
+ # Remove each key once
23
+ mutations << [:hash, [:true ], [:true ]]
24
+ mutations << [:hash, [:false ], [:false ]]
25
+
26
+ # Empty hash
27
+ mutations << [:hash]
28
+
29
+ # Extra element
30
+ mutations << [:hash, [:true ], [:true ], [:false], [:false ], [:nil], [:nil] ]
31
+ end
32
+
33
+ it_should_behave_like 'a mutator'
34
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'nil' do
4
+ let(:source) { 'nil' }
5
+
6
+ let(:mutations) do
7
+ mutations = []
8
+
9
+ mutations << 'Object.new'
10
+ end
11
+
12
+ it_should_behave_like 'a mutator'
13
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'range' do
4
+ context 'inclusive range literal' do
5
+ let(:source) { '1..100' }
6
+
7
+ let(:mutations) do
8
+ mutations = []
9
+ mutations << 'nil'
10
+ mutations << '1...100'
11
+ mutations << '(0.0/0.0)..100'
12
+ mutations << [:dot2, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
13
+ mutations << '1..(1.0/0.0)'
14
+ mutations << '1..(0.0/0.0)'
15
+ end
16
+
17
+ it_should_behave_like 'a mutator'
18
+ end
19
+
20
+ context 'exclusive range literal' do
21
+ let(:source) { '1...100' }
22
+
23
+ let(:mutations) do
24
+ mutations = []
25
+ mutations << 'nil'
26
+ mutations << '1..100'
27
+ mutations << '(0.0/0.0)...100'
28
+ mutations << [:dot3, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
29
+ mutations << '1...(1.0/0.0)'
30
+ mutations << '1...(0.0/0.0)'
31
+ end
32
+
33
+ it_should_behave_like 'a mutator'
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'regex' do
4
+ let(:random_string) { 'bar' }
5
+
6
+ let(:source) { '/foo/' }
7
+
8
+ let(:base_mutations) do
9
+ mutations = []
10
+ mutations << 'nil'
11
+ mutations << "/#{random_string}/"
12
+ mutations << '//' # match all
13
+ mutations << '/a\A/' # match nothing
14
+ end
15
+
16
+ before do
17
+ Mutant::Random.stub(:hex_string => random_string)
18
+ end
19
+
20
+ let(:mutations) { base_mutations }
21
+
22
+ it_should_behave_like 'a mutator'
23
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'string' do
4
+ let(:random_string) { 'bar' }
5
+
6
+ let(:source) { '"foo"' }
7
+
8
+ let(:mutations) do
9
+ %W(nil "#{random_string}")
10
+ end
11
+
12
+ before do
13
+ Mutant::Random.stub(:hex_string => random_string)
14
+ end
15
+
16
+ it_should_behave_like 'a mutator'
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::Literal, 'symbol' do
4
+ let(:random_string) { 'bar' }
5
+
6
+ let(:source) { ':foo' }
7
+
8
+ let(:mutations) do
9
+ %w(nil) << ":s#{random_string}"
10
+ end
11
+
12
+ before do
13
+ Mutant::Random.stub(:hex_string => random_string)
14
+ end
15
+
16
+ it_should_behave_like 'a mutator'
17
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator::Node::ReceiverCase do
4
+ let(:source) { 'case self.condition; when true; true; when false; false; else raise; end' }
5
+
6
+ let(:mutations) do
7
+ mutations = []
8
+
9
+ # Delete each when once
10
+ mutations << 'case self.condition; when true; true; else raise; end'
11
+ mutations << 'case self.condition; when false; false; else raise; end'
12
+
13
+ # Mutate receiver
14
+ mutations << 'case condition; when true; true; when false; false; else raise; end'
15
+
16
+ # Remove else branch
17
+ mutations << 'case self.condition; when true; true; when false; false; end'
18
+
19
+ # Mutate when branch bodies
20
+ mutations << 'case self.condition; when true; nil; when false; false; else raise; end'
21
+ mutations << 'case self.condition; when true; false; when false; false; else raise; end'
22
+ mutations << 'case self.condition; when true; true; when false; nil; else raise; end'
23
+ mutations << 'case self.condition; when true; true; when false; true; else raise; end'
24
+ end
25
+
26
+ it_should_behave_like 'a mutator'
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator, 'return' do
4
+
5
+ context 'return without value' do
6
+ let(:source) { 'return' }
7
+
8
+ let(:mutations) { ['nil'] }
9
+
10
+ it_should_behave_like 'a mutator'
11
+ end
12
+
13
+ context 'return with value' do
14
+ let(:source) { 'return foo' }
15
+
16
+ let(:mutations) { ['foo'] }
17
+
18
+ it_should_behave_like 'a mutator'
19
+ end
20
+
21
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator, 'call' do
4
+ context 'send without arguments' do
5
+ # This could not be reproduced in a test case but happens in the mutant source code?
6
+ context 'block given' do
7
+ context 'implicit self' do
8
+ let(:source) { 'block_given?' }
9
+
10
+ it_should_behave_like 'a noop mutator'
11
+ end
12
+
13
+ context 'explicit self' do
14
+ let(:source) { 'self.block_given?' }
15
+
16
+ it_should_behave_like 'a noop mutator'
17
+ end
18
+ end
19
+
20
+ context 'with self as receiver' do
21
+
22
+ context 'implicit' do
23
+ let(:source) { 'foo' }
24
+
25
+ it_should_behave_like 'a noop mutator'
26
+ end
27
+
28
+ context 'explict' do
29
+ let(:source) { 'self.foo' }
30
+
31
+ let(:mutations) do
32
+ mutations = []
33
+ # with implicit receiver (send privately)
34
+ mutations << 'foo'
35
+ end
36
+
37
+ it_should_behave_like 'a mutator'
38
+ end
39
+ end
40
+
41
+ context 'to some object' do
42
+ let(:source) { '1.foo' }
43
+
44
+ it_should_behave_like 'a noop mutator'
45
+ end
46
+ end
47
+
48
+ context 'send with arguments' do
49
+
50
+ context 'with self as receiver' do
51
+ context 'implicit' do
52
+ let(:source) { 'foo(nil)' }
53
+
54
+ let(:mutations) do
55
+ mutations = []
56
+ mutations << 'foo()'
57
+ mutations << 'foo(Object.new)'
58
+ end
59
+
60
+ it_should_behave_like 'a mutator'
61
+ end
62
+
63
+ context 'explicit' do
64
+ let(:source) { 'self.foo(nil)' }
65
+
66
+ let(:mutations) do
67
+ mutations = []
68
+ # with implicit receiver (send privately)
69
+ mutations << 'foo(nil)'
70
+ mutations << 'self.foo(Object.new)'
71
+ mutations << 'self.foo()'
72
+ end
73
+
74
+ it_should_behave_like 'a mutator'
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Mutator, 'self' do
4
+ let(:source) { 'self' }
5
+
6
+ it_should_behave_like 'a noop mutator'
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Subject, '.new' do
4
+ subject { object.new(matcher, context, ast) }
5
+
6
+ let(:object) { described_class }
7
+
8
+ let(:matcher) { mock('Matcher') }
9
+ let(:context) { mock('Context') }
10
+ let(:ast) { mock('AST') }
11
+
12
+ it { should be_frozen }
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Subject, '#context' do
4
+ subject { object.context }
5
+
6
+ let(:object) { described_class.new(matcher, context, ast) }
7
+ let(:matcher) { mock('Matcher') }
8
+ let(:ast) { mock('AST') }
9
+ let(:context) { mock('Context') }
10
+
11
+ it { should be(context) }
12
+
13
+ it_should_behave_like 'an idempotent method'
14
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Subject, '#each' do
4
+ subject { object.each { |item| yields << item } }
5
+
6
+ let(:object) { described_class.new(matcher, context, ast) }
7
+ let(:matcher) { mock('Matcher') }
8
+ let(:root) { mock('Root AST') }
9
+ let(:ast) { mock('AST') }
10
+ let(:context) { mock('Context', :root => root) }
11
+ let(:mutant) { mock('Mutant') }
12
+ let(:mutation) { mock('Mutation') }
13
+ let(:yields) { [] }
14
+
15
+ before do
16
+ Mutant::Mutator.stub(:each).with(ast).and_yield(mutant).and_return(Mutant::Mutator)
17
+ Mutant::Mutation.stub(:new => mutation)
18
+ end
19
+
20
+ it_should_behave_like 'an #each method'
21
+
22
+ it 'should initialize mutator with ast' do
23
+ Mutant::Mutator.should_receive(:each).with(ast).and_yield(mutation).and_return(Mutant::Mutator)
24
+ subject
25
+ end
26
+
27
+ it 'should yield mutations' do
28
+ expect { subject }.to change { yields.dup }.from([]).to([mutation])
29
+ end
30
+
31
+ it 'should initialize mutation' do
32
+ Mutant::Mutation.should_receive(:new).with(object, mutant).and_return(mutation)
33
+ subject
34
+ end
35
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Subject, '#node' do
4
+ subject { object.node }
5
+ let(:object) { described_class.new(matcher, context, node) }
6
+ let(:matcher) { mock('Matcher') }
7
+ let(:node) { mock('Node') }
8
+ let(:context) { mock('Context') }
9
+
10
+ it { should be(node) }
11
+
12
+ it_should_behave_like 'an idempotent method'
13
+ end
@@ -0,0 +1,7 @@
1
+ desc 'Run metrics with Heckle'
2
+ task :ci => %w[ ci:metrics heckle ]
3
+
4
+ namespace :ci do
5
+ desc 'Run metrics'
6
+ task :metrics => %w[ verify_measurements flog flay reek roodi metrics:all ]
7
+ end
@@ -0,0 +1,41 @@
1
+ begin
2
+ require 'flay'
3
+ require 'yaml'
4
+
5
+ config = YAML.load_file(File.expand_path('../../../config/flay.yml', __FILE__)).freeze
6
+ threshold = config.fetch('threshold').to_i
7
+ total_score = config.fetch('total_score').to_f
8
+ files = Flay.expand_dirs_to_files(config.fetch('path', 'lib'))
9
+
10
+ # original code by Marty Andrews:
11
+ # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
12
+ desc 'Analyze for code duplication'
13
+ task :flay do
14
+ # run flay once without a threshold to ensure the max mass matches the threshold
15
+ flay = Flay.new(:fuzzy => false, :verbose => false, :mass => 0)
16
+ flay.process(*files)
17
+
18
+ max = flay.masses.map { |hash, mass| mass.to_f / flay.hashes[hash].size }.max
19
+ unless max >= threshold
20
+ raise "Adjust flay threshold down to #{max}"
21
+ end
22
+
23
+ total = flay.masses.reduce(0.0) { |total, (hash, mass)| total + (mass.to_f / flay.hashes[hash].size) }
24
+ unless total == total_score
25
+ raise "Flay total is now #{total}, but expected #{total_score}"
26
+ end
27
+
28
+ # run flay a second time with the threshold set
29
+ flay = Flay.new(:fuzzy => false, :verbose => false, :mass => threshold.succ)
30
+ flay.process(*files)
31
+
32
+ if flay.masses.any?
33
+ flay.report
34
+ raise "#{flay.masses.size} chunks of code have a duplicate mass > #{threshold}"
35
+ end
36
+ end
37
+ rescue LoadError
38
+ task :flay do
39
+ abort 'Flay is not available. In order to run flay, you must: gem install flay'
40
+ end
41
+ end