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
@@ -2,75 +2,89 @@ require 'spec_helper'
2
2
 
3
3
  shared_examples_for 'an invalid cli run' do
4
4
  it 'should raise error' do
5
- expect { subject }.to raise_error(described_class::Error, expected_message)
5
+ expect { subject }.to raise_error(Mutant::CLI::Error, expected_message)
6
6
  end
7
7
  end
8
8
 
9
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) }
10
+ subject { cli.config }
11
+ its(:filter) { should eql(expected_filter) }
12
+ its(:strategy) { should eql(expected_strategy) }
13
+ its(:reporter) { should eql(expected_reporter) }
14
+ its(:matcher) { should eql(expected_matcher) }
14
15
  end
15
16
 
16
17
  describe Mutant::CLI, '.new' do
17
18
 
19
+ let(:object) { described_class }
20
+ let(:time) { Time.now }
21
+
18
22
  before do
19
- pending
23
+ Time.stub(:now => time)
20
24
  end
21
25
 
22
- let(:object) { described_class }
23
-
24
26
  # 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) }
27
+ let(:expected_filter) { Mutant::Mutation::Filter::ALL }
28
+ let(:expected_strategy) { Mutant::Strategy::Rspec::Unit }
29
+ let(:expected_reporter) { Mutant::Reporter::CLI.new($stdout) }
30
+
31
+ let(:cli) { object.new(arguments) }
32
+
33
+ subject { cli }
34
+
35
+ context 'with unknown flag' do
36
+ let(:arguments) { %w(--invalid) }
37
+
38
+ let(:expected_message) { 'invalid option: --invalid' }
28
39
 
29
- subject { object.new(arguments) }
40
+ it_should_behave_like 'an invalid cli run'
41
+ end
30
42
 
31
43
  context 'with unknown option' do
32
44
  let(:arguments) { %w(--invalid Foo) }
33
45
 
34
- let(:expected_message) { 'Unknown option: "--invalid"' }
46
+ let(:expected_message) { 'invalid option: --invalid' }
35
47
 
36
48
  it_should_behave_like 'an invalid cli run'
37
49
  end
38
50
 
51
+ context 'with many strategy flags' do
52
+ let(:arguments) { %w(--rspec-unit --rspec-dm2) }
53
+
54
+ let(:expected_strategy) { Mutant::Strategy::Rspec::DM2 }
55
+ end
56
+
39
57
  context 'without arguments' do
40
58
  let(:arguments) { [] }
41
59
 
42
- let(:expected_message) { 'No matchers given' }
60
+ let(:expected_message) { 'No strategy was set!' }
43
61
 
44
62
  it_should_behave_like 'an invalid cli run'
45
63
  end
46
64
 
47
65
  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' }
66
+ let(:arguments) { %w(--rspec-unit --code) }
67
+ let(:expected_message) { 'missing argument: --code' }
51
68
 
52
69
  it_should_behave_like 'an invalid cli run'
53
70
  end
54
71
 
55
72
  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') }
