mutant 0.3.0.beta14 → 0.3.0.beta15
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.
- checksums.yaml +4 -4
- data/Gemfile.devtools +9 -5
- data/config/rubocop.yml +31 -0
- data/lib/mutant/cli.rb +19 -6
- data/lib/mutant/config.rb +1 -1
- data/lib/mutant/runner.rb +99 -22
- data/lib/mutant/runner/config.rb +18 -4
- data/lib/mutant/runner/mutation.rb +4 -1
- data/lib/mutant/runner/subject.rb +3 -11
- data/lib/mutant/subject.rb +17 -27
- data/lib/mutant/subject/method.rb +7 -4
- data/mutant.gemspec +4 -3
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/mutant/runner/config/subjects_spec.rb +24 -14
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +18 -23
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +9 -6
- data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +29 -27
- data/spec/unit/mutant/subject/mutations_spec.rb +23 -0
- data/test_app/spec/shared/method_filter_parse_behavior.rb +1 -1
- data/test_app/spec/shared/method_match_behavior.rb +3 -4
- data/test_app/spec/shared/mutator_behavior.rb +3 -3
- data/test_app/spec/spec_helper.rb +3 -3
- data/test_app/spec/unit/test_app/literal/command_spec.rb +2 -2
- metadata +10 -10
- data/spec/unit/mutant/runner/failed_predicte_spec.rb +0 -33
- data/spec/unit/mutant/subject/each_spec.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1042e4c0fc2031a03918edcdfdfa7dfcdac388e7
|
|
4
|
+
data.tar.gz: b4f7f5d0b9d8e4ac9d59a147e8b25860d173145f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85fadf546e6df77875b1d36ce8c9010037a1ed94571ec3e48b92ac73c89729d62321910872046295cbdf757ca715b88f1bf0b714ed0e9f5d443705664dc8454f
|
|
7
|
+
data.tar.gz: af84ddf9ba4c27c335b7c58c48a35e899bc568871ab53141db7f175ed99cdb3383c4307ee9b257fc5ef61ec15307dbfcb9ab981c5b65fcb1c489e6ffd4fc3097
|
data/Gemfile.devtools
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
group :development do
|
|
4
4
|
gem 'rake', '~> 10.1.0'
|
|
5
|
-
gem 'rspec', '~> 2.
|
|
5
|
+
gem 'rspec', '~> 2.14.1'
|
|
6
6
|
gem 'yard', '~> 0.8.6.2'
|
|
7
7
|
end
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ group :guard do
|
|
|
14
14
|
gem 'guard', '~> 1.8.1'
|
|
15
15
|
gem 'guard-bundler', '~> 1.0.0'
|
|
16
16
|
gem 'guard-rspec', '~> 3.0.2'
|
|
17
|
-
gem 'guard-rubocop', '~> 0.2.0'
|
|
17
|
+
# gem 'guard-rubocop', '~> 0.2.0'
|
|
18
18
|
|
|
19
19
|
# file system change event handling
|
|
20
20
|
gem 'listen', '~> 1.2.2'
|
|
@@ -30,13 +30,17 @@ end
|
|
|
30
30
|
|
|
31
31
|
group :metrics do
|
|
32
32
|
gem 'coveralls', '~> 0.6.7'
|
|
33
|
-
gem 'flay', '~> 2.3.
|
|
34
|
-
gem 'flog', '~> 4.1.
|
|
33
|
+
gem 'flay', '~> 2.3.1'
|
|
34
|
+
gem 'flog', '~> 4.1.1'
|
|
35
35
|
gem 'reek', '~> 1.3.1', :git => 'https://github.com/troessner/reek.git'
|
|
36
|
-
gem 'rubocop', '~> 0.9.1'
|
|
36
|
+
# gem 'rubocop', '~> 0.9.1'
|
|
37
37
|
gem 'simplecov', '~> 0.7.1'
|
|
38
38
|
gem 'yardstick', '~> 0.9.6'
|
|
39
39
|
|
|
40
|
+
platforms :ruby_19, :ruby_20 do
|
|
41
|
+
gem 'yard-spellcheck', '~> 0.1.5'
|
|
42
|
+
end
|
|
43
|
+
|
|
40
44
|
platforms :ruby_19 do
|
|
41
45
|
gem 'json', '~> 1.8.0'
|
|
42
46
|
end
|
data/config/rubocop.yml
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
Includes:
|
|
3
|
+
- '../**/*.rake'
|
|
4
|
+
Excludes:
|
|
5
|
+
- '../vendor/**'
|
|
6
|
+
|
|
7
|
+
# Avoid parameter lists longer than five parameters.
|
|
8
|
+
ParameterLists:
|
|
9
|
+
Max: 3
|
|
10
|
+
CountKeywordArgs: true
|
|
11
|
+
|
|
12
|
+
# Avoid more than `Max` levels of nesting.
|
|
13
|
+
BlockNesting:
|
|
14
|
+
Max: 3
|
|
15
|
+
|
|
16
|
+
# Align with the style guide.
|
|
17
|
+
CollectionMethods:
|
|
18
|
+
PreferredMethods:
|
|
19
|
+
collect: 'map'
|
|
20
|
+
inject: 'reduce'
|
|
21
|
+
find: 'detect'
|
|
22
|
+
find_all: 'select'
|
|
23
|
+
|
|
24
|
+
# Do not force public/protected/private keyword to be indented at the same
|
|
25
|
+
# level as the def keyword. My personal preference is to outdent these keywords
|
|
26
|
+
# because I think when scanning code it makes it easier to identify the
|
|
27
|
+
# sections of code and visually separate them. When the keyword is at the same
|
|
28
|
+
# level I think it sort of blends in with the def keywords and makes it harder
|
|
29
|
+
# to scan the code and see where the sections are.
|
|
30
|
+
AccessControl:
|
|
31
|
+
Enabled: false
|
data/lib/mutant/cli.rb
CHANGED
|
@@ -56,12 +56,13 @@ module Mutant
|
|
|
56
56
|
#
|
|
57
57
|
def config
|
|
58
58
|
Config.new(
|
|
59
|
-
:cache
|
|
60
|
-
:debug
|
|
61
|
-
:matcher
|
|
62
|
-
:filter
|
|
63
|
-
:
|
|
64
|
-
:
|
|
59
|
+
:cache => @cache,
|
|
60
|
+
:debug => debug?,
|
|
61
|
+
:matcher => matcher,
|
|
62
|
+
:filter => filter,
|
|
63
|
+
:fail_fast => !!@fail_fast,
|
|
64
|
+
:strategy => strategy,
|
|
65
|
+
:reporter => reporter
|
|
65
66
|
)
|
|
66
67
|
end
|
|
67
68
|
memoize :config
|
|
@@ -151,6 +152,16 @@ module Mutant
|
|
|
151
152
|
@filters << klass.new(filter)
|
|
152
153
|
end
|
|
153
154
|
|
|
155
|
+
# Set fail fast
|
|
156
|
+
#
|
|
157
|
+
# @api private
|
|
158
|
+
#
|
|
159
|
+
# @return [undefined]
|
|
160
|
+
#
|
|
161
|
+
def set_fail_fast
|
|
162
|
+
@fail_fast = true
|
|
163
|
+
end
|
|
164
|
+
|
|
154
165
|
# Set debug mode
|
|
155
166
|
#
|
|
156
167
|
# @api private
|
|
@@ -252,6 +263,8 @@ module Mutant
|
|
|
252
263
|
|
|
253
264
|
opts.on('--code FILTER', 'Adds a code filter') do |filter|
|
|
254
265
|
add_filter Mutation::Filter::Code, filter
|
|
266
|
+
end.on('--fail-fast', 'Fail fast') do
|
|
267
|
+
set_fail_fast
|
|
255
268
|
end.on('-d','--debug', 'Enable debugging output') do
|
|
256
269
|
set_debug
|
|
257
270
|
end.on_tail('-h', '--help', 'Show this message') do
|
data/lib/mutant/config.rb
CHANGED
data/lib/mutant/runner.rb
CHANGED
|
@@ -1,8 +1,57 @@
|
|
|
1
1
|
module Mutant
|
|
2
2
|
# Runner baseclass
|
|
3
3
|
class Runner
|
|
4
|
-
include Adamantium::Flat, AbstractType
|
|
5
|
-
|
|
4
|
+
include Adamantium::Flat, AbstractType
|
|
5
|
+
|
|
6
|
+
REGISTRY = {}
|
|
7
|
+
|
|
8
|
+
# Register handler
|
|
9
|
+
#
|
|
10
|
+
# @param [Class] klass
|
|
11
|
+
#
|
|
12
|
+
# @return [undefined]
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
def self.register(klass)
|
|
17
|
+
REGISTRY[klass]=self
|
|
18
|
+
end
|
|
19
|
+
private_class_method :register
|
|
20
|
+
|
|
21
|
+
# Lookup runner
|
|
22
|
+
#
|
|
23
|
+
# @param [Class] klass
|
|
24
|
+
#
|
|
25
|
+
# @return [undefined]
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
def self.lookup(klass)
|
|
30
|
+
current = klass
|
|
31
|
+
while current
|
|
32
|
+
handler = REGISTRY.fetch(current) do
|
|
33
|
+
current = current.superclass; nil
|
|
34
|
+
end
|
|
35
|
+
return handler if handler
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
raise ArgumentError, "No handler for: #{klass}"
|
|
39
|
+
end
|
|
40
|
+
private_class_method :lookup
|
|
41
|
+
|
|
42
|
+
# Run runner for object
|
|
43
|
+
#
|
|
44
|
+
# @param [Config] config
|
|
45
|
+
# @param [Object] object
|
|
46
|
+
#
|
|
47
|
+
# @return [Runner]
|
|
48
|
+
#
|
|
49
|
+
# @api private
|
|
50
|
+
#
|
|
51
|
+
def self.run(config, object)
|
|
52
|
+
handler = lookup(object.class)
|
|
53
|
+
handler.new(config, object)
|
|
54
|
+
end
|
|
6
55
|
|
|
7
56
|
# Return config
|
|
8
57
|
#
|
|
@@ -27,6 +76,18 @@ module Mutant
|
|
|
27
76
|
@end = Time.now
|
|
28
77
|
end
|
|
29
78
|
|
|
79
|
+
# Test if runner should stop
|
|
80
|
+
#
|
|
81
|
+
# @return [true]
|
|
82
|
+
# if runner should stop
|
|
83
|
+
#
|
|
84
|
+
# @return [false]
|
|
85
|
+
# otherwise
|
|
86
|
+
#
|
|
87
|
+
def stop?
|
|
88
|
+
!!@stop
|
|
89
|
+
end
|
|
90
|
+
|
|
30
91
|
# Return runtime
|
|
31
92
|
#
|
|
32
93
|
# @return [Float]
|
|
@@ -34,22 +95,17 @@ module Mutant
|
|
|
34
95
|
# @api private
|
|
35
96
|
#
|
|
36
97
|
def runtime
|
|
37
|
-
@end - @start
|
|
98
|
+
(@end || Time.now) - @start
|
|
38
99
|
end
|
|
39
|
-
memoize :runtime
|
|
40
100
|
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# @return [true]
|
|
44
|
-
# if failed
|
|
101
|
+
# Return reporter
|
|
45
102
|
#
|
|
46
|
-
# @return [
|
|
47
|
-
# otherwise
|
|
103
|
+
# @return [Reporter]
|
|
48
104
|
#
|
|
49
105
|
# @api private
|
|
50
106
|
#
|
|
51
|
-
def
|
|
52
|
-
|
|
107
|
+
def reporter
|
|
108
|
+
config.reporter
|
|
53
109
|
end
|
|
54
110
|
|
|
55
111
|
# Test if runner is successful
|
|
@@ -64,16 +120,6 @@ module Mutant
|
|
|
64
120
|
#
|
|
65
121
|
abstract_method :success?
|
|
66
122
|
|
|
67
|
-
# Return reporter
|
|
68
|
-
#
|
|
69
|
-
# @return [Reporter]
|
|
70
|
-
#
|
|
71
|
-
# @api private
|
|
72
|
-
#
|
|
73
|
-
def reporter
|
|
74
|
-
config.reporter
|
|
75
|
-
end
|
|
76
|
-
|
|
77
123
|
private
|
|
78
124
|
|
|
79
125
|
# Perform operation
|
|
@@ -96,5 +142,36 @@ module Mutant
|
|
|
96
142
|
reporter.report(object)
|
|
97
143
|
end
|
|
98
144
|
|
|
145
|
+
# Perform dispatch
|
|
146
|
+
#
|
|
147
|
+
# @return [Enumerable<Runner>]
|
|
148
|
+
#
|
|
149
|
+
# @api private
|
|
150
|
+
#
|
|
151
|
+
def dispatch(input)
|
|
152
|
+
collection = []
|
|
153
|
+
input.each do |object|
|
|
154
|
+
runner = visit(object)
|
|
155
|
+
collection << runner
|
|
156
|
+
if runner.stop?
|
|
157
|
+
@stop = true
|
|
158
|
+
break
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
collection
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Visit object
|
|
165
|
+
#
|
|
166
|
+
# @param [Object] object
|
|
167
|
+
#
|
|
168
|
+
# @return [undefined]
|
|
169
|
+
#
|
|
170
|
+
# @api private
|
|
171
|
+
#
|
|
172
|
+
def visit(object)
|
|
173
|
+
Runner.run(config, object)
|
|
174
|
+
end
|
|
175
|
+
|
|
99
176
|
end # Runner
|
|
100
177
|
end # Mutant
|
data/lib/mutant/runner/config.rb
CHANGED
|
@@ -3,6 +3,22 @@ module Mutant
|
|
|
3
3
|
# Runner for object config
|
|
4
4
|
class Config < self
|
|
5
5
|
|
|
6
|
+
register Mutant::Config
|
|
7
|
+
|
|
8
|
+
# Run runner for object
|
|
9
|
+
#
|
|
10
|
+
# @param [Config] config
|
|
11
|
+
# @param [Object] object
|
|
12
|
+
#
|
|
13
|
+
# @return [Runner]
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
def self.run(config)
|
|
18
|
+
handler = lookup(config.class)
|
|
19
|
+
handler.new(config)
|
|
20
|
+
end
|
|
21
|
+
|
|
6
22
|
# Return subject runners
|
|
7
23
|
#
|
|
8
24
|
# @return [Enumerable<Runner::Subject>]
|
|
@@ -18,7 +34,7 @@ module Mutant
|
|
|
18
34
|
# @api private
|
|
19
35
|
#
|
|
20
36
|
def failed_subjects
|
|
21
|
-
subjects.
|
|
37
|
+
subjects.reject(&:success?)
|
|
22
38
|
end
|
|
23
39
|
memoize :failed_subjects
|
|
24
40
|
|
|
@@ -58,9 +74,7 @@ module Mutant
|
|
|
58
74
|
def run_subjects
|
|
59
75
|
strategy = self.strategy
|
|
60
76
|
strategy.setup
|
|
61
|
-
@subjects = config.subjects
|
|
62
|
-
Subject.run(config, subject)
|
|
63
|
-
end
|
|
77
|
+
@subjects = dispatch(config.subjects)
|
|
64
78
|
strategy.teardown
|
|
65
79
|
end
|
|
66
80
|
|
|
@@ -4,6 +4,8 @@ module Mutant
|
|
|
4
4
|
class Mutation < self
|
|
5
5
|
include Concord::Public.new(:config, :mutation)
|
|
6
6
|
|
|
7
|
+
register Mutant::Mutation
|
|
8
|
+
|
|
7
9
|
# Return killer instance
|
|
8
10
|
#
|
|
9
11
|
# @return [Killer]
|
|
@@ -50,7 +52,8 @@ module Mutant
|
|
|
50
52
|
#
|
|
51
53
|
def run
|
|
52
54
|
@killer = config.strategy.kill(mutation)
|
|
53
|
-
report(
|
|
55
|
+
report(killer)
|
|
56
|
+
@stop = config.fail_fast && !killer.success?
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
end # Mutation
|
|
@@ -4,13 +4,7 @@ module Mutant
|
|
|
4
4
|
class Subject < self
|
|
5
5
|
include Concord::Public.new(:config, :subject)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# @return [Subject]
|
|
10
|
-
#
|
|
11
|
-
# @api private
|
|
12
|
-
#
|
|
13
|
-
attr_reader :subject
|
|
7
|
+
register Mutant::Subject
|
|
14
8
|
|
|
15
9
|
# Initialize object
|
|
16
10
|
#
|
|
@@ -41,7 +35,7 @@ module Mutant
|
|
|
41
35
|
# @api private
|
|
42
36
|
#
|
|
43
37
|
def failed_mutations
|
|
44
|
-
mutations.
|
|
38
|
+
mutations.reject(&:success?)
|
|
45
39
|
end
|
|
46
40
|
memoize :failed_mutations
|
|
47
41
|
|
|
@@ -70,9 +64,7 @@ module Mutant
|
|
|
70
64
|
def run
|
|
71
65
|
subject = self.subject
|
|
72
66
|
report(subject)
|
|
73
|
-
@mutations = subject.
|
|
74
|
-
Mutation.run(config, mutation)
|
|
75
|
-
end
|
|
67
|
+
@mutations = dispatch(subject.mutations)
|
|
76
68
|
report(self)
|
|
77
69
|
end
|
|
78
70
|
|
data/lib/mutant/subject.rb
CHANGED
|
@@ -3,38 +3,18 @@ module Mutant
|
|
|
3
3
|
class Subject
|
|
4
4
|
include AbstractType, Adamantium::Flat, Enumerable, Concord::Public.new(:context, :node)
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Return mutations
|
|
7
7
|
#
|
|
8
|
-
# @return [
|
|
9
|
-
# returns self if block given
|
|
10
|
-
#
|
|
11
|
-
# @return [Enumerator<Mutation>]
|
|
12
|
-
# returns eumerator if no block given
|
|
13
|
-
#
|
|
14
|
-
# @api private
|
|
15
|
-
#
|
|
16
|
-
def each
|
|
17
|
-
return to_enum unless block_given?
|
|
18
|
-
|
|
19
|
-
yield noop_mutation
|
|
20
|
-
|
|
21
|
-
mutations.each do |mutation|
|
|
22
|
-
yield mutation
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
self
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Return noop mutation
|
|
29
|
-
#
|
|
30
|
-
# @return [Mutation::Noop]
|
|
8
|
+
# @return [Enumerable<Mutation>]
|
|
31
9
|
#
|
|
32
10
|
# @api private
|
|
33
11
|
#
|
|
34
|
-
def
|
|
35
|
-
|
|
12
|
+
def mutations
|
|
13
|
+
mutations = []
|
|
14
|
+
generate_mutations(mutations)
|
|
15
|
+
mutations
|
|
36
16
|
end
|
|
37
|
-
memoize :
|
|
17
|
+
memoize :mutations
|
|
38
18
|
|
|
39
19
|
# Return source path
|
|
40
20
|
#
|
|
@@ -122,5 +102,15 @@ module Mutant
|
|
|
122
102
|
Mutation::Neutral::Noop.new(self, node)
|
|
123
103
|
end
|
|
124
104
|
|
|
105
|
+
# Generate mutations
|
|
106
|
+
#
|
|
107
|
+
# @param [#<<] emitter
|
|
108
|
+
#
|
|
109
|
+
# @return [undefined]
|
|
110
|
+
#
|
|
111
|
+
# @api private
|
|
112
|
+
#
|
|
113
|
+
abstract_method :generate_mutations
|
|
114
|
+
|
|
125
115
|
end # Subject
|
|
126
116
|
end # Mutant
|
|
@@ -29,13 +29,16 @@ module Mutant
|
|
|
29
29
|
|
|
30
30
|
# Return mutations
|
|
31
31
|
#
|
|
32
|
-
# @
|
|
32
|
+
# @param [#<<] emitter
|
|
33
|
+
#
|
|
34
|
+
# @return [undefined]
|
|
33
35
|
#
|
|
34
36
|
# @api private
|
|
35
37
|
#
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
def generate_mutations(emitter)
|
|
39
|
+
emitter << noop_mutation
|
|
40
|
+
Mutator.each(node) do |mutant|
|
|
41
|
+
emitter << Mutation::Evil.new(self, mutant)
|
|
39
42
|
end
|
|
40
43
|
end
|
|
41
44
|
|
data/mutant.gemspec
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |gem|
|
|
4
4
|
gem.name = 'mutant'
|
|
5
|
-
gem.version = '0.3.0.
|
|
5
|
+
gem.version = '0.3.0.beta15'
|
|
6
6
|
gem.authors = [ 'Markus Schirp' ]
|
|
7
7
|
gem.email = [ 'mbj@schirp-dso.com' ]
|
|
8
8
|
|
|
9
9
|
gem.description = 'Mutation testing for ruby'
|
|
10
10
|
gem.summary = 'Mutation testing tool for ruby under MRI and Rubinius'
|
|
11
11
|
gem.homepage = 'https://github.com/mbj/mutant'
|
|
12
|
+
gem.license = 'MIT'
|
|
12
13
|
|
|
13
14
|
gem.require_paths = [ 'lib' ]
|
|
14
15
|
gem.files = `git ls-files`.split("\n")
|
|
@@ -16,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
|
16
17
|
gem.extra_rdoc_files = %w[TODO LICENSE]
|
|
17
18
|
gem.executables = [ 'mutant', 'zombie' ]
|
|
18
19
|
|
|
19
|
-
gem.add_runtime_dependency('parser', '~> 2.0.pre2')
|
|
20
|
+
gem.add_runtime_dependency('parser', '~> 2.0.0.pre2')
|
|
20
21
|
gem.add_runtime_dependency('unparser', '~> 0.0.8')
|
|
21
22
|
gem.add_runtime_dependency('ice_nine', '~> 0.8.0')
|
|
22
23
|
gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
|
|
@@ -25,5 +26,5 @@ Gem::Specification.new do |gem|
|
|
|
25
26
|
gem.add_runtime_dependency('inflecto', '~> 0.0.2')
|
|
26
27
|
gem.add_runtime_dependency('anima', '~> 0.0.6')
|
|
27
28
|
gem.add_runtime_dependency('concord', '~> 0.1.1')
|
|
28
|
-
gem.add_runtime_dependency('rspec', '~> 2.
|
|
29
|
+
gem.add_runtime_dependency('rspec', '~> 2.14.1')
|
|
29
30
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -8,31 +8,41 @@ describe Mutant::Runner::Config, '#subjects' do
|
|
|
8
8
|
let(:config) do
|
|
9
9
|
double(
|
|
10
10
|
'Config',
|
|
11
|
-
:
|
|
11
|
+
:class => Mutant::Config,
|
|
12
|
+
:subjects => [subject_a, subject_b],
|
|
12
13
|
:strategy => strategy,
|
|
13
14
|
:reporter => reporter
|
|
14
15
|
)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
let(:reporter)
|
|
18
|
-
let(:strategy)
|
|
19
|
-
let(:
|
|
20
|
-
let(:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
include Concord::Public.new(:config, :mutation)
|
|
24
|
-
|
|
25
|
-
def self.run(*args); new(*args); end
|
|
26
|
-
end
|
|
18
|
+
let(:reporter) { double('Reporter') }
|
|
19
|
+
let(:strategy) { double('Strategy') }
|
|
20
|
+
let(:subject_a) { double('Subject A') }
|
|
21
|
+
let(:subject_b) { double('Subject B') }
|
|
22
|
+
let(:runner_a) { double('Runner A', :stop? => stop_a) }
|
|
23
|
+
let(:runner_b) { double('Runner B', :stop? => stop_b) }
|
|
27
24
|
|
|
28
25
|
before do
|
|
29
26
|
strategy.stub(:setup)
|
|
30
27
|
strategy.stub(:teardown)
|
|
31
28
|
reporter.stub(:report => reporter)
|
|
32
|
-
|
|
29
|
+
Mutant::Runner.stub(:run).with(config, subject_a).and_return(runner_a)
|
|
30
|
+
Mutant::Runner.stub(:run).with(config, subject_b).and_return(runner_b)
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
context 'without earily stop' do
|
|
34
|
+
let(:stop_a) { false }
|
|
35
|
+
let(:stop_b) { false }
|
|
36
|
+
it { should eql([runner_a, runner_b]) }
|
|
37
|
+
it_should_behave_like 'an idempotent method'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
context 'with earily stop' do
|
|
42
|
+
let(:stop_a) { true }
|
|
43
|
+
let(:stop_b) { false }
|
|
44
|
+
it { should eql([runner_a]) }
|
|
45
|
+
it_should_behave_like 'an idempotent method'
|
|
46
|
+
end
|
|
36
47
|
|
|
37
|
-
it_should_behave_like 'an idempotent method'
|
|
38
48
|
end
|
|
@@ -3,50 +3,45 @@ require 'spec_helper'
|
|
|
3
3
|
describe Mutant::Runner::Config, '#success?' do
|
|
4
4
|
subject { object.success? }
|
|
5
5
|
|
|
6
|
-
let(:object) { described_class.
|
|
6
|
+
let(:object) { described_class.new(config) }
|
|
7
7
|
|
|
8
8
|
let(:config) do
|
|
9
9
|
double(
|
|
10
10
|
'Config',
|
|
11
11
|
:reporter => reporter,
|
|
12
12
|
:strategy => strategy,
|
|
13
|
-
:subjects =>
|
|
13
|
+
:subjects => [subject_a, subject_b]
|
|
14
14
|
)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
let(:reporter) { double('Reporter')
|
|
18
|
-
let(:strategy) { double('Strategy')
|
|
19
|
-
let(:
|
|
20
|
-
let(:
|
|
21
|
-
let(:
|
|
22
|
-
|
|
23
|
-
class DummySubjectRunner
|
|
24
|
-
include Concord::Public.new(:config, :subject)
|
|
25
|
-
|
|
26
|
-
def self.run(*args)
|
|
27
|
-
new(*args)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def failed?
|
|
31
|
-
@subject.fails?
|
|
32
|
-
end
|
|
33
|
-
end
|
|
17
|
+
let(:reporter) { double('Reporter') }
|
|
18
|
+
let(:strategy) { double('Strategy') }
|
|
19
|
+
let(:subject_a) { double('Subject A') }
|
|
20
|
+
let(:subject_b) { double('Subject B') }
|
|
21
|
+
let(:runner_a) { double('Runner A', :stop? => stop_a, :success? => success_a) }
|
|
22
|
+
let(:runner_b) { double('Runner B', :stop? => stop_b, :success? => success_b) }
|
|
34
23
|
|
|
35
24
|
before do
|
|
36
|
-
stub_const('Mutant::Runner::Subject', DummySubjectRunner)
|
|
37
25
|
reporter.stub(:report => reporter)
|
|
38
26
|
strategy.stub(:setup)
|
|
39
27
|
strategy.stub(:teardown)
|
|
28
|
+
Mutant::Runner.stub(:run).with(config, subject_a).and_return(runner_a)
|
|
29
|
+
Mutant::Runner.stub(:run).with(config, subject_b).and_return(runner_b)
|
|
40
30
|
end
|
|
41
31
|
|
|
42
32
|
context 'without failed subjects' do
|
|
33
|
+
let(:stop_a) { false }
|
|
34
|
+
let(:stop_b) { false }
|
|
35
|
+
let(:success_a) { true }
|
|
36
|
+
let(:success_b) { true }
|
|
43
37
|
it { should be(true) }
|
|
44
38
|
end
|
|
45
39
|
|
|
46
40
|
context 'with failing subjects' do
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
let(:stop_a) { false }
|
|
42
|
+
let(:stop_b) { false }
|
|
43
|
+
let(:success_a) { false }
|
|
44
|
+
let(:success_b) { true }
|
|
50
45
|
|
|
51
46
|
it { should be(false) }
|
|
52
47
|
end
|
|
@@ -6,15 +6,18 @@ describe Mutant::Runner::Mutation, '#killer' do
|
|
|
6
6
|
let(:config) do
|
|
7
7
|
double(
|
|
8
8
|
'Config',
|
|
9
|
-
:
|
|
10
|
-
:
|
|
9
|
+
:fail_fast => fail_fast,
|
|
10
|
+
:reporter => reporter,
|
|
11
|
+
:strategy => strategy
|
|
11
12
|
)
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
let(:reporter)
|
|
15
|
-
let(:mutation)
|
|
16
|
-
let(:strategy)
|
|
17
|
-
let(:killer)
|
|
15
|
+
let(:reporter) { double('Reporter') }
|
|
16
|
+
let(:mutation) { double('Mutation', :class => Mutant::Mutation) }
|
|
17
|
+
let(:strategy) { double('Strategy') }
|
|
18
|
+
let(:killer) { double('Killer', :success? => success) }
|
|
19
|
+
let(:fail_fast) { false }
|
|
20
|
+
let(:success) { false }
|
|
18
21
|
|
|
19
22
|
subject { object.killer }
|
|
20
23
|
|
|
@@ -3,47 +3,49 @@ require 'spec_helper'
|
|
|
3
3
|
describe Mutant::Runner::Subject, '#success?' do
|
|
4
4
|
subject { object.success? }
|
|
5
5
|
|
|
6
|
-
let(:object) { described_class.
|
|
6
|
+
let(:object) { described_class.new(config, mutation_subject) }
|
|
7
|
+
|
|
8
|
+
let(:mutation_subject) {
|
|
9
|
+
double(
|
|
10
|
+
'Subject',
|
|
11
|
+
:class => Mutant::Subject,
|
|
12
|
+
:mutations => [mutation_a, mutation_b]
|
|
13
|
+
)
|
|
14
|
+
}
|
|
7
15
|
|
|
8
16
|
let(:reporter) { double('Reporter') }
|
|
9
|
-
let(:mutation_subject) { double('Subject', :map => mutations) }
|
|
10
17
|
let(:config) { double('Config', :reporter => reporter) }
|
|
11
|
-
let(:mutation_a) { double('Mutation A'
|
|
12
|
-
let(:mutation_b) { double('Mutation B'
|
|
13
|
-
|
|
18
|
+
let(:mutation_a) { double('Mutation A') }
|
|
19
|
+
let(:mutation_b) { double('Mutation B') }
|
|
20
|
+
|
|
21
|
+
let(:runner_a) { double('Runner A', :success? => success_a, :stop? => stop_a) }
|
|
22
|
+
let(:runner_b) { double('Runner B', :success? => success_b, :stop? => stop_b) }
|
|
14
23
|
|
|
15
24
|
before do
|
|
16
25
|
reporter.stub(:report => reporter)
|
|
26
|
+
Mutant::Runner.stub(:run).with(config, mutation_a).and_return(runner_a)
|
|
27
|
+
Mutant::Runner.stub(:run).with(config, mutation_b).and_return(runner_b)
|
|
17
28
|
end
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
30
|
+
context 'with failing mutations' do
|
|
31
|
+
let(:stop_a) { false }
|
|
32
|
+
let(:stop_b) { false }
|
|
33
|
+
let(:success_a) { false }
|
|
34
|
+
let(:success_b) { true }
|
|
21
35
|
|
|
22
|
-
|
|
23
|
-
new(*args)
|
|
24
|
-
end
|
|
36
|
+
it { should be(false) }
|
|
25
37
|
|
|
26
|
-
|
|
27
|
-
@mutation.failed?
|
|
28
|
-
end
|
|
38
|
+
it_should_behave_like 'an idempotent method'
|
|
29
39
|
end
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
context 'without failing mutations' do
|
|
42
|
+
let(:stop_a) { false }
|
|
43
|
+
let(:stop_b) { false }
|
|
44
|
+
let(:success_a) { true }
|
|
45
|
+
let(:success_b) { true }
|
|
34
46
|
|
|
35
|
-
context 'without evil failed mutations' do
|
|
36
47
|
it { should be(true) }
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
context 'with failing noop mutation' do
|
|
40
|
-
end
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
before do
|
|
44
|
-
mutation_a.stub(:failed? => true)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it { should be(false) }
|
|
49
|
+
it_should_behave_like 'an idempotent method'
|
|
48
50
|
end
|
|
49
51
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mutant::Subject, '#mutations' do
|
|
4
|
+
subject { object.mutations }
|
|
5
|
+
|
|
6
|
+
let(:class_under_test) do
|
|
7
|
+
mutation_a, mutation_b = self.mutation_a, self.mutation_b
|
|
8
|
+
Class.new(described_class) do
|
|
9
|
+
define_method(:generate_mutations) do |emitter|
|
|
10
|
+
emitter << mutation_a
|
|
11
|
+
emitter << mutation_b
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let(:object) { class_under_test.new(context, node) }
|
|
17
|
+
let(:node) { double('Node') }
|
|
18
|
+
let(:context) { double('Context') }
|
|
19
|
+
let(:mutation_a) { double('Mutation A') }
|
|
20
|
+
let(:mutation_b) { double('Mutation B') }
|
|
21
|
+
|
|
22
|
+
it { should eql([mutation_a, mutation_b]) }
|
|
23
|
+
end
|
|
@@ -8,10 +8,9 @@ shared_examples_for 'a method match' do
|
|
|
8
8
|
let(:method_arity) { values.fetch(:method_arity) }
|
|
9
9
|
let(:scope) { values.fetch(:scope) }
|
|
10
10
|
let(:node_class) { values.fetch(:node_class) }
|
|
11
|
-
|
|
12
|
-
let(:
|
|
13
|
-
let(:
|
|
14
|
-
let(:mutation_subject) { subject.first }
|
|
11
|
+
let(:node) { mutation_subject.node }
|
|
12
|
+
let(:context) { mutation_subject.context }
|
|
13
|
+
let(:mutation_subject) { subject.first }
|
|
15
14
|
|
|
16
15
|
it 'should return one subject' do
|
|
17
16
|
subject.size.should be(1)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
shared_examples_for 'a mutator' do
|
|
2
2
|
subject { object.each(node) { |item| yields << item } }
|
|
3
3
|
|
|
4
|
-
let(:yields)
|
|
5
|
-
let(:object)
|
|
4
|
+
let(:yields) { [] }
|
|
5
|
+
let(:object) { described_class }
|
|
6
6
|
|
|
7
7
|
unless instance_methods.map(&:to_s).include?('node')
|
|
8
|
-
let(:node)
|
|
8
|
+
let(:node) { source.to_ast }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
it_should_behave_like 'a command method'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
-
require 'test_app'
|
|
3
|
-
require 'rspec'
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
|
|
6
4
|
|
|
5
|
+
require 'test_app'
|
|
6
|
+
require 'rspec'
|
|
7
7
|
|
|
8
8
|
# require spec support files and shared behavior
|
|
9
9
|
Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require f }
|
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.3.0.
|
|
4
|
+
version: 0.3.0.beta15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Markus Schirp
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ~>
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 2.0.pre2
|
|
19
|
+
version: 2.0.0.pre2
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ~>
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 2.0.pre2
|
|
26
|
+
version: 2.0.0.pre2
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: unparser
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -142,14 +142,14 @@ dependencies:
|
|
|
142
142
|
requirements:
|
|
143
143
|
- - ~>
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 2.
|
|
145
|
+
version: 2.14.1
|
|
146
146
|
type: :runtime
|
|
147
147
|
prerelease: false
|
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
149
|
requirements:
|
|
150
150
|
- - ~>
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: 2.
|
|
152
|
+
version: 2.14.1
|
|
153
153
|
description: Mutation testing for ruby
|
|
154
154
|
email:
|
|
155
155
|
- mbj@schirp-dso.com
|
|
@@ -180,6 +180,7 @@ files:
|
|
|
180
180
|
- config/flog.yml
|
|
181
181
|
- config/mutant.yml
|
|
182
182
|
- config/reek.yml
|
|
183
|
+
- config/rubocop.yml
|
|
183
184
|
- config/yardstick.yml
|
|
184
185
|
- lib/mutant.rb
|
|
185
186
|
- lib/mutant/cache.rb
|
|
@@ -340,14 +341,13 @@ files:
|
|
|
340
341
|
- spec/unit/mutant/mutator/self_spec.rb
|
|
341
342
|
- spec/unit/mutant/runner/config/subjects_spec.rb
|
|
342
343
|
- spec/unit/mutant/runner/config/success_predicate_spec.rb
|
|
343
|
-
- spec/unit/mutant/runner/failed_predicte_spec.rb
|
|
344
344
|
- spec/unit/mutant/runner/mutation/killer_spec.rb
|
|
345
345
|
- spec/unit/mutant/runner/subject/success_predicate_spec.rb
|
|
346
346
|
- spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb
|
|
347
347
|
- spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb
|
|
348
348
|
- spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb
|
|
349
349
|
- spec/unit/mutant/subject/context_spec.rb
|
|
350
|
-
- spec/unit/mutant/subject/
|
|
350
|
+
- spec/unit/mutant/subject/mutations_spec.rb
|
|
351
351
|
- spec/unit/mutant/subject/node_spec.rb
|
|
352
352
|
- test_app/.rspec
|
|
353
353
|
- test_app/lib/test_app.rb
|
|
@@ -364,7 +364,8 @@ files:
|
|
|
364
364
|
- test_app/spec/unit/test_app/literal/command_spec.rb
|
|
365
365
|
- test_app/spec/unit/test_app/literal/string_spec.rb
|
|
366
366
|
homepage: https://github.com/mbj/mutant
|
|
367
|
-
licenses:
|
|
367
|
+
licenses:
|
|
368
|
+
- MIT
|
|
368
369
|
metadata: {}
|
|
369
370
|
post_install_message:
|
|
370
371
|
rdoc_options: []
|
|
@@ -447,13 +448,12 @@ test_files:
|
|
|
447
448
|
- spec/unit/mutant/mutator/self_spec.rb
|
|
448
449
|
- spec/unit/mutant/runner/config/subjects_spec.rb
|
|
449
450
|
- spec/unit/mutant/runner/config/success_predicate_spec.rb
|
|
450
|
-
- spec/unit/mutant/runner/failed_predicte_spec.rb
|
|
451
451
|
- spec/unit/mutant/runner/mutation/killer_spec.rb
|
|
452
452
|
- spec/unit/mutant/runner/subject/success_predicate_spec.rb
|
|
453
453
|
- spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb
|
|
454
454
|
- spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb
|
|
455
455
|
- spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb
|
|
456
456
|
- spec/unit/mutant/subject/context_spec.rb
|
|
457
|
-
- spec/unit/mutant/subject/
|
|
457
|
+
- spec/unit/mutant/subject/mutations_spec.rb
|
|
458
458
|
- spec/unit/mutant/subject/node_spec.rb
|
|
459
459
|
has_rdoc:
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe Mutant::Runner, '#failed?' do
|
|
4
|
-
subject { object.failed? }
|
|
5
|
-
|
|
6
|
-
let(:object) { class_under_test.run(config) }
|
|
7
|
-
|
|
8
|
-
let(:config) { double('Config') }
|
|
9
|
-
let(:class_under_test) do
|
|
10
|
-
success = self.success
|
|
11
|
-
|
|
12
|
-
Class.new(described_class) do
|
|
13
|
-
define_method :success? do
|
|
14
|
-
success
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
define_method :run do
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
context 'when runner is successful' do
|
|
23
|
-
let(:success) { true }
|
|
24
|
-
|
|
25
|
-
it { should be(false) }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
context 'when runner is NOT successful' do
|
|
29
|
-
let(:success) { false }
|
|
30
|
-
|
|
31
|
-
it { should be(true) }
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe Mutant::Subject, '#each' do
|
|
4
|
-
subject { object.each { |item| yields << item } }
|
|
5
|
-
|
|
6
|
-
let(:class_under_test) do
|
|
7
|
-
mutations = [mutation_a, mutation_b]
|
|
8
|
-
Class.new(described_class) do
|
|
9
|
-
define_method(:mutations) { mutations }
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
let(:object) { class_under_test.new(context, node) }
|
|
14
|
-
let(:yields) { [] }
|
|
15
|
-
let(:node) { double('Node') }
|
|
16
|
-
let(:context) { double('Context') }
|
|
17
|
-
let(:mutant) { double('Mutant') }
|
|
18
|
-
let(:mutation_a) { double('Mutation A') }
|
|
19
|
-
let(:mutation_b) { double('Mutation B') }
|
|
20
|
-
|
|
21
|
-
it_should_behave_like 'an #each method'
|
|
22
|
-
|
|
23
|
-
let(:neutral_mutation) do
|
|
24
|
-
Mutant::Mutation::Neutral.new(object, node)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it 'yields mutations' do
|
|
28
|
-
expect { subject }.to change { yields.dup }.from([])
|
|
29
|
-
.to([neutral_mutation, mutation_a, mutation_b])
|
|
30
|
-
end
|
|
31
|
-
end
|