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
@@ -1,7 +1,8 @@
1
1
  module Mutant
2
2
  class Reporter
3
- # Null reporter
4
- Null = Class.new(self) do
3
+
4
+ class Null < self
5
+
5
6
  # Report subject
6
7
  #
7
8
  # @param [Subject] subject
@@ -37,6 +38,7 @@ module Mutant
37
38
  def killer(*)
38
39
  self
39
40
  end
40
- end.new.freeze
41
+ end
42
+
41
43
  end
42
44
  end
@@ -10,7 +10,7 @@ module Mutant
10
10
  #
11
11
  # @api private
12
12
  #
13
- attr_reader :subject
13
+ attr_reader :subjects
14
14
 
15
15
  # Return mutation count
16
16
  #
@@ -18,7 +18,15 @@ module Mutant
18
18
  #
19
19
  # @api private
20
20
  #
21
- attr_reader :mutation
21
+ attr_reader :mutations
22
+
23
+ # Return skip count
24
+ #
25
+ # @return [Fixnum]
26
+ #
27
+ # @api private
28
+ #
29
+ attr_reader :noop_fails
22
30
 
23
31
  # Return kill count
24
32
  #
@@ -26,7 +34,7 @@ module Mutant
26
34
  #
27
35
  # @api private
28
36
  #
29
- attr_reader :kill
37
+ attr_reader :kills
30
38
 
31
39
  # Return mutation runtime
32
40
  #
@@ -36,29 +44,77 @@ module Mutant
36
44
  #
37
45
  attr_reader :time
38
46
 
47
+ # Initialize object
48
+ #
49
+ # @return [undefined]
50
+ #
51
+ # @api private
52
+ #
39
53
  def initialize
40
54
  @start = Time.now
41
- @subject = @mutation = @kill = @time = 0
55
+ @noop_fails = @subjects = @mutations = @kills = @time = 0
42
56
  end
43
57
 
58
+ # Return runtime in seconds
59
+ #
60
+ # @return [Float]
61
+ #
62
+ # @api private
63
+ #
44
64
  def runtime
45
65
  Time.now - @start
46
66
  end
47
67
 
68
+ # Count subject
69
+ #
70
+ # @return [self]
71
+ #
72
+ # @api private
73
+ #
48
74
  def subject
49
- @subject +=1
75
+ @subjects +=1
76
+ self
50
77
  end
51
78
 
79
+ # Return number of mutants alive
80
+ #
81
+ # @return [Fixnum]
82
+ #
83
+ # @api private
84
+ #
52
85
  def alive
53
- @mutation - @kill
86
+ @mutations - @kills
54
87
  end
55
88
 
89
+ # Count noop mutation fail
90
+ #
91
+ # @param [Killer] killer
92
+ #
93
+ # @return [self]
94
+ #
95
+ # @api private
96
+ #
97
+ def noop_fail(killer)
98
+ @noop_fails += 1
99
+ @time += killer.runtime
100
+ self
101
+ end
102
+
103
+ # Count killer
104
+ #
105
+ # @param [Killer] killer
106
+ #
107
+ # @return [self]
108
+ #
109
+ # @api private
110
+ #
56
111
  def killer(killer)
57
- @mutation +=1
58
- @kill +=1 unless killer.fail?
112
+ @mutations +=1
113
+ @kills +=1 unless killer.fail?
59
114
  @time += killer.runtime
115
+ self
60
116
  end
61
- end
62
117
 
118
+ end
63
119
  end
64
120
  end
data/lib/mutant/runner.rb CHANGED
@@ -86,6 +86,7 @@ module Mutant
86
86
  # @api private
87
87
  #
88
88
  def run_subject(subject)
89
+ return unless noop(subject)
89
90
  subject.each do |mutation|
90
91
  next unless config.filter.match?(mutation)
91
92
  reporter.mutation(mutation)
@@ -93,20 +94,58 @@ module Mutant
93
94
  end
94
95
  end
95
96
 
97
+ # Test for noop mutation
98
+ #
99
+ # @param [Subject] subject
100
+ #
101
+ # @return [true]
102
+ # if noop mutation is okay
103
+ #
104
+ # @return [false]
105
+ # otherwise
106
+ #
107
+ # @api private
108
+ #
109
+ def noop(subject)
110
+ killer = killer(subject.noop)
111
+ reporter.noop(killer)
112
+ unless killer.fail?
113
+ @errors << killer
114
+ return false
115
+ end
116
+
117
+ true
118
+ end
119
+
96
120
  # Run killer on mutation
97
121
  #