73
+ let(:arguments) { %w(--rspec-unit TestApp::Literal#float) }
74
+ let(:expected_matcher) { Mutant::CLI::Classifier::Method.new('TestApp::Literal#float') }
59
75
 
60
76
  it_should_behave_like 'a cli parser'
61
-
62
77
  end
63
78
 
64
- context 'with library name' do
65
- let(:arguments) { %w(::TestApp) }
66
-
67
- let(:expected_matcher) { Mutant::Matcher::ObjectSpace.new(%r(\ATestApp(\z|::))) }
79
+ context 'with namespace matcher' do
80
+ let(:arguments) { %w(--rspec-unit ::TestApp*) }
81
+ let(:expected_matcher) { Mutant::CLI::Classifier::Namespace::Recursive.new('::TestApp*') }
68
82
 
69
83
  it_should_behave_like 'a cli parser'
70
84
  end
71
85
 
72
86
  context 'with code filter' do
73
- let(:arguments) { %w(--code faa --code bbb TestApp::Literal#float) }
87
+ let(:arguments) { %w(--rspec-unit --code faa --code bbb TestApp::Literal#float) }
74
88
 
75
89
  let(:filters) do
76
90
  [
@@ -79,8 +93,8 @@ describe Mutant::CLI, '.new' do
79
93
  ]
80
94
  end
81
95
 
82
- let(:expected_matcher) { Mutant::Matcher::Method.parse('TestApp::Literal#float') }
83
- let(:expected_filter) { Mutant::Mutation::Filter::Whitelist.new(filters) }
96
+ let(:expected_matcher) { Mutant::CLI::Classifier::Method.new('TestApp::Literal#float') }
97
+ let(:expected_filter) { Mutant::Mutation::Filter::Whitelist.new(filters) }
84
98
 
85
99
  it_should_behave_like 'a cli parser'
86
100
  end
@@ -3,36 +3,38 @@ require 'spec_helper'
3
3
  describe Mutant::CLI, '.run' do
4
4
  subject { object.run(argv) }
5
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
6
+ let(:object) { described_class }
7
+ let(:argv) { mock('ARGV') }
8
+ let(:attributes) { mock('Options') }
9
+ let(:runner) { mock('Runner', :success? => success) }
10
+ let(:config) { mock('Config') }
11
+ let(:instance) { mock(described_class.name, :config => config) }
12
+
13
+ before do
13
14
  described_class.stub(:new => instance)
14
- Mutant::Runner.stub(:run => runner)
15
+ Mutant::Runner::Config.stub(:run => runner)
15
16
  end
16
17
 
17
- context 'when runner does NOT fail' do
18
- let(:failure) { false }
18
+ context 'when runner is successful' do
19
+ let(:success) { true }
19
20
 
20
21
  it { should be(0) }
21
22
 
22
23
  it 'should run with attributes' do
23
- Mutant::Runner.should_receive(:run).with(instance).and_return(runner)
24
+ Mutant::Runner::Config.should_receive(:run).with(config).and_return(runner)
24
25
  should be(0)
25
26
  end
26
27
  end
27
28
 
28
29
  context 'when runner fails' do
29
- let(:failure) { true }
30
+ let(:success) { false }
30
31
 
31
32
  it { should be(1) }
32
33
 
33
34
  it 'should run with attributes' do
34
- Mutant::Runner.should_receive(:run).with(instance).and_return(runner)
35
+ Mutant::Runner::Config.should_receive(:run).with(config).and_return(runner)
35
36
  should be(1)
36
37
  end
37
38
  end
39
+
38
40
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::CLI::Classifier, '.build' do
4
+ subject { described_class.build(input) }
5
+
6
+ this_spec = 'Mutant::CLI::Classifier.build'
7
+
8
+ shared_examples_for this_spec do
9
+ it 'shoud return expected instance' do
10
+ should eql(expected_class.new(expected_class::REGEXP.match(input)))
11
+ end
12
+ end
13
+
14
+ context 'with explicit toplevel scope' do
15
+
16
+ let(:input) { '::TestApp::Literal#string' }
17
+ let(:expected_class) { Mutant::CLI::Classifier::Method }
18
+
19
+ it_should_behave_like this_spec
20
+ end
21
+
22
+ context 'with instance method notation' do
23
+
24
+ let(:input) { 'TestApp::Literal#string' }
25
+ let(:expected_class) { Mutant::CLI::Classifier::Method }
26
+
27
+ it_should_behave_like this_spec
28
+ end
29
+
30
+ context 'with singleton method notation' do
31
+ let(:input) { 'TestApp::Literal.string' }
32
+ let(:expected_class) { Mutant::CLI::Classifier::Method }
33
+
34
+ it_should_behave_like this_spec
35
+ end
36
+
37
+ context 'with invalid notation' do
38
+ let(:input) { '::' }
39
+
40
+ it 'should return nil' do
41
+ should be(nil)
42
+ end
43
+ end
44
+ end
@@ -5,13 +5,13 @@ describe Mutant::Context::Scope, '#root' do
5
5
 
6
6
  let(:object) { described_class.new(TestApp::Literal, path) }
7
7
  let(:path) { mock('Path') }
8
- let(:node) { ':node'.to_ast }
8
+ let(:node) { parse(':node') }
9
9
 
10
10
  let(:scope) { subject.body }
11
11
  let(:scope_body) { scope.body }
12
12
 
13
13
  let(:expected_source) do
14
- ToSource.to_source(<<-RUBY.to_ast)
14
+ generate(parse(<<-RUBY))
15
15
  module TestApp
16
16
  class Literal
17
17
  :node
@@ -21,11 +21,11 @@ describe Mutant::Context::Scope, '#root' do
21
21
  end
22
22
 
23
23
  let(:generated_source) do
24
- ToSource.to_source(subject)
24
+ Unparser.unparse(subject)
25
25
  end
26
26
 
27
27
  let(:round_tripped_source) do
28
- ToSource.to_source(expected_source.to_ast)
28
+ Unparser.unparse(parse(expected_source))
29
29
  end
30
30
 
31
31
  it 'should create correct source' do
@@ -4,9 +4,10 @@ describe Mutant::Killer::Rspec, '.new' do
4
4
 
5
5
  subject { object.new(strategy, mutation) }
6
6
 
7
- let(:strategy) { mock('Strategy', :spec_files => ['foo'], :error_stream => $stderr, :output_stream => $stdout) }
8
- let(:context) { mock('Context') }
9
- let(:mutation) { mock('Mutation') }
7
+ let(:strategy) { mock('Strategy', :spec_files => ['foo'], :error_stream => $stderr, :output_stream => $stdout) }
8
+ let(:context) { mock('Context') }
9
+ let(:mutation) { mock('Mutation', :subject => mutation_subject) }
10
+ let(:mutation_subject) { mock('Mutation Subject') }
10
11
 
11
12
  let(:object) { described_class }
12
13
 
@@ -19,14 +20,14 @@ describe Mutant::Killer::Rspec, '.new' do
19
20
  context 'when run exits zero' do
20
21
  let(:exit_status) { 0 }
21
22
 
22
- its(:fail?) { should be(true) }
23
+ its(:killed?) { should be(false) }
23
24
  it { should be_a(described_class) }
24
25
  end
25
26
 
26
27
  context 'when run exits nonzero' do
27
28
  let(:exit_status) { 1 }
28
29
 
29
- its(:fail?) { should be(false) }
30
+ its(:killed?) { should be(true) }
30
31
  it { should be_a(described_class) }
31
32
  end
32
33
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Killer, '#success?' do
4
+ subject { object.success? }
5
+
6
+ let(:object) { class_under_test.new(strategy, mutation) }
7
+ let(:strategy) { mock('Strategy') }
8
+ let(:mutation) { mock('Mutation', :success? => kill_state) }
9
+ let(:kill_state) { mock('Kill State') }
10
+
11
+ before do
12
+ kill_state.stub(:freeze => kill_state, :dup => kill_state)
13
+ end
14
+
15
+ let(:class_under_test) do
16
+ Class.new(described_class) do
17
+ def run
18
+ end
19
+ end
20
+ end
21
+
22
+ it_should_behave_like 'an idempotent method'
23
+
24
+ it 'should use kill state to gather success' do
25
+ mutation.should_receive(:success?).with(object).and_return(kill_state)
26
+ should be(kill_state)
27
+ end
28
+ end
@@ -26,7 +26,7 @@ describe Mutant::Loader::Eval, '.run' do
26
26
  end
27
27
 
28
28
  let(:node) do
29
- source.to_ast
29
+ parse(source)
30
30
  end
31
31
 
32
32
  it 'should load nodes into vm' do
@@ -12,7 +12,7 @@ describe Mutant::Matcher::Chain, '#each' do
12
12
 
13
13
  let(:subject_a) { mock('Subject A') }
14
14
  let(:subject_b) { mock('Subject B') }
15
-
15
+
16
16
  before do
17
17
  matcher_a.stub(:each).and_yield(subject_a).and_return(matcher_a)
18
18
  matcher_b.stub(:each).and_yield(subject_b).and_return(matcher_b)
@@ -4,7 +4,7 @@ describe Mutant::Matcher::Chain, '#matchers' do
4
4
  subject { object.matchers }
5
5
 
6
6
  let(:object) { described_class.new(matchers) }
7
- let(:matchers) { mock('Matchers') }
7
+ let(:matchers) { mock('Matchers') }
8
8
 
9
9
  it { should be(matchers) }
10
10
 
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Method::Instance, '#each' do
4
+ let(:object) { described_class.new(scope, method) }
5
+ let(:method) { scope.instance_method(method_name) }
6
+
7
+ let(:yields) { [] }
8
+
9
+ let(:namespace) do
10
+ klass = self.class
11
+ end
12
+
13
+ let(:scope) { self.class::Foo }
14
+
15
+ subject { object.each { |subject| yields << subject } }
16
+
17
+ let(:type) { :def }
18
+ let(:method_name) { :bar }
19
+ let(:method_arity) { 0 }
20
+
21
+ def name
22
+ node.children[0]
23
+ end
24
+
25
+ def arguments
26
+ node.children[1]
27
+ end
28
+
29
+ context 'when method is defined once' do
30
+ let(:base) { __LINE__ }
31
+ class self::Foo
32
+ def bar; end
33
+ end
34
+
35
+ let(:method_line) { 2 }
36
+
37
+ it_should_behave_like 'a method matcher'
38
+ end
39
+
40
+ context 'when method is defined multiple times' do
41
+ context 'on differend lines' do
42
+ let(:base) { __LINE__ }
43
+ class self::Foo
44
+ def bar; end
45
+ def bar(arg); end
46
+ end
47
+
48
+ let(:method_line) { 3 }
49
+ let(:method_arity) { 1 }
50
+
51
+ it_should_behave_like 'a method matcher'
52
+ end
53
+
54
+ context 'on the same line' do
55
+ let(:base) { __LINE__ }
56
+ class self::Foo
57
+ def bar; end; def bar(arg); end
58
+ end
59
+
60
+ let(:method_line) { 2 }
61
+ let(:method_arity) { 1 }
62
+
63
+ it_should_behave_like 'a method matcher'
64
+ end
65
+
66
+ context 'on the same line with differend scope' do
67
+ let(:base) { __LINE__ }
68
+ class self::Foo
69
+ def self.bar; end; def bar(arg); end
70
+ end
71
+
72
+ let(:method_line) { 2 }
73
+ let(:method_arity) { 1 }
74
+
75
+ it_should_behave_like 'a method matcher'
76
+ end
77
+
78
+ context 'when nested' do
79
+ let(:pattern) { 'Foo::Bar#baz' }
80
+
81
+ context 'in class' do
82
+ let(:base) { __LINE__ }
83
+ class self::Foo
84
+ class Bar
85
+ def baz; end
86
+ end
87
+ end
88
+
89
+ let(:method_line) { 3 }
90
+ let(:method_name) { :baz }
91
+ let(:scope) { self.class::Foo::Bar }
92
+
93
+ it_should_behave_like 'a method matcher'
94
+ end
95
+
96
+ context 'in module' do
97
+ let(:base) { __LINE__ }
98
+ module self::Foo
99
+ class Bar
100
+ def baz; end
101
+ end
102
+ end
103
+
104
+ let(:method_line) { 3 }
105
+ let(:method_name) { :baz }
106
+ let(:scope) { self.class::Foo::Bar }
107
+
108
+ it_should_behave_like 'a method matcher'
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Method::Singleton, '#each' do
4
+ let(:object) { described_class.new(scope, method) }
5
+ let(:method) { scope.method(method_name) }
6
+
7
+ let(:yields) { [] }
8
+
9
+ let(:namespace) do
10
+ klass = self.class
11
+ end
12
+
13
+ let(:scope) { self.class::Foo }
14
+
15
+ subject { object.each { |subject| yields << subject } }
16
+
17
+ let(:type) { :defs }
18
+ let(:method_arity) { 0 }
19
+
20
+ def name
21
+ node.children[1]
22
+ end
23
+
24
+ def arguments
25
+ node.children[2]
26
+ end
27
+
28
+ context 'on singleton methods' do
29
+
30
+ context 'when defined on self' do
31
+ let(:base) { __LINE__ }
32
+ class self::Foo
33
+ def self.bar; end
34
+ end
35
+
36
+ let(:method_name) { :bar }
37
+ let(:method_line) { 2 }
38
+
39
+ it_should_behave_like 'a method matcher'
40
+ end
41
+
42
+ context 'when defined on constant' do
43
+
44
+ context 'inside namespace' do
45
+ let(:base) { __LINE__ }
46
+ module self::Namespace
47
+ class Foo
48
+ def Foo.bar; end
49
+ end
50
+ end
51
+
52
+ let(:scope) { self.class::Namespace::Foo }
53
+ let(:method_name) { :bar }
54
+ let(:method_line) { 3 }
55
+
56
+ it_should_behave_like 'a method matcher'
57
+ end
58
+
59
+ context 'outside namespace' do
60
+ let(:base) { __LINE__ }
61
+ module self::Namespace
62
+ class Foo; end;
63
+ def Foo.bar; end
64
+ end
65
+
66
+ let(:method_name) { :bar }
67
+ let(:method_line) { 3 }
68
+ let(:scope) { self.class::Namespace::Foo }
69
+
70
+ it_should_behave_like 'a method matcher'
71
+ end
72
+ end
73
+
74
+ context 'when defined multiple times in the same line' do
75
+ context 'with method on differend scope' do
76
+ let(:base) { __LINE__ }
77
+ module self::Namespace
78
+ module Foo; end
79
+ module Bar
80
+ def self.baz; end; def Foo.baz(arg); end
81
+ end
82
+ end
83
+
84
+ let(:scope) { self.class::Namespace::Bar }
85
+ let(:method_name) { :baz }
86
+ let(:method_line) { 4 }
87
+ let(:method_arity) { 0 }
88
+
89
+ it_should_behave_like 'a method matcher'
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Methods::Instance, '#each' do
4
+ let(:object) { described_class.new(Foo) }
5
+
6
+ subject { object.each { |matcher| yields << matcher } }
7
+
8
+ let(:yields) { [] }
9
+
10
+ module Bar
11
+ def method_d
12
+ end
13
+
14
+ def method_e
15
+ end
16
+ end
17
+
18
+ class Foo
19
+ include Bar
20
+
21
+ private :method_d
22
+
23
+ public
24
+
25
+ def method_a
26
+ end
27
+
28
+ protected
29
+
30
+ def method_b
31
+ end
32
+
33
+ private
34
+
35
+ def method_c
36
+ end
37
+
38
+ end
39
+
40
+ let(:subject_a) { mock('Subject A') }
41
+ let(:subject_b) { mock('Subject B') }
42
+ let(:subject_c) { mock('Subject C') }
43
+
44
+ let(:subjects) { [subject_a, subject_b, subject_c] }
45
+
46
+ before do
47
+ matcher = Mutant::Matcher::Method::Instance
48
+ matcher.stub(:new).with(Foo, Foo.instance_method(:method_a)).and_return([subject_a])
49
+ matcher.stub(:new).with(Foo, Foo.instance_method(:method_b)).and_return([subject_b])
50
+ matcher.stub(:new).with(Foo, Foo.instance_method(:method_c)).and_return([subject_c])
51
+ end
52
+
53
+ it 'should yield expected subjects' do
54
+ subject
55
+ yields.should eql(subjects)
56
+ end
57
+
58
+ it_should_behave_like 'an #each method'
59
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Methods::Singleton, '#each' do
4
+ let(:object) { described_class.new(Foo) }
5
+
6
+ subject { object.each { |matcher| yields << matcher } }
7
+
8
+ let(:yields) { [] }
9
+
10
+ module Bar
11
+ def method_d
12
+ end
13
+
14
+ def method_e
15
+ end
16
+ end
17
+
18
+ class Foo
19
+ extend Bar
20
+
21
+ def self.method_a
22
+ end
23
+
24
+ def self.method_b
25
+ end
26
+ class << self; protected :method_b; end
27
+
28
+ def self.method_c
29
+ end
30
+ private_class_method :method_c
31
+
32
+ end
33
+
34
+ let(:subject_a) { mock('Subject A') }
35
+ let(:subject_b) { mock('Subject B') }
36
+ let(:subject_c) { mock('Subject C') }
37
+
38
+ let(:subjects) { [subject_a, subject_b, subject_c] }
39
+
40
+ before do
41
+ matcher = Mutant::Matcher::Method::Singleton
42
+ matcher.stub(:new).with(Foo, Foo.method(:method_a)).and_return([subject_a])
43
+ matcher.stub(:new).with(Foo, Foo.method(:method_b)).and_return([subject_b])
44
+ matcher.stub(:new).with(Foo, Foo.method(:method_c)).and_return([subject_c])
45
+ end
46
+
47
+ it 'should yield expected subjects' do
48
+ subject
49
+ yields.should eql(subjects)
50
+ end
51
+
52
+ it_should_behave_like 'an #each method'
53
+ end