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.
- data/.travis.yml +3 -3
- data/Changelog.md +21 -0
- data/Gemfile.devtools +1 -0
- data/Guardfile +1 -1
- data/README.md +48 -4
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/site.reek +3 -1
- data/lib/mutant.rb +14 -2
- data/lib/mutant/cli.rb +38 -39
- data/lib/mutant/context/scope.rb +37 -32
- data/lib/mutant/killer/forking.rb +53 -0
- data/lib/mutant/killer/rspec.rb +1 -1
- data/lib/mutant/killer/static.rb +14 -0
- data/lib/mutant/matcher.rb +2 -0
- data/lib/mutant/matcher/method.rb +2 -2
- data/lib/mutant/matcher/method/singleton.rb +2 -1
- data/lib/mutant/matcher/object_space.rb +1 -1
- data/lib/mutant/matcher/scope_methods.rb +2 -0
- data/lib/mutant/mutation.rb +26 -0
- data/lib/mutant/mutation/filter/whitelist.rb +1 -1
- data/lib/mutant/mutator.rb +52 -9
- data/lib/mutant/mutator/node.rb +18 -19
- data/lib/mutant/mutator/node/arguments.rb +156 -0
- data/lib/mutant/mutator/node/block.rb +7 -20
- data/lib/mutant/mutator/node/define.rb +18 -1
- data/lib/mutant/mutator/node/iter_19.rb +26 -0
- data/lib/mutant/mutator/node/local_variable_assignment.rb +25 -0
- data/lib/mutant/mutator/node/noop.rb +4 -0
- data/lib/mutant/mutator/node/send.rb +24 -10
- data/lib/mutant/mutator/util.rb +28 -1
- data/lib/mutant/random.rb +1 -0
- data/lib/mutant/reporter.rb +28 -0
- data/lib/mutant/reporter/cli.rb +90 -19
- data/lib/mutant/reporter/null.rb +5 -3
- data/lib/mutant/reporter/stats.rb +65 -9
- data/lib/mutant/runner.rb +41 -2
- data/lib/mutant/strategy.rb +46 -5
- data/lib/mutant/strategy/rspec.rb +11 -4
- data/lib/mutant/strategy/rspec/example_lookup.rb +30 -30
- data/lib/mutant/subject.rb +11 -0
- data/mutant.gemspec +3 -2
- data/spec/integration/mutant/loader_spec.rb +4 -4
- data/spec/shared/mutator_behavior.rb +13 -1
- data/spec/unit/mutant/context/scope/root_spec.rb +20 -8
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +2 -2
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/each_spec.rb +6 -2
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +76 -0
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +80 -21
- data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +3 -3
- metadata +21 -10
- data/lib/mutant/inflector/defaults.rb +0 -64
- data/lib/mutant/inflector/inflections.rb +0 -211
- data/lib/mutant/inflector/methods.rb +0 -151
- data/lib/mutant/inflector/version.rb +0 -5
- data/locator.rb +0 -87
- data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +0 -29
data/lib/mutant/reporter/null.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Mutant
|
2
2
|
class Reporter
|
3
|
-
|
4
|
-
Null
|
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
|
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 :
|
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 :
|
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 :
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
58
|
-
@
|
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 [
|
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 =
|
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
|
data/lib/mutant/strategy.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
-
:<=>
|
61
|
-
:===
|
62
|
-
:[]=
|
63
|
-
:[]
|
64
|
-
:<=
|
65
|
-
:>=
|
66
|
-
:~@
|
67
|
-
:+@
|
68
|
-
:-@
|
69
|
-
:==
|
70
|
-
|
71
|
-
|
72
|
-
:=~
|
73
|
-
:<<
|
74
|
-
:>>
|
75
|
-
:**
|
76
|
-
:*
|
77
|
-
:%
|
78
|
-
:/
|
79
|
-
:|
|
80
|
-
|
81
|
-
:^
|
82
|
-
:&
|
83
|
-
:<
|
84
|
-
:>
|
85
|
-
:+
|
86
|
-
:-
|
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
|
data/lib/mutant/subject.rb
CHANGED
@@ -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.
|
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.
|
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')
|