mutant 0.2.4 → 0.2.5

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 (58) hide show
  1. data/.travis.yml +3 -3
  2. data/Changelog.md +21 -0
  3. data/Gemfile.devtools +1 -0
  4. data/Guardfile +1 -1
  5. data/README.md +48 -4
  6. data/config/flay.yml +2 -2
  7. data/config/flog.yml +1 -1
  8. data/config/site.reek +3 -1
  9. data/lib/mutant.rb +14 -2
  10. data/lib/mutant/cli.rb +38 -39
  11. data/lib/mutant/context/scope.rb +37 -32
  12. data/lib/mutant/killer/forking.rb +53 -0
  13. data/lib/mutant/killer/rspec.rb +1 -1
  14. data/lib/mutant/killer/static.rb +14 -0
  15. data/lib/mutant/matcher.rb +2 -0
  16. data/lib/mutant/matcher/method.rb +2 -2
  17. data/lib/mutant/matcher/method/singleton.rb +2 -1
  18. data/lib/mutant/matcher/object_space.rb +1 -1
  19. data/lib/mutant/matcher/scope_methods.rb +2 -0
  20. data/lib/mutant/mutation.rb +26 -0
  21. data/lib/mutant/mutation/filter/whitelist.rb +1 -1
  22. data/lib/mutant/mutator.rb +52 -9
  23. data/lib/mutant/mutator/node.rb +18 -19
  24. data/lib/mutant/mutator/node/arguments.rb +156 -0
  25. data/lib/mutant/mutator/node/block.rb +7 -20
  26. data/lib/mutant/mutator/node/define.rb +18 -1
  27. data/lib/mutant/mutator/node/iter_19.rb +26 -0
  28. data/lib/mutant/mutator/node/local_variable_assignment.rb +25 -0
  29. data/lib/mutant/mutator/node/noop.rb +4 -0
  30. data/lib/mutant/mutator/node/send.rb +24 -10
  31. data/lib/mutant/mutator/util.rb +28 -1
  32. data/lib/mutant/random.rb +1 -0
  33. data/lib/mutant/reporter.rb +28 -0
  34. data/lib/mutant/reporter/cli.rb +90 -19
  35. data/lib/mutant/reporter/null.rb +5 -3
  36. data/lib/mutant/reporter/stats.rb +65 -9
  37. data/lib/mutant/runner.rb +41 -2
  38. data/lib/mutant/strategy.rb +46 -5
  39. data/lib/mutant/strategy/rspec.rb +11 -4
  40. data/lib/mutant/strategy/rspec/example_lookup.rb +30 -30
  41. data/lib/mutant/subject.rb +11 -0
  42. data/mutant.gemspec +3 -2
  43. data/spec/integration/mutant/loader_spec.rb +4 -4
  44. data/spec/shared/mutator_behavior.rb +13 -1
  45. data/spec/unit/mutant/context/scope/root_spec.rb +20 -8
  46. data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +2 -2
  47. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +1 -1
  48. data/spec/unit/mutant/matcher/chain/each_spec.rb +6 -2
  49. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +76 -0
  50. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +80 -21
  51. data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +3 -3
  52. metadata +21 -10
  53. data/lib/mutant/inflector/defaults.rb +0 -64
  54. data/lib/mutant/inflector/inflections.rb +0 -211
  55. data/lib/mutant/inflector/methods.rb +0 -151
  56. data/lib/mutant/inflector/version.rb +0 -5
  57. data/locator.rb +0 -87
  58. data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +0 -29
@@ -7,11 +7,11 @@ class CodeLoadingSubject
7
7
  end
8
8
 
9
9
  describe Mutant, 'code loading' do
10
- let(:context) { Mutant::Context::Scope.build(CodeLoadingSubject,"/some/path") }
11
- let(:node) { 'def foo; :bar; end'.to_ast }
12
- let(:root) { context.root(node) }
10
+ let(:context) { Mutant::Context::Scope.new(CodeLoadingSubject, "/some/path") }
11
+ let(:node) { 'def foo; :bar; end'.to_ast }
12
+ let(:root) { context.root(node) }
13
13
 
