mutant 0.5.26 → 0.6.0
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/.rspec +1 -0
- data/.travis.yml +1 -0
- data/Changelog.md +16 -3
- data/Gemfile +0 -2
- data/Gemfile.devtools +2 -2
- data/README.md +9 -15
- data/bin/mutant +0 -1
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/mutant.yml +1 -1
- data/config/reek.yml +14 -11
- data/config/rubocop.yml +1 -1
- data/lib/mutant.rb +22 -21
- data/lib/mutant/ast.rb +47 -0
- data/lib/mutant/cli.rb +7 -4
- data/lib/mutant/config.rb +1 -0
- data/lib/mutant/context.rb +1 -1
- data/lib/mutant/diff.rb +38 -7
- data/lib/mutant/env.rb +22 -3
- data/lib/mutant/expression.rb +15 -4
- data/lib/mutant/integration.rb +1 -1
- data/lib/mutant/isolation.rb +2 -4
- data/lib/mutant/matcher.rb +1 -1
- data/lib/mutant/matcher/method.rb +1 -1
- data/lib/mutant/matcher/method/singleton.rb +1 -1
- data/lib/mutant/matcher/methods.rb +0 -2
- data/lib/mutant/meta/example.rb +0 -2
- data/lib/mutant/meta/example/dsl.rb +1 -1
- data/lib/mutant/mutator.rb +1 -1
- data/lib/mutant/mutator/node.rb +3 -3
- data/lib/mutant/mutator/node/begin.rb +1 -1
- data/lib/mutant/mutator/node/block.rb +16 -3
- data/lib/mutant/mutator/node/if.rb +1 -1
- data/lib/mutant/mutator/node/literal/fixnum.rb +1 -1
- data/lib/mutant/mutator/node/resbody.rb +0 -2
- data/lib/mutant/mutator/node/send.rb +17 -7
- data/lib/mutant/mutator/node/send/index.rb +0 -2
- data/lib/mutant/mutator/registry.rb +1 -1
- data/lib/mutant/mutator/util.rb +1 -1
- data/lib/mutant/mutator/util/array.rb +1 -1
- data/lib/mutant/reporter.rb +13 -3
- data/lib/mutant/reporter/cli.rb +54 -8
- data/lib/mutant/reporter/cli/format.rb +197 -0
- data/lib/mutant/reporter/cli/printer.rb +402 -22
- data/lib/mutant/reporter/cli/tput.rb +27 -0
- data/lib/mutant/reporter/null.rb +4 -34
- data/lib/mutant/reporter/trace.rb +6 -38
- data/lib/mutant/result.rb +44 -56
- data/lib/mutant/runner.rb +99 -52
- data/lib/mutant/runner/collector.rb +134 -0
- data/lib/mutant/subject/method/instance.rb +12 -4
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warning_filter.rb +0 -2
- data/lib/mutant/zombifier/file.rb +1 -1
- data/meta/block.rb +17 -1
- data/meta/send.rb +123 -1
- data/mutant-rspec.gemspec +3 -3
- data/mutant.gemspec +1 -1
- data/spec/integration/mutant/corpus_spec.rb +4 -195
- data/spec/integration/mutant/null_spec.rb +1 -3
- data/spec/integration/mutant/rspec_spec.rb +1 -3
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -3
- data/spec/integration/mutant/zombie_spec.rb +1 -3
- data/spec/integrations.yml +7 -0
- data/spec/shared/method_matcher_behavior.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/compress_helper.rb +1 -0
- data/spec/support/corpus.rb +239 -0
- data/spec/support/mutation_verifier.rb +2 -4
- data/spec/unit/mutant/cli_spec.rb +20 -13
- data/spec/unit/mutant/context/root_spec.rb +1 -3
- data/spec/unit/mutant/context/scope/root_spec.rb +1 -3
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +1 -3
- data/spec/unit/mutant/diff_spec.rb +37 -19
- data/spec/unit/mutant/expression/method_spec.rb +5 -7
- data/spec/unit/mutant/expression/methods_spec.rb +5 -7
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +6 -8
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +6 -7
- data/spec/unit/mutant/expression_spec.rb +14 -5
- data/spec/unit/mutant/integration_spec.rb +14 -3
- data/spec/unit/mutant/isolation_spec.rb +2 -4
- data/spec/unit/mutant/loader/eval_spec.rb +1 -3
- data/spec/unit/mutant/matcher/chain_spec.rb +1 -3
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +21 -0
- data/spec/unit/mutant/matcher/compiler_spec.rb +28 -3
- data/spec/unit/mutant/matcher/filter_spec.rb +1 -3
- data/spec/unit/mutant/matcher/method/instance_spec.rb +3 -5
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +22 -4
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +7 -6
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +4 -6
- data/spec/unit/mutant/matcher/namespace_spec.rb +1 -3
- data/spec/unit/mutant/matcher/null_spec.rb +1 -3
- data/spec/unit/mutant/mutation_spec.rb +1 -3
- data/spec/unit/mutant/mutator/node_spec.rb +1 -3
- data/spec/unit/mutant/reporter/cli_spec.rb +444 -206
- data/spec/unit/mutant/reporter/null_spec.rb +1 -3
- data/spec/unit/mutant/require_highjack_spec.rb +1 -3
- data/spec/unit/mutant/runner_spec.rb +42 -28
- data/spec/unit/mutant/subject/context_spec.rb +1 -3
- data/spec/unit/mutant/subject/method/instance_spec.rb +27 -19
- data/spec/unit/mutant/subject/method/singleton_spec.rb +49 -17
- data/spec/unit/mutant/subject_spec.rb +1 -3
- data/spec/unit/mutant/test_spec.rb +1 -3
- data/spec/unit/mutant/warning_expectation.rb +1 -3
- data/spec/unit/mutant/warning_filter_spec.rb +1 -3
- data/spec/unit/mutant_spec.rb +13 -3
- data/test_app/Gemfile.devtools +2 -2
- data/test_app/spec/unit/test_app/literal/string_spec.rb +1 -1
- metadata +10 -21
- data/lib/mutant/matcher/method/finder.rb +0 -72
- data/lib/mutant/reporter/cli/progress.rb +0 -10
- data/lib/mutant/reporter/cli/progress/config.rb +0 -30
- data/lib/mutant/reporter/cli/progress/env.rb +0 -30
- data/lib/mutant/reporter/cli/progress/noop.rb +0 -27
- data/lib/mutant/reporter/cli/progress/result.rb +0 -12
- data/lib/mutant/reporter/cli/progress/result/mutation.rb +0 -45
- data/lib/mutant/reporter/cli/progress/result/subject.rb +0 -54
- data/lib/mutant/reporter/cli/progress/subject.rb +0 -27
- data/lib/mutant/reporter/cli/registry.rb +0 -81
- data/lib/mutant/reporter/cli/report.rb +0 -10
- data/lib/mutant/reporter/cli/report/env.rb +0 -92
- data/lib/mutant/reporter/cli/report/mutation.rb +0 -103
- data/lib/mutant/reporter/cli/report/subject.rb +0 -32
- data/lib/mutant/reporter/cli/report/test.rb +0 -28
- data/lib/mutant/walker.rb +0 -53
- data/spec/shared/mutator_behavior.rb +0 -55
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
describe Mutant::Matcher::Methods::Singleton, '#each' do
|
|
1
|
+
RSpec.describe Mutant::Matcher::Methods::Singleton, '#each' do
|
|
4
2
|
let(:object) { described_class.new(env, Foo) }
|
|
5
3
|
let(:env) { Fixtures::TEST_ENV }
|
|
6
4
|
|
|
@@ -40,11 +38,11 @@ describe Mutant::Matcher::Methods::Singleton, '#each' do
|
|
|
40
38
|
|
|
41
39
|
before do
|
|
42
40
|
matcher = Mutant::Matcher::Method::Singleton
|
|
43
|
-
matcher.
|
|
41
|
+
allow(matcher).to receive(:new)
|
|
44
42
|
.with(env, Foo, Foo.method(:method_a)).and_return([subject_a])
|
|
45
|
-
matcher.
|
|
43
|
+
allow(matcher).to receive(:new)
|
|
46
44
|
.with(env, Foo, Foo.method(:method_b)).and_return([subject_b])
|
|
47
|
-
matcher.
|
|
45
|
+
allow(matcher).to receive(:new)
|
|
48
46
|
.with(env, Foo, Foo.method(:method_c)).and_return([subject_c])
|
|
49
47
|
end
|
|
50
48
|
|
|
@@ -1,26 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
describe Mutant::Reporter::CLI do
|
|
4
|
-
let(:object) { described_class.new(output) }
|
|
1
|
+
RSpec.describe Mutant::Reporter::CLI do
|
|
2
|
+
let(:object) { described_class.new(output, format) }
|
|
5
3
|
let(:output) { StringIO.new }
|
|
6
4
|
|
|
5
|
+
let(:framed_format) do
|
|
6
|
+
described_class::Format::Framed.new(
|
|
7
|
+
tty: false,
|
|
8
|
+
tput: described_class::Tput::UNAVAILABLE
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:progressive_format) do
|
|
13
|
+
described_class::Format::Progressive.new(tty: false)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let(:format) { framed_format }
|
|
17
|
+
|
|
7
18
|
def contents
|
|
8
19
|
output.rewind
|
|
9
20
|
output.read
|
|
10
21
|
end
|
|
11
22
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
it 'writes message to output' do
|
|
18
|
-
expect { subject }.to change { contents }.from('').to("message\n")
|
|
23
|
+
def self.it_reports(expected_content)
|
|
24
|
+
it 'writes expected report to output' do
|
|
25
|
+
subject
|
|
26
|
+
expect(contents).to eql(strip_indent(expected_content))
|
|
19
27
|
end
|
|
20
28
|
end
|
|
21
29
|
|
|
30
|
+
before do
|
|
31
|
+
allow(Time).to receive(:now).and_return(Time.now)
|
|
32
|
+
end
|
|
33
|
+
|
|
22
34
|
let(:result) do
|
|
23
35
|
Mutant::Result::Env.new(
|
|
36
|
+
done: true,
|
|
24
37
|
env: env,
|
|
25
38
|
runtime: 1.1,
|
|
26
39
|
subject_results: subject_results
|
|
@@ -33,22 +46,34 @@ describe Mutant::Reporter::CLI do
|
|
|
33
46
|
class: Mutant::Env,
|
|
34
47
|
matchable_scopes: matchable_scopes,
|
|
35
48
|
config: config,
|
|
36
|
-
subjects: subjects
|
|
49
|
+
subjects: subjects,
|
|
50
|
+
mutations: subjects.flat_map(&:mutations)
|
|
37
51
|
)
|
|
38
52
|
end
|
|
39
53
|
|
|
40
|
-
let(:config) { Mutant::Config::DEFAULT
|
|
41
|
-
let(:mutation_class) { Mutant::Mutation::Evil
|
|
42
|
-
let(:matchable_scopes) { double('Matchable Scopes', length: 10)
|
|
54
|
+
let(:config) { Mutant::Config::DEFAULT.update(processes: 1) }
|
|
55
|
+
let(:mutation_class) { Mutant::Mutation::Evil }
|
|
56
|
+
let(:matchable_scopes) { double('Matchable Scopes', length: 10) }
|
|
43
57
|
|
|
44
58
|
before do
|
|
45
|
-
allow(
|
|
59
|
+
allow(mutation_a).to receive(:subject).and_return(_subject)
|
|
60
|
+
allow(mutation_b).to receive(:subject).and_return(_subject)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
let(:mutation_a) do
|
|
64
|
+
double(
|
|
65
|
+
'Mutation',
|
|
66
|
+
identification: 'mutation_id-a',
|
|
67
|
+
class: mutation_class,
|
|
68
|
+
original_source: 'true',
|
|
69
|
+
source: mutation_source
|
|
70
|
+
)
|
|
46
71
|
end
|
|
47
72
|
|
|
48
|
-
let(:
|
|
73
|
+
let(:mutation_b) do
|
|
49
74
|
double(
|
|
50
75
|
'Mutation',
|
|
51
|
-
identification: 'mutation_id',
|
|
76
|
+
identification: 'mutation_id-b',
|
|
52
77
|
class: mutation_class,
|
|
53
78
|
original_source: 'true',
|
|
54
79
|
source: mutation_source
|
|
@@ -63,13 +88,15 @@ describe Mutant::Reporter::CLI do
|
|
|
63
88
|
class: Mutant::Subject,
|
|
64
89
|
node: s(:true),
|
|
65
90
|
identification: 'subject_id',
|
|
66
|
-
mutations:
|
|
91
|
+
mutations: subject_mutations,
|
|
67
92
|
tests: [
|
|
68
93
|
double('Test', identification: 'test_id')
|
|
69
94
|
]
|
|
70
95
|
)
|
|
71
96
|
end
|
|
72
97
|
|
|
98
|
+
let(:subject_mutations) { [mutation_a] }
|
|
99
|
+
|
|
73
100
|
let(:test_results) do
|
|
74
101
|
[
|
|
75
102
|
double(
|
|
@@ -83,253 +110,464 @@ describe Mutant::Reporter::CLI do
|
|
|
83
110
|
]
|
|
84
111
|
end
|
|
85
112
|
|
|
113
|
+
let(:mutation_a_result) do
|
|
114
|
+
double(
|
|
115
|
+
'Mutation Result',
|
|
116
|
+
class: Mutant::Result::Mutation,
|
|
117
|
+
mutation: mutation_a,
|
|
118
|
+
killtime: 0.5,
|
|
119
|
+
runtime: 1.0,
|
|
120
|
+
index: 0,
|
|
121
|
+
success?: mutation_result_success,
|
|
122
|
+
test_results: test_results,
|
|
123
|
+
failed_test_results: mutation_result_success ? [] : test_results
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
86
127
|
let(:subject_results) do
|
|
87
128
|
[
|
|
88
129
|
Mutant::Result::Subject.new(
|
|
89
130
|
subject: _subject,
|
|
90
131
|
runtime: 1.0,
|
|
91
|
-
mutation_results: [
|
|
92
|
-
double(
|
|
93
|
-
'Mutation Result',
|
|
94
|
-
class: Mutant::Result::Mutation,
|
|
95
|
-
mutation: mutation,
|
|
96
|
-
killtime: 0.5,
|
|
97
|
-
success?: mutation_result_success,
|
|
98
|
-
test_results: test_results,
|
|
99
|
-
failed_test_results: mutation_result_success ? [] : test_results
|
|
100
|
-
)
|
|
101
|
-
]
|
|
132
|
+
mutation_results: [mutation_a_result]
|
|
102
133
|
)
|
|
103
134
|
]
|
|
104
135
|
end
|
|
105
136
|
|
|
106
137
|
let(:subjects) { [_subject] }
|
|
107
138
|
|
|
108
|
-
describe '
|
|
109
|
-
subject {
|
|
139
|
+
describe '.build' do
|
|
140
|
+
subject { described_class.build(output) }
|
|
110
141
|
|
|
111
|
-
|
|
112
|
-
|
|
142
|
+
let(:progressive_format) do
|
|
143
|
+
described_class::Format::Progressive.new(tty: tty?)
|
|
144
|
+
end
|
|
113
145
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
Integration: null
|
|
120
|
-
Expect Coverage: 100.00%
|
|
121
|
-
Available Subjects: 10
|
|
122
|
-
Subjects: 1
|
|
123
|
-
REPORT
|
|
124
|
-
end
|
|
146
|
+
let(:framed_format) do
|
|
147
|
+
described_class::Format::Framed.new(
|
|
148
|
+
tty: true,
|
|
149
|
+
tput: described_class::Tput::INSTANCE
|
|
150
|
+
)
|
|
125
151
|
end
|
|
126
152
|
|
|
127
|
-
|
|
128
|
-
|
|
153
|
+
before do
|
|
154
|
+
expect(ENV).to receive(:key?).with('CI').and_return(ci?)
|
|
155
|
+
end
|
|
129
156
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
end
|
|
157
|
+
let(:output) { double('Output', tty?: tty?) }
|
|
158
|
+
let(:tty?) { true }
|
|
159
|
+
let(:ci?) { false }
|
|
160
|
+
|
|
161
|
+
context 'when not on CI and on a tty' do
|
|
162
|
+
it { should eql(described_class.new(output, framed_format)) }
|
|
137
163
|
end
|
|
138
164
|
|
|
139
|
-
context '
|
|
140
|
-
let(:
|
|
141
|
-
|
|
165
|
+
context 'when on CI' do
|
|
166
|
+
let(:ci?) { true }
|
|
167
|
+
it { should eql(described_class.new(output, progressive_format)) }
|
|
168
|
+
end
|
|
142
169
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
end
|
|
170
|
+
context 'when output is not a tty?' do
|
|
171
|
+
let(:tty?) { false }
|
|
172
|
+
it { should eql(described_class.new(output, progressive_format)) }
|
|
147
173
|
end
|
|
148
174
|
|
|
149
|
-
context '
|
|
150
|
-
let(:
|
|
175
|
+
context 'when output does not respond to #tty?' do
|
|
176
|
+
let(:output) { double('Output') }
|
|
177
|
+
let(:tty?) { false }
|
|
151
178
|
|
|
152
|
-
|
|
153
|
-
|
|
179
|
+
it { should eql(described_class.new(output, progressive_format)) }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
154
182
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
183
|
+
describe '#warn' do
|
|
184
|
+
subject { object.warn(message) }
|
|
185
|
+
|
|
186
|
+
let(:message) { 'message' }
|
|
187
|
+
|
|
188
|
+
it_reports("message\n")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
describe '#start' do
|
|
192
|
+
subject { object.start(env) }
|
|
193
|
+
|
|
194
|
+
context 'on progressive format' do
|
|
195
|
+
let(:format) { progressive_format }
|
|
196
|
+
|
|
197
|
+
it_reports(<<-REPORT)
|
|
198
|
+
Mutant configuration:
|
|
199
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
200
|
+
Integration: null
|
|
201
|
+
Expect Coverage: 100.00%
|
|
202
|
+
Processes: 1
|
|
203
|
+
Includes: []
|
|
204
|
+
Requires: []
|
|
205
|
+
REPORT
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
context 'on framed format' do
|
|
209
|
+
it_reports ''
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe '#progress' do
|
|
214
|
+
subject { object.progress(collector) }
|
|
215
|
+
|
|
216
|
+
let(:collector) do
|
|
217
|
+
Mutant::Runner::Collector.new(env)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
let(:mutation_result_success) { true }
|
|
221
|
+
|
|
222
|
+
context 'on progressive format' do
|
|
223
|
+
|
|
224
|
+
let(:format) { progressive_format }
|
|
225
|
+
|
|
226
|
+
context 'with empty collector' do
|
|
227
|
+
|
|
228
|
+
it_reports ''
|
|
159
229
|
end
|
|
160
230
|
|
|
161
|
-
context '
|
|
162
|
-
|
|
231
|
+
context 'with last mutation present' do
|
|
232
|
+
|
|
233
|
+
before do
|
|
234
|
+
collector.start(mutation_a)
|
|
235
|
+
collector.finish(mutation_a_result)
|
|
236
|
+
end
|
|
163
237
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
238
|
+
context 'when mutation is successful' do
|
|
239
|
+
it_reports '.'
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
context 'when mutation is NOT successful' do
|
|
243
|
+
let(:mutation_result_success) { false }
|
|
244
|
+
|
|
245
|
+
it_reports 'F'
|
|
167
246
|
end
|
|
168
247
|
end
|
|
169
248
|
end
|
|
170
|
-
end
|
|
171
249
|
|
|
172
|
-
|
|
173
|
-
subject { object.report(result) }
|
|
250
|
+
context 'on framed format' do
|
|
174
251
|
|
|
175
|
-
|
|
252
|
+
let(:mutation_result_success) { true }
|
|
176
253
|
|
|
177
|
-
context '
|
|
178
|
-
|
|
254
|
+
context 'with empty collector' do
|
|
255
|
+
it_reports <<-REPORT
|
|
256
|
+
Mutant configuration:
|
|
257
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
258
|
+
Integration: null
|
|
259
|
+
Expect Coverage: 100.00%
|
|
260
|
+
Processes: 1
|
|
261
|
+
Includes: []
|
|
262
|
+
Requires: []
|
|
263
|
+
Available Subjects: 1
|
|
264
|
+
Subjects: 1
|
|
265
|
+
Mutations: 1
|
|
266
|
+
Kills: 0
|
|
267
|
+
Alive: 0
|
|
268
|
+
Runtime: 0.00s
|
|
269
|
+
Killtime: 0.00s
|
|
270
|
+
Overhead: NaN%
|
|
271
|
+
Coverage: 0.00%
|
|
272
|
+
Expected: 100.00%
|
|
273
|
+
Active subjects: 0
|
|
274
|
+
REPORT
|
|
275
|
+
end
|
|
179
276
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
277
|
+
context 'with collector active on one subject' do
|
|
278
|
+
before do
|
|
279
|
+
collector.start(mutation_a)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
context 'without progress' do
|
|
283
|
+
|
|
284
|
+
it_reports(<<-REPORT)
|
|
285
|
+
Mutant configuration:
|
|
286
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
287
|
+
Integration: null
|
|
288
|
+
Expect Coverage: 100.00%
|
|
289
|
+
Processes: 1
|
|
290
|
+
Includes: []
|
|
291
|
+
Requires: []
|
|
292
|
+
Available Subjects: 1
|
|
293
|
+
Subjects: 1
|
|
294
|
+
Mutations: 1
|
|
295
|
+
Kills: 0
|
|
296
|
+
Alive: 0
|
|
297
|
+
Runtime: 0.00s
|
|
298
|
+
Killtime: 0.00s
|
|
299
|
+
Overhead: NaN%
|
|
300
|
+
Coverage: 0.00%
|
|
301
|
+
Expected: 100.00%
|
|
302
|
+
Active subjects: 1
|
|
303
|
+
subject_id mutations: 1
|
|
304
|
+
- test_id
|
|
305
|
+
(00/01) 0% - killtime: 0.00s runtime: 0.00s overhead: 0.00s
|
|
192
306
|
REPORT
|
|
193
307
|
end
|
|
308
|
+
|
|
309
|
+
context 'with progress' do
|
|
310
|
+
|
|
311
|
+
let(:subject_mutations) { [mutation_a, mutation_b] }
|
|
312
|
+
|
|
313
|
+
before do
|
|
314
|
+
collector.start(mutation_b)
|
|
315
|
+
collector.finish(mutation_a_result)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
context 'on failure' do
|
|
319
|
+
let(:mutation_result_success) { false }
|
|
320
|
+
|
|
321
|
+
it_reports(<<-REPORT)
|
|
322
|
+
Mutant configuration:
|
|
323
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
324
|
+
Integration: null
|
|
325
|
+
Expect Coverage: 100.00%
|
|
326
|
+
Processes: 1
|
|
327
|
+
Includes: []
|
|
328
|
+
Requires: []
|
|
329
|
+
Available Subjects: 1
|
|
330
|
+
Subjects: 1
|
|
331
|
+
Mutations: 2
|
|
332
|
+
Kills: 0
|
|
333
|
+
Alive: 1
|
|
334
|
+
Runtime: 0.00s
|
|
335
|
+
Killtime: 0.50s
|
|
336
|
+
Overhead: -100.00%
|
|
337
|
+
Coverage: 0.00%
|
|
338
|
+
Expected: 100.00%
|
|
339
|
+
Active subjects: 1
|
|
340
|
+
subject_id mutations: 2
|
|
341
|
+
- test_id
|
|
342
|
+
F
|
|
343
|
+
(00/02) 0% - killtime: 0.50s runtime: 1.00s overhead: 0.50s
|
|
344
|
+
REPORT
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
context 'on success' do
|
|
348
|
+
it_reports(<<-REPORT)
|
|
349
|
+
Mutant configuration:
|
|
350
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
351
|
+
Integration: null
|
|
352
|
+
Expect Coverage: 100.00%
|
|
353
|
+
Processes: 1
|
|
354
|
+
Includes: []
|
|
355
|
+
Requires: []
|
|
356
|
+
Available Subjects: 1
|
|
357
|
+
Subjects: 1
|
|
358
|
+
Mutations: 2
|
|
359
|
+
Kills: 1
|
|
360
|
+
Alive: 0
|
|
361
|
+
Runtime: 0.00s
|
|
362
|
+
Killtime: 0.50s
|
|
363
|
+
Overhead: -100.00%
|
|
364
|
+
Coverage: 100.00%
|
|
365
|
+
Expected: 100.00%
|
|
366
|
+
Active subjects: 1
|
|
367
|
+
subject_id mutations: 2
|
|
368
|
+
- test_id
|
|
369
|
+
.
|
|
370
|
+
(01/02) 100% - killtime: 0.50s runtime: 1.00s overhead: 0.50s
|
|
371
|
+
REPORT
|
|
372
|
+
end
|
|
373
|
+
end
|
|
194
374
|
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
describe '#report' do
|
|
378
|
+
subject { object.report(result) }
|
|
379
|
+
|
|
380
|
+
context 'with full coverage' do
|
|
381
|
+
let(:mutation_result_success) { true }
|
|
195
382
|
|
|
196
|
-
|
|
383
|
+
it_reports(<<-REPORT)
|
|
384
|
+
Mutant configuration:
|
|
385
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
386
|
+
Integration: null
|
|
387
|
+
Expect Coverage: 100.00%
|
|
388
|
+
Processes: 1
|
|
389
|
+
Includes: []
|
|
390
|
+
Requires: []
|
|
391
|
+
Available Subjects: 1
|
|
392
|
+
Subjects: 1
|
|
393
|
+
Mutations: 1
|
|
394
|
+
Kills: 1
|
|
395
|
+
Alive: 0
|
|
396
|
+
Runtime: 1.10s
|
|
397
|
+
Killtime: 0.50s
|
|
398
|
+
Overhead: 120.00%
|
|
399
|
+
Coverage: 100.00%
|
|
400
|
+
Expected: 100.00%
|
|
401
|
+
REPORT
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
context 'and partial coverage' do
|
|
197
405
|
let(:mutation_result_success) { false }
|
|
198
406
|
|
|
199
407
|
context 'on evil mutation' do
|
|
200
408
|
context 'with a diff' do
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
409
|
+
it_reports(<<-REPORT)
|
|
410
|
+
subject_id
|
|
411
|
+
- test_id
|
|
412
|
+
mutation_id-a
|
|
413
|
+
@@ -1,2 +1,2 @@
|
|
414
|
+
-true
|
|
415
|
+
+false
|
|
416
|
+
-----------------------
|
|
417
|
+
Mutant configuration:
|
|
418
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
419
|
+
Integration: null
|
|
420
|
+
Expect Coverage: 100.00%
|
|
421
|
+
Processes: 1
|
|
422
|
+
Includes: []
|
|
423
|
+
Requires: []
|
|
424
|
+
Available Subjects: 1
|
|
425
|
+
Subjects: 1
|
|
426
|
+
Mutations: 1
|
|
427
|
+
Kills: 0
|
|
428
|
+
Alive: 1
|
|
429
|
+
Runtime: 1.10s
|
|
430
|
+
Killtime: 0.50s
|
|
431
|
+
Overhead: 120.00%
|
|
432
|
+
Coverage: 0.00%
|
|
433
|
+
Expected: 100.00%
|
|
434
|
+
REPORT
|
|
222
435
|
end
|
|
223
436
|
|
|
224
437
|
context 'without a diff' do
|
|
225
438
|
let(:mutation_source) { 'true' }
|
|
226
439
|
|
|
227
|
-
|
|
228
|
-
subject
|
|
229
|
-
expect(contents).to eql(strip_indent(<<-REPORT))
|
|
230
|
-
subject_id
|
|
231
|
-
- test_id
|
|
232
|
-
mutation_id
|
|
233
|
-
BUG: Mutation NOT resulted in exactly one diff. Please report a reproduction!
|
|
234
|
-
-----------------------
|
|
235
|
-
Subjects: 1
|
|
236
|
-
Mutations: 1
|
|
237
|
-
Kills: 0
|
|
238
|
-
Alive: 1
|
|
239
|
-
Runtime: 1.10s
|
|
240
|
-
Killtime: 0.50s
|
|
241
|
-
Overhead: 120.00%
|
|
242
|
-
Coverage: 0.00%
|
|
243
|
-
Expected: 100.00%
|
|
244
|
-
REPORT
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
context 'on neutral mutation' do
|
|
250
|
-
let(:mutation_class) { Mutant::Mutation::Neutral }
|
|
251
|
-
let(:mutation_source) { 'true' }
|
|
252
|
-
|
|
253
|
-
it 'writes report to output' do
|
|
254
|
-
subject
|
|
255
|
-
expect(contents).to eql(strip_indent(<<-REPORT))
|
|
440
|
+
it_reports(<<-REPORT)
|
|
256
441
|
subject_id
|
|
257
442
|
- test_id
|
|
258
|
-
mutation_id
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
Subject AST:
|
|
263
|
-
(true)
|
|
264
|
-
Unparsed Source:
|
|
443
|
+
mutation_id-a
|
|
444
|
+
Original source:
|
|
445
|
+
true
|
|
446
|
+
Mutated Source:
|
|
265
447
|
true
|
|
266
|
-
|
|
267
|
-
- test_id / runtime: 1.0
|
|
268
|
-
Test Output:
|
|
269
|
-
test-output
|
|
448
|
+
BUG: Mutation NOT resulted in exactly one diff. Please report a reproduction!
|
|
270
449
|
-----------------------
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
450
|
+
Mutant configuration:
|
|
451
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
452
|
+
Integration: null
|
|
453
|
+
Expect Coverage: 100.00%
|
|
454
|
+
Processes: 1
|
|
455
|
+
Includes: []
|
|
456
|
+
Requires: []
|
|
457
|
+
Available Subjects: 1
|
|
458
|
+
Subjects: 1
|
|
459
|
+
Mutations: 1
|
|
460
|
+
Kills: 0
|
|
461
|
+
Alive: 1
|
|
462
|
+
Runtime: 1.10s
|
|
463
|
+
Killtime: 0.50s
|
|
464
|
+
Overhead: 120.00%
|
|
465
|
+
Coverage: 0.00%
|
|
466
|
+
Expected: 100.00%
|
|
280
467
|
REPORT
|
|
281
468
|
end
|
|
282
469
|
end
|
|
283
470
|
|
|
284
471
|
context 'on neutral mutation' do
|
|
472
|
+
let(:mutation_class) { Mutant::Mutation::Neutral }
|
|
473
|
+
let(:mutation_source) { 'true' }
|
|
474
|
+
|
|
475
|
+
it_reports(<<-REPORT)
|
|
476
|
+
subject_id
|
|
477
|
+
- test_id
|
|
478
|
+
mutation_id-a
|
|
479
|
+
--- Neutral failure ---
|
|
480
|
+
Original code was inserted unmutated. And the test did NOT PASS.
|
|
481
|
+
Your tests do not pass initially or you found a bug in mutant / unparser.
|
|
482
|
+
Subject AST:
|
|
483
|
+
(true)
|
|
484
|
+
Unparsed Source:
|
|
485
|
+
true
|
|
486
|
+
Test Reports: 1
|
|
487
|
+
- test_id / runtime: 1.0
|
|
488
|
+
Test Output:
|
|
489
|
+
test-output
|
|
490
|
+
-----------------------
|
|
491
|
+
Mutant configuration:
|
|
492
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
493
|
+
Integration: null
|
|
494
|
+
Expect Coverage: 100.00%
|
|
495
|
+
Processes: 1
|
|
496
|
+
Includes: []
|
|
497
|
+
Requires: []
|
|
498
|
+
Available Subjects: 1
|
|
499
|
+
Subjects: 1
|
|
500
|
+
Mutations: 1
|
|
501
|
+
Kills: 0
|
|
502
|
+
Alive: 1
|
|
503
|
+
Runtime: 1.10s
|
|
504
|
+
Killtime: 0.50s
|
|
505
|
+
Overhead: 120.00%
|
|
506
|
+
Coverage: 0.00%
|
|
507
|
+
Expected: 100.00%
|
|
508
|
+
REPORT
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
context 'on noop mutation' do
|
|
285
512
|
let(:mutation_class) { Mutant::Mutation::Noop }
|
|
286
513
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
514
|
+
it_reports(<<-REPORT)
|
|
515
|
+
subject_id
|
|
516
|
+
- test_id
|
|
517
|
+
mutation_id-a
|
|
518
|
+
---- Noop failure -----
|
|
519
|
+
No code was inserted. And the test did NOT PASS.
|
|
520
|
+
This is typically a problem of your specs not passing unmutated.
|
|
521
|
+
Test Reports: 1
|
|
522
|
+
- test_id / runtime: 1.0
|
|
523
|
+
Test Output:
|
|
524
|
+
test-output
|
|
525
|
+
-----------------------
|
|
526
|
+
Mutant configuration:
|
|
527
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
528
|
+
Integration: null
|
|
529
|
+
Expect Coverage: 100.00%
|
|
530
|
+
Processes: 1
|
|
531
|
+
Includes: []
|
|
532
|
+
Requires: []
|
|
533
|
+
Available Subjects: 1
|
|
534
|
+
Subjects: 1
|
|
535
|
+
Mutations: 1
|
|
536
|
+
Kills: 0
|
|
537
|
+
Alive: 1
|
|
538
|
+
Runtime: 1.10s
|
|
539
|
+
Killtime: 0.50s
|
|
540
|
+
Overhead: 120.00%
|
|
541
|
+
Coverage: 0.00%
|
|
542
|
+
Expected: 100.00%
|
|
543
|
+
REPORT
|
|
312
544
|
end
|
|
313
545
|
end
|
|
314
|
-
end
|
|
315
546
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
547
|
+
context 'without subjects' do
|
|
548
|
+
let(:subjects) { [] }
|
|
549
|
+
let(:subject_results) { [] }
|
|
550
|
+
|
|
551
|
+
let(:config) { Mutant::Config::DEFAULT.update(processes: 1, includes: %w[include-dir], requires: %w[require-name]) }
|
|
552
|
+
|
|
553
|
+
it_reports(<<-REPORT)
|
|
554
|
+
Mutant configuration:
|
|
555
|
+
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
|
556
|
+
Integration: null
|
|
557
|
+
Expect Coverage: 100.00%
|
|
558
|
+
Processes: 1
|
|
559
|
+
Includes: ["include-dir"]
|
|
560
|
+
Requires: ["require-name"]
|
|
561
|
+
Available Subjects: 0
|
|
562
|
+
Subjects: 0
|
|
563
|
+
Mutations: 0
|
|
564
|
+
Kills: 0
|
|
565
|
+
Alive: 0
|
|
566
|
+
Runtime: 1.10s
|
|
567
|
+
Killtime: 0.00s
|
|
568
|
+
Overhead: Inf%
|
|
569
|
+
Coverage: 0.00%
|
|
570
|
+
Expected: 100.00%
|
|
333
571
|
REPORT
|
|
334
572
|
end
|
|
335
573
|
end
|