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,87 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'an invalid cli run' do
4
+ it 'should raise error' do
5
+ expect { subject }.to raise_error(described_class::Error, expected_message)
6
+ end
7
+ end
8
+
9
+ shared_examples_for 'a cli parser' do
10
+ its(:filter) { should eql(expected_filter) }
11
+ its(:killer) { should eql(expected_killer) }
12
+ its(:reporter) { should eql(expected_reporter) }
13
+ its(:matcher) { should eql(expected_matcher) }
14
+ end
15
+
16
+ describe Mutant::CLI, '.new' do
17
+
18
+ before do
19
+ pending
20
+ end
21
+
22
+ let(:object) { described_class }
23
+
24
+ # Defaults
25
+ let(:expected_filter) { Mutant::Mutation::Filter::ALL }
26
+ let(:expected_killer) { Mutant::Killer::Rspec::Forking }
27
+ let(:expected_reporter) { Mutant::Reporter::CLI.new($stderr) }
28
+
29
+ subject { object.new(arguments) }
30
+
31
+ context 'with unknown option' do
32
+ let(:arguments) { %w(--invalid Foo) }
33
+
34
+ let(:expected_message) { 'Unknown option: "--invalid"' }
35
+
36
+ it_should_behave_like 'an invalid cli run'
37
+ end
38
+
39
+ context 'without arguments' do
40
+ let(:arguments) { [] }
41
+
42
+ let(:expected_message) { 'No matchers given' }
43
+
44
+ it_should_behave_like 'an invalid cli run'
45
+ end
46
+
47
+ context 'with code filter and missing argument' do
48
+ let(:arguments) { %w(--rspec-unit --code) }
49
+
50
+ let(:expected_message) { '"--code" is missing an argument' }
51
+
52
+ it_should_behave_like 'an invalid cli run'
53
+ end
54
+
55
+ context 'with explicit method matcher' do
56
+ let(:arguments) { %w(TestApp::Literal#float) }
57
+
58
+ let(:expected_matcher) { Mutant::Matcher::Method.parse('TestApp::Literal#float') }
59
+
60
+ it_should_behave_like 'a cli parser'
61
+
62
+ end
63
+
64
+ context 'with library name' do
65
+ let(:arguments) { %w(::TestApp) }
66
+
67
+ let(:expected_matcher) { Mutant::Matcher::ObjectSpace.new(%r(\ATestApp(\z|::))) }
68
+
69
+ it_should_behave_like 'a cli parser'
70
+ end
71
+
72
+ context 'with code filter' do
73
+ let(:arguments) { %w(--code faa --code bbb TestApp::Literal#float) }
74
+
75
+ let(:filters) do
76
+ [
77
+ Mutant::Mutation::Filter::Code.new('faa'),
78
+ Mutant::Mutation::Filter::Code.new('bbb'),
79
+ ]
80
+ end
81
+
82
+ let(:expected_matcher) { Mutant::Matcher::Method.parse('TestApp::Literal#float') }
83
+ let(:expected_filter) { Mutant::Mutation::Filter::Whitelist.new(filters) }
84
+
85
+ it_should_behave_like 'a cli parser'
86
+ end
87
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::CLI, '.run' do
4
+ subject { object.run(argv) }
5
+
6
+ let(:object) { described_class }
7
+ let(:argv) { mock('ARGV') }
8
+ let(:attributes) { mock('Options') }
9
+ let(:runner) { mock('Runner', :fail? => failure) }
10
+ let(:instance) { mock(described_class.name, :attributes => attributes) }
11
+
12
+ before do
13
+ described_class.stub(:new => instance)
14
+ Mutant::Runner.stub(:run => runner)
15
+ end
16
+
17
+ context 'when runner does NOT fail' do
18
+ let(:failure) { false }
19
+
20
+ it { should be(0) }
21
+
22
+ it 'should run with attributes' do
23
+ Mutant::Runner.should_receive(:run).with(instance).and_return(runner)
24
+ should be(0)
25
+ end
26
+ end
27
+
28
+ context 'when runner fails' do
29
+ let(:failure) { true }
30
+
31
+ it { should be(1) }
32
+
33
+ it 'should run with attributes' do
34
+ Mutant::Runner.should_receive(:run).with(instance).and_return(runner)
35
+ should be(1)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Context, '#root' do
4
+ subject { object.root(mock) }
5
+
6
+ let(:object) { described_class.allocate }
7
+
8
+ it 'should raise error' do
9
+ expect { subject }.to raise_error('Mutant::Context#root is not implemented')
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Context::Scope, '.build' do
4
+ subject { described_class.build(constant, path) }
5
+
6
+ let(:object) { described_class }
7
+ let(:context) { mock('Context') }
8
+ let(:path) { mock('Path') }
9
+
10
+ context 'when constant is a module' do
11
+ let(:constant) { Module.new }
12
+
13
+ it { should be_kind_of(described_class::Module) }
14
+ end
15
+
16
+ context 'when constant is a class' do
17
+ let(:constant) { Class.new }
18
+
19
+ it { should be_kind_of(described_class::Class) }
20
+ end
21
+
22
+ context 'when constant is not a class nor a module' do
23
+ let(:constant) { Object.new }
24
+
25
+ it 'should raise error' do
26
+ expect { subject }.to raise_error(ArgumentError, 'Can only build mutation scope from class or module got: Object')
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Context::Scope, '#root' do
4
+ subject { object.root(node) }
5
+
6
+ let(:object) { described_class.build(TestApp::Literal, path) }
7
+ let(:path) { mock('Path') }
8
+ let(:node) { mock('Node') }
9
+
10
+ let(:scope) { subject.body }
11
+ let(:scope_body) { scope.body }
12
+
13
+ it 'should wrap the ast under constant' do
14
+ scope.should be_kind_of(Rubinius::AST::ClassScope)
15
+ end
16
+
17
+ it 'should place the ast under scope inside of block' do
18
+ scope_body.should be_a(Rubinius::AST::Block)
19
+ scope_body.array.should eql([node])
20
+ scope_body.array.first.should be(node)
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Context::Scope, '#unqualified_name' do
4
+ subject { object.unqualified_name }
5
+
6
+ let(:path) { mock('Path') }
7
+
8
+ context 'with top level constant name' do
9
+ let(:object) { described_class.build(TestApp, path) }
10
+
11
+ it 'should return the unqualified name' do
12
+ should eql('TestApp')
13
+ end
14
+
15
+ it_should_behave_like 'an idempotent method'
16
+ end
17
+
18
+ context 'with scoped constant name' do
19
+ let(:object) { described_class.build(TestApp::Literal, path) }
20
+
21
+ it 'should return the unqualified name' do
22
+ should eql('Literal')
23
+ end
24
+
25
+ it_should_behave_like 'an idempotent method'
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Killer,'#fail?' do
4
+ subject { object.fail? }
5
+
6
+ let(:object) { class_under_test.new(strategy, mutation) }
7
+ let(:strategy) { mock('Strategy') }
8
+ let(:mutation) { mock('Mutation') }
9
+
10
+ before do
11
+ mutation.stub(:insert)
12
+ mutation.stub(:reset)
13
+ end
14
+
15
+ let(:class_under_test) do
16
+ kill_state = self.kill_state
17
+ Class.new(described_class) do
18
+ define_method :run do
19
+ kill_state
20
+ end
21
+ end
22
+ end
23
+
24
+ context 'when mutant was killed' do
25
+ let(:kill_state) { true }
26
+
27
+ it_should_behave_like 'an idempotent method'
28
+
29
+ it { should be(false) }
30
+ end
31
+
32
+ context 'when mutant was NOT killed' do
33
+ let(:kill_state) { false }
34
+
35
+ it_should_behave_like 'an idempotent method'
36
+
37
+ it { should be(true) }
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Killer::Rspec, '.new' do
4
+
5
+ subject { object.new(strategy, mutation) }
6
+
7
+ let(:strategy) { mock('Strategy', :spec_files => ['foo']) }
8
+ let(:context) { mock('Context') }
9
+ let(:mutation) { mock('Mutation') }
10
+
11
+ let(:object) { described_class }
12
+
13
+ before do
14
+ mutation.stub(:insert)
15
+ mutation.stub(:reset)
16
+ RSpec::Core::Runner.stub(:run => exit_status)
17
+ end
18
+
19
+ context 'when run exits zero' do
20
+ let(:exit_status) { 0 }
21
+
22
+ its(:fail?) { should be(true) }
23
+ it { should be_a(described_class) }
24
+ end
25
+
26
+ context 'when run exits nonzero' do
27
+ let(:exit_status) { 1 }
28
+
29
+ its(:fail?) { should be(false) }
30
+ it { should be_a(described_class) }
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Loader::Eval, '.run' do
4
+
5
+ subject { object.run(node) }
6
+
7
+ let(:object) { described_class }
8
+
9
+ let(:source) do
10
+ # This test case will blow up when not executed
11
+ # under toplevel binding.
12
+ <<-RUBY
13
+ class SomeNamespace
14
+ class Bar
15
+ end
16
+
17
+ class SomeOther
18
+ class Foo < Bar
19
+ end
20
+ end
21
+ end
22
+ RUBY
23
+ end
24
+
25
+ let(:node) do
26
+ source.to_ast
27
+ end
28
+
29
+ it 'should load nodes into vm' do
30
+ subject
31
+ ::SomeNamespace::SomeOther::Foo
32
+ end
33
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Loader::Rubinius, '.run' do
4
+ before do
5
+ pending
6
+ end
7
+
8
+ subject { object.run(node) }
9
+
10
+ let(:object) { described_class }
11
+
12
+ after do
13
+ Object.send(:remove_const, :SomeNamespace)
14
+ end
15
+
16
+ let(:source) do
17
+ # This test case will blow up when not executed
18
+ # under toplevel binding.
19
+ <<-RUBY
20
+ class SomeNamespace
21
+ class Bar
22
+ end
23
+
24
+ class SomeOther
25
+ class Foo < Bar
26
+ end
27
+ end
28
+ end
29
+ RUBY
30
+ end
31
+
32
+ let(:node) do
33
+ Rubinius::AST::Script.new(source.to_ast).tap do |source|
34
+ source.file = "/some/source"
35
+ end
36
+ end
37
+
38
+ it 'should load nodes into vm' do
39
+ subject
40
+ SomeNamespace::SomeOther::Foo
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Chain, '#each' do
4
+ subject { object.each { |entry| yields << entry } }
5
+
6
+ let(:object) { described_class.new(matchers) }
7
+
8
+ let(:matchers) { [matcher_a, matcher_b] }
9
+
10
+ let(:matcher_a) { mock('Matcher A') }
11
+ let(:matcher_b) { mock('Matcher B') }
12
+
13
+ let(:subject_a) { mock('Subject A') }
14
+ let(:subject_b) { mock('Subject B') }
15
+
16
+ before do
17
+ matcher_a.stub(:each).and_yield(subject_a).and_return(matcher_a)
18
+ matcher_b.stub(:each).and_yield(subject_b).and_return(matcher_b)
19
+ end
20
+
21
+ # it_should_behave_like 'an #each method'
22
+ context 'with no block' do
23
+ subject { object.each }
24
+
25
+ it { should be_instance_of(to_enum.class) }
26
+
27
+ it 'yields the expected values' do
28
+ subject.to_a.should eql(object.to_a)
29
+ end
30
+ end
31
+
32
+ let(:yields) { [] }
33
+
34
+ it 'should yield subjects' do
35
+ expect { subject }.to change { yields }.from([]).to([subject_a, subject_b])
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Chain, '#matchers' do
4
+ subject { object.matchers }
5
+
6
+ let(:object) { described_class.new(matchers) }
7
+ let(:matchers) { mock('Matchers') }
8
+
9
+ it { should be(matchers) }
10
+
11
+ it_should_behave_like 'an idempotent method'
12
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher, '.from_string' do
4
+ subject { object.from_string(input) }
5
+
6
+ let(:input) { mock('Input') }
7
+ let(:matcher) { mock('Matcher') }
8
+
9
+ let(:descendant_a) { mock('Descendant A', :parse => nil) }
10
+ let(:descendant_b) { mock('Descendant B', :parse => nil) }
11
+
12
+ let(:object) { described_class }
13
+
14
+ before do
15
+ described_class.stub(:descendants => [descendant_a, descendant_b])
16
+ end
17
+
18
+ context 'when no descendant takes the input' do
19
+ it { should be(nil) }
20
+
21
+ it_should_behave_like 'an idempotent method'
22
+ end
23
+
24
+ context 'when one descendant handles input' do
25
+ before do
26
+ descendant_a.stub(:parse => matcher)
27
+ end
28
+
29
+ it { should be(matcher) }
30
+
31
+ it_should_behave_like 'an idempotent method'
32
+ end
33
+
34
+ context 'when more than one descendant handles input' do
35
+ let(:matcher_b) { mock('Matcher B') }
36
+
37
+ before do
38
+ descendant_a.stub(:parse => matcher)
39
+ descendant_b.stub(:parse => matcher_b)
40
+ end
41
+
42
+ it 'should return the first matcher' do
43
+ should be(matcher)
44
+ end
45
+
46
+ it_should_behave_like 'an idempotent method'
47
+ end
48
+ end
49
+