14
- subject { Mutant::Loader::Eval.run(root) }
14
+ subject { Mutant::Loader::Eval.run(root) }
15
15
 
16
16
  before { subject }
17
17
 
@@ -15,13 +15,25 @@ shared_examples_for 'a mutator' do
15
15
 
16
16
  it { should be_instance_of(to_enum.class) }
17
17
 
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]
24
+ end
25
+ end
26
+
18
27
  unless instance_methods.include?(:expected_mutations)
19
28
  let(:expected_mutations) do
20
29
  mutations.map do |mutation|
21
30
  case mutation
22
31
  when String
23
- mutation.to_ast
32
+ ast = mutation.to_ast
33
+ assert_transitive(ast)
34
+ ast
24
35
  when Rubinius::AST::Node
36
+ assert_transitive(mutation)
25
37
  mutation
26
38
  else
27
39
  raise
@@ -3,20 +3,32 @@ require 'spec_helper'
3
3
  describe Mutant::Context::Scope, '#root' do
4
4
  subject { object.root(node) }
5
5
 
6
- let(:object) { described_class.build(TestApp::Literal, path) }
6
+ let(:object) { described_class.new(TestApp::Literal, path) }
7
7
  let(:path) { mock('Path') }
8
- let(:node) { mock('Node') }
8
+ let(:node) { ':node'.to_ast }
9
9
 
10
10
  let(:scope) { subject.body }
11
11
  let(:scope_body) { scope.body }
12
12
 
13
- it 'should wrap the ast under constant' do
14
- scope.should be_kind_of(Rubinius::AST::ClassScope)
13
+ let(:expected_source) do
14
+ ToSource.to_source(<<-RUBY.to_ast)
15
+ module TestApp
16
+ class Literal
17
+ :node
18
+ end
19
+ end
20
+ RUBY
15
21
  end
16
22
 
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)
23
+ let(:generated_source) do
24
+ ToSource.to_source(subject)
25
+ end
26
+
27
+ let(:round_tripped_source) do
28
+ ToSource.to_source(expected_source.to_ast)
29
+ end
30
+
31
+ it 'should create correct source' do
32
+ generated_source.should eql(expected_source)
21
33
  end
22
34
  end
@@ -6,7 +6,7 @@ describe Mutant::Context::Scope, '#unqualified_name' do
6
6
  let(:path) { mock('Path') }
7
7
 
8
8
  context 'with top level constant name' do
9
- let(:object) { described_class.build(TestApp, path) }
9
+ let(:object) { described_class.new(TestApp, path) }
10
10
 
11
11
  it 'should return the unqualified name' do
12
12
  should eql('TestApp')
@@ -16,7 +16,7 @@ describe Mutant::Context::Scope, '#unqualified_name' do
16
16
  end
17
17
 
18
18
  context 'with scoped constant name' do
19
- let(:object) { described_class.build(TestApp::Literal, path) }
19
+ let(:object) { described_class.new(TestApp::Literal, path) }
20
20
 
21
21
  it 'should return the unqualified name' do
22
22
  should eql('Literal')
@@ -4,7 +4,7 @@ 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']) }
7
+ let(:strategy) { mock('Strategy', :spec_files => ['foo'], :error_stream => $stderr, :output_stream => $stdout) }
8
8
  let(:context) { mock('Context') }
9
9
  let(:mutation) { mock('Mutation') }
10
10
 
@@ -24,8 +24,12 @@ describe Mutant::Matcher::Chain, '#each' do
24
24
 
25
25
  it { should be_instance_of(to_enum.class) }
26
26
 
27
- it 'yields the expected values' do
28
- subject.to_a.should eql(object.to_a)
27
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
28
+ pending 'FIX RBX rspec? BUG HERE'
29
+ else
30
+ it 'yields the expected values' do
31
+ subject.to_a.should eql(object.to_a)
32
+ end
29
33
  end
30
34
  end
31
35
 
@@ -23,6 +23,54 @@ describe Mutant::Mutator, 'define' do
23
23
  it_should_behave_like 'a mutator'