98
122
  # @param [Mutation] mutation
99
123
  #
100
- # @return [undefined]
124
+ # @return [true]
125
+ # if killer was unsuccessful
126
+ #
127
+ # @return [false]
128
+ # otherwise
101
129
  #
102
130
  # @api private
103
131
  #
104
132
  def kill(mutation)
105
- killer = config.strategy.kill(mutation)
133
+ killer = killer(mutation)
106
134
  reporter.killer(killer)
135
+
107
136
  if killer.fail?
108
137
  @errors << killer
109
138
  end
110
139
  end
140
+
141
+ # Return killer for mutation
142
+ #
143
+ # @return [Killer]
144
+ #
145
+ # @api private
146
+ #
147
+ def killer(mutation)
148
+ config.strategy.kill(mutation)
149
+ end
111
150
  end
112
151
  end
@@ -1,16 +1,56 @@
1
1
  module Mutant
2
2
  class Strategy
3
- include AbstractType
3
+ include AbstractType, Adamantium::Flat, Equalizer.new
4
+
5
+ # Return config
6
+ #
7
+ # @return [Config]
8
+ #
9
+ # @api private
10
+ #
11
+ attr_reader :config
12
+
13
+ # Initialize object
14
+ #
15
+ # @param [Config] config
16
+ #
17
+ # @return [undefined
18
+ #
19
+ # @api private
20
+ #
21
+ def initialize(config)
22
+ @config = config
23
+ end
24
+
25
+ # Return output stream
26
+ #
27
+ # @return [IO]
28
+ #
29
+ # @api private
30
+ #
31
+ def output_stream
32
+ config.reporter.output_stream
33
+ end
34
+
35
+ # Return error stream
36
+ #
37
+ # @return [IO]
38
+ #
39
+ # @api private
40
+ #
41
+ def error_stream
42
+ config.reporter.error_stream
43
+ end
4
44
 
5
45
  # Kill mutation
6
46
  #
7
- # @param [Mutation]
47
+ # @param [Mutation] mutation
8
48
  #
9
49
  # @return [Killer]
10
50
  #
11
51
  # @api private
12
52
  #
13
- def self.kill(mutation)
53
+ def kill(mutation)
14
54
  killer.new(self, mutation)
15
55
  end
16
56
 
@@ -20,12 +60,13 @@ module Mutant
20
60
  #
21
61
  # @api private
22
62
  #
23
- def self.killer
24
- self::KILLER
63
+ def killer
64
+ self.class::KILLER
25
65
  end
26
66
 
27
67
  # Static strategies
28
68
  class Static < self
69
+ include Equalizer.new
29
70
 
30
71
  # Always fail to kill strategy
31
72
  class Fail < self
@@ -15,7 +15,7 @@ module Mutant
15
15
  #
16
16
  # @api private
17
17
  #
18
- def self.spec_files(mutation)
18
+ def spec_files(mutation)
19
19
  ExampleLookup.run(mutation)
20
20
  end
21
21
  end
@@ -29,7 +29,7 @@ module Mutant
29
29
  #
30
30
  # @api private
31
31
  #
32
- def self.spec_files(mutation)
32
+ def spec_files(mutation)
33
33
  ['spec/unit']
34
34
  end
35
35
  end
@@ -43,14 +43,21 @@ module Mutant
43
43
  #
44
44
  # @api private
45
45
  #
46
- def self.spec_files(mutation)
46
+ def spec_files(mutation)
47
47
  Dir['spec/integration/**/*_spec.rb']
48
48
  end
49
49
  end
50
50
 
51
51
  # Run all specs per mutation
52
52
  class Full < self
53
- def self.spec_files(mutation)
53
+
54
+ # Return spec files
55
+ #
56
+ # @return [Enumerable<String>]
57
+ #
58
+ # @api private
59
+ #
60
+ def spec_files(mutation)
54
61
  Dir['spec/**/*_spec.rb']
55
62
  end
56
63
  end
@@ -8,7 +8,7 @@ module Mutant
8
8
 
9
9
  # Perform example lookup
10
10
  #
11
- # @param [Mutation]
11
+ # @param [Mutation] mutation
12
12
  #
13
13
  # @return [Enumerable<String>]
14
14
  #
@@ -57,33 +57,33 @@ module Mutant
57
57
  end
58
58
 
