mutant 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
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