24
24
  end
25
25
 
26
+ context 'with arguments' do
27
+ let(:source) { 'def foo(a, b); nil; end' }
28
+
29
+ before do
30
+ Mutant::Random.stub(:hex_string => 'random')
31
+ end
32
+
33
+ let(:mutations) do
34
+ mutations = []
35
+
36
+ # Deletion of each argument
37
+ mutations << 'def foo(a); nil; end'
38
+ mutations << 'def foo(b); nil; end'
39
+
40
+ # Deletion of all arguments
41
+ mutations << 'def foo; nil; end'
42
+
43
+ # Rename each argument
44
+ mutations << 'def foo(srandom, b); nil; end'
45
+ mutations << 'def foo(a, srandom); nil; end'
46
+
47
+ # Mutation of body
48
+ mutations << 'def foo(a, b); Object.new; end'
49
+ end
50
+
51
+ it_should_behave_like 'a mutator'
52
+ end
53
+
54
+ context 'default argument' do
55
+ let(:source) { 'def foo(a = "literal"); end' }
56
+
57
+ before do
58
+ Mutant::Random.stub(:hex_string => 'random')
59
+ end
60
+
61
+ let(:mutations) do
62
+ mutations = []
63
+ mutations << 'def foo(a); end'
64
+ mutations << 'def foo(); end'
65
+ mutations << 'def foo(a = "random"); end'
66
+ mutations << 'def foo(a = nil); end'
67
+ mutations << 'def foo(a = "literal"); Object.new; end'
68
+ mutations << 'def foo(srandom = "literal"); nil; end'
69
+ end
70
+
71
+ it_should_behave_like 'a mutator'
72
+ end
73
+
26
74
  context 'define on singleton' do
27
75
  let(:source) { 'def self.foo; self.bar; self.baz; end' }
28
76
 
@@ -44,4 +92,32 @@ describe Mutant::Mutator, 'define' do
44
92
  it_should_behave_like 'a mutator'
45
93
  end
46
94
 
95
+ context 'define on singleton with argument' do
96
+
97
+ before do
98
+ Mutant::Random.stub(:hex_string => 'random')
99
+ end
100
+
101
+ let(:source) { 'def self.foo(a, b); nil; end' }
102
+
103
+ let(:mutations) do
104
+ mutations = []
105
+
106
+ # Deletion of each argument
107
+ mutations << 'def self.foo(a); nil; end'
108
+ mutations << 'def self.foo(b); nil; end'
109
+
110
+ # Deletion of all arguments
111
+ mutations << 'def self.foo; nil; end'
112
+
113
+ # Rename each argument
114
+ mutations << 'def self.foo(srandom, b); nil; end'
115
+ mutations << 'def self.foo(a, srandom); nil; end'
116
+
117
+ # Mutation of body
118
+ mutations << 'def self.foo(a, b); Object.new; end'
119
+ end
120
+
121
+ it_should_behave_like 'a mutator'
122
+ end
47
123
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Mutant::Mutator, 'call' do
3
+ describe Mutant::Mutator, 'send' do
4
4
  context 'send without arguments' do
5
5
  # This could not be reproduced in a test case but happens in the mutant source code?
6
- context 'block given' do
6
+ context 'block_given?' do
7
7
  context 'implicit self' do
8
8
  let(:source) { 'block_given?' }
9
9
 
@@ -47,32 +47,91 @@ describe Mutant::Mutator, 'call' do
47
47
 
48
48
  context 'send with arguments' do
49
49
 
50
- context 'with self as receiver' do
51
- context 'implicit' do
52
- let(:source) { 'foo(nil)' }
50
+ context 'one argument' do
51
+ let(:source) { 'foo(nil)' }
53
52
 
54
- let(:mutations) do
55
- mutations = []
56
- mutations << 'foo()'
57
- mutations << 'foo(Object.new)'
58
- end
53
+ let(:mutations) do
54
+ mutations = []
55
+ mutations << 'foo()'
56
+ mutations << 'foo(Object.new)'
57
+ end
59
58
 