59
59
  MAPPING = {
60
- :<=> => :spaceship_operator,
61
- :=== => :case_equality_operator,
62
- :[]= => :element_writer,
63
- :[] => :element_reader,
64
- :<= => :less_than_or_equal_to_operator,
65
- :>= => :greater_than_or_equal_to_operator,
66
- :~@ => :unary_match_operator,
67
- :+@ => :unary_addition_operator,
68
- :-@ => :unary_substraction_operator,
69
- :== => :equality_operator,
70
- :!~ => :nomatch_operator,
71
- :!= => :inequality_operator,
72
- :=~ => :match_operator,
73
- :<< => :left_shift_operator,
74
- :>> => :right_shift_operator,
75
- :** => :exponentation_operator,
76
- :* => :multiplication_operator,
77
- :% => :modulo_operator,
78
- :/ => :division_operator,
79
- :| => :bitwise_or_operator,
80
- :! => :negation_operator,
81
- :^ => :bitwise_xor_operator,
82
- :& => :bitwise_and_operator,
83
- :< => :less_than_operator,
84
- :> => :greater_than_operator,
85
- :+ => :addition_operator,
86
- :- => :substraction_operator
60
+ :<=> => :spaceship_operator,
61
+ :=== => :case_equality_operator,
62
+ :[]= => :element_writer,
63
+ :[] => :element_reader,
64
+ :<= => :less_than_or_equal_to_operator,
65
+ :>= => :greater_than_or_equal_to_operator,
66
+ :~@ => :unary_match_operator,
67
+ :+@ => :unary_addition_operator,
68
+ :-@ => :unary_substraction_operator,
69
+ :== => :equality_operator,
70
+ :'!~' => :nomatch_operator,
71
+ :'!=' => :inequality_operator,
72
+ :=~ => :match_operator,
73
+ :<< => :left_shift_operator,
74
+ :>> => :right_shift_operator,
75
+ :** => :exponentation_operator,
76
+ :* => :multiplication_operator,
77
+ :% => :modulo_operator,
78
+ :/ => :division_operator,
79
+ :| => :bitwise_or_operator,
80
+ :'!' => :negation_operator,
81
+ :^ => :bitwise_xor_operator,
82
+ :& => :bitwise_and_operator,
83
+ :< => :less_than_operator,
84
+ :> => :greater_than_operator,
85
+ :+ => :addition_operator,
86
+ :- => :substraction_operator
87
87
  }
88
88
 
89
89
  EXPANSIONS = {
@@ -111,6 +111,8 @@ module Mutant
111
111
  # @return [nil]
112
112
  # otherwise
113
113
  #
114
+ # @api private
115
+ #
114
116
  def mapped_name
115
117
  MAPPING[method_name]
116
118
  end
@@ -144,8 +146,6 @@ module Mutant
144
146
  # @api private
145
147
  #
146
148
  def glob_expression
147
- return base_path if method_name == :initialize
148
-
149
149
  if mutation.subject.matcher.public?
150
150
  "#{base_path}/#{spec_file}"
151
151
  else
@@ -46,6 +46,17 @@ module Mutant
46
46
  self
47
47
  end
48
48
 
49
+ # Return noop mutation
50
+ #
51
+ # @return [Mutation::Noop]
52
+ #
53
+ # @api private
54
+ #
55
+ def noop
56
+ Mutation::Noop.new(self)
57
+ end
58
+ memoize :noop
59
+
49
60
  # Return subject identicication
50
61
  #
51
62
  # @return [String]
data/mutant.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'mutant'
5
- gem.version = '0.2.4'
5
+ gem.version = '0.2.5'
6
6
  gem.authors = [ 'Markus Schirp' ]
7
7
  gem.email = [ 'mbj@seonic.net' ]
8
8
  gem.description = 'Mutation testing for ruby under rubinius'
@@ -15,11 +15,12 @@ Gem::Specification.new do |gem|
15
15
  gem.extra_rdoc_files = %w[TODO]
16
16
  gem.executables = [ 'mutant' ]
17
17
 
18
- gem.add_runtime_dependency('to_source', '~> 0.2.0')
18
+ gem.add_runtime_dependency('to_source', '~> 0.2.4')
19
19
  gem.add_runtime_dependency('ice_nine', '~> 0.5.0')
20
20
  gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
21
21
  gem.add_runtime_dependency('backports', '~> 2.6')
22
22
  gem.add_runtime_dependency('adamantium', '~> 0.0.3')
23
+ gem.add_runtime_dependency('mbj-inflector', '~> 0.0.1')
23
24
  gem.add_runtime_dependency('equalizer', '~> 0.0.1')
24
25
  gem.add_runtime_dependency('abstract_type', '~> 0.0.2')
25
26
  gem.add_runtime_dependency('diff-lcs', '~> 1.1.3')