60
- it_should_behave_like 'a mutator'
59
+ it_should_behave_like 'a mutator'
60
+ end
61
+
62
+ context 'two arguments' do
63
+ let(:source) { 'foo(nil, nil)' }
64
+
65
+ let(:mutations) do
66
+ mutations = []
67
+ mutations << 'foo()'
68
+ mutations << 'foo(nil)'
69
+ mutations << 'foo(Object.new, nil)'
70
+ mutations << 'foo(nil, Object.new)'
61
71
  end
62
72
 
63
- context 'explicit' do
64
- let(:source) { 'self.foo(nil)' }
73
+ it_should_behave_like 'a mutator'
74
+ end
65
75
 
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
76
+ context 'with block' do
77
+ let(:source) { 'foo() { a; b }' }
73
78
 
74
- it_should_behave_like 'a mutator'
79
+ let(:mutations) do
80
+ mutations = []
81
+ mutations << 'foo() { a }'
82
+ mutations << 'foo() { b }'
83
+ mutations << 'foo() { }'
84
+ mutations << 'foo'
85
+ end
86
+
87
+ it_should_behave_like 'a mutator'
88
+ end
89
+
90
+ context 'with block args' do
91
+
92
+ let(:source) { 'foo { |a, b| }' }
93
+
94
+ before do
95
+ Mutant::Random.stub(:hex_string => :random)
96
+ end
97
+
98
+ let(:mutations) do
99
+ mutations = []
100
+ mutations << 'foo'
101
+ mutations << 'foo() { |a, b| Object.new }'
102
+ mutations << 'foo() { |a, srandom| }'
103
+ mutations << 'foo() { |srandom, b| }'
104
+ mutations << 'foo() { |a| }'
105
+ mutations << 'foo() { |b| }'
106
+ mutations << 'foo() { || }'
107
+ end
108
+
109
+ it_should_behave_like 'a mutator'
110
+ end
111
+
112
+ context 'with block pattern args' do
113
+
114
+ before do
115
+ Mutant::Random.stub(:hex_string => :random)
75
116
  end
117
+
118
+ let(:source) { 'foo { |(a, b), c| }' }
119
+
120
+ let(:mutations) do
121
+ mutations = []
122
+ mutations << 'foo() { || }'
123
+ mutations << 'foo() { |a, b, c| }'
124
+ mutations << 'foo() { |(a, b), c| Object.new }'
125
+ mutations << 'foo() { |(a, b)| }'
126
+ mutations << 'foo() { |c| }'
127
+ mutations << 'foo() { |(srandom, b), c| }'
128
+ mutations << 'foo() { |(a, srandom), c| }'
129
+ mutations << 'foo() { |(a, b), srandom| }'
130
+ mutations << 'foo'
131
+ end
132
+
133
+ it_should_behave_like 'a mutator'
76
134
  end
135
+
77
136
  end
78
137
  end
@@ -17,7 +17,7 @@ describe Mutant::Strategy::Rspec::ExampleLookup, '#spec_file' do
17
17
  end
18
18
 
19
19
  context 'negation operator' do
20
- let(:method_name) { :! }
20
+ let(:method_name) { :'!' }
21
21
  let(:expected_spec_file) { 'negation_operator_spec.rb' }
22
22
 
23
23
  it_should_behave_like 'Mutant::Strategy::Rspec::ExampleLookup#spec_file'
@@ -164,7 +164,7 @@ describe Mutant::Strategy::Rspec::ExampleLookup, '#spec_file' do
164
164
  end
165
165
 
166
166
  context 'with nomatch operator method' do
167
- let(:method_name) { :!~ }
167
+ let(:method_name) { :'!~' }
168
168
  let(:expected_spec_file) { 'nomatch_operator_spec.rb' }
169
169
 
170
170
  it_should_behave_like 'Mutant::Strategy::Rspec::ExampleLookup#spec_file'
@@ -178,7 +178,7 @@ describe Mutant::Strategy::Rspec::ExampleLookup, '#spec_file' do
178
178
  end
179
179
 
180
180
  context 'with inequality operator method' do
181
- let(:method_name) { :!= }
181
+ let(:method_name) { :'!=' }
182
182
  let(:expected_spec_file) { 'inequality_operator_spec.rb' }
183
183
 
184
184
  it_should_behave_like 'Mutant::Strategy::Rspec::ExampleLookup#spec_file'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.2.0
21
+ version: 0.2.4
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 0.2.0
29
+ version: 0.2.4
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: ice_nine
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -91,6 +91,22 @@ dependencies:
91
91
  - - ~>
92
92
  - !ruby/object:Gem::Version
93
93
  version: 0.0.3
94
+ - !ruby/object:Gem::Dependency
95
+ name: mbj-inflector
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 0.0.1
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 0.0.1
94
110
  - !ruby/object:Gem::Dependency
95
111
  name: equalizer
96
112
  requirement: !ruby/object:Gem::Requirement
@@ -173,10 +189,6 @@ files:
173
189
  - lib/mutant/differ.rb
174
190
  - lib/mutant/helper.rb
175
191
  - lib/mutant/inflector.rb
176
- - lib/mutant/inflector/defaults.rb
177
- - lib/mutant/inflector/inflections.rb
178
- - lib/mutant/inflector/methods.rb
179
- - lib/mutant/inflector/version.rb
180
192
  - lib/mutant/killer.rb
181
193
  - lib/mutant/killer/forking.rb
182
194
  - lib/mutant/killer/rspec.rb
@@ -201,6 +213,7 @@ files:
201
213
  - lib/mutant/mutator/node/block.rb
202
214
  - lib/mutant/mutator/node/define.rb
203
215
  - lib/mutant/mutator/node/if_statement.rb
216
+ - lib/mutant/mutator/node/iter_19.rb
204
217
  - lib/mutant/mutator/node/literal.rb
205
218
  - lib/mutant/mutator/node/literal/array.rb
206
219
  - lib/mutant/mutator/node/literal/boolean.rb
@@ -214,6 +227,7 @@ files:
214
227
  - lib/mutant/mutator/node/literal/regex.rb
215
228
  - lib/mutant/mutator/node/literal/string.rb
216
229
  - lib/mutant/mutator/node/literal/symbol.rb
230
+ - lib/mutant/mutator/node/local_variable_assignment.rb
217
231
  - lib/mutant/mutator/node/noop.rb
218
232
  - lib/mutant/mutator/node/receiver_case.rb
219
233
  - lib/mutant/mutator/node/return.rb
@@ -231,7 +245,6 @@ files:
231
245
  - lib/mutant/strategy/rspec/example_lookup.rb
232
246
  - lib/mutant/subject.rb
233
247
  - lib/mutant/support/method_object.rb
234
- - locator.rb
235
248
  - mutant.gemspec
236
249
  - spec/integration/mutant/differ_spec.rb
237
250
  - spec/integration/mutant/loader_spec.rb
@@ -255,7 +268,6 @@ files:
255
268
  - spec/unit/mutant/cli/class_methods/new_spec.rb
256
269
  - spec/unit/mutant/cli/class_methods/run_spec.rb
257
270
  - spec/unit/mutant/context/root_spec.rb
258
- - spec/unit/mutant/context/scope/class_methods/build_spec.rb
259
271
  - spec/unit/mutant/context/scope/root_spec.rb
260
272
  - spec/unit/mutant/context/scope/unqualified_name_spec.rb
261
273
  - spec/unit/mutant/killer/fail_ques_spec.rb
@@ -368,7 +380,6 @@ test_files:
368
380
  - spec/unit/mutant/cli/class_methods/new_spec.rb
369
381
  - spec/unit/mutant/cli/class_methods/run_spec.rb
370
382
  - spec/unit/mutant/context/root_spec.rb
371
- - spec/unit/mutant/context/scope/class_methods/build_spec.rb
372
383
  - spec/unit/mutant/context/scope/root_spec.rb
373
384
  - spec/unit/mutant/context/scope/unqualified_name_spec.rb
374
385
  - spec/unit/mutant/killer/fail_ques_spec.rb