mutant 0.8.22 → 0.8.23
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/Changelog.md +5 -0
- data/lib/mutant.rb +5 -4
- data/lib/mutant/env.rb +17 -17
- data/lib/mutant/isolation.rb +42 -1
- data/lib/mutant/isolation/fork.rb +118 -54
- data/lib/mutant/isolation/none.rb +4 -7
- data/lib/mutant/loader.rb +2 -2
- data/lib/mutant/mutation.rb +9 -8
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +112 -0
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +5 -7
- data/lib/mutant/result.rb +20 -12
- data/lib/mutant/runner/sink.rb +2 -2
- data/lib/mutant/version.rb +1 -1
- data/spec/support/shared_context.rb +34 -15
- data/spec/unit/mutant/env_spec.rb +64 -59
- data/spec/unit/mutant/isolation/fork_spec.rb +164 -70
- data/spec/unit/mutant/isolation/none_spec.rb +12 -7
- data/spec/unit/mutant/isolation/result_spec.rb +41 -0
- data/spec/unit/mutant/loader_spec.rb +1 -5
- data/spec/unit/mutant/mutation_spec.rb +4 -3
- data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +124 -0
- data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +21 -11
- data/spec/unit/mutant/result/env_spec.rb +51 -4
- data/spec/unit/mutant/result/mutation_spec.rb +40 -9
- metadata +8 -3
@@ -4,15 +4,20 @@ RSpec.describe Mutant::Isolation::None do
|
|
4
4
|
describe '.call' do
|
5
5
|
let(:object) { described_class.new }
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
context 'without exception' do
|
8
|
+
it 'returns success result' do
|
9
|
+
expect(object.call { :foo })
|
10
|
+
.to eql(Mutant::Isolation::Result::Success.new(:foo))
|
11
|
+
end
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
context 'with exception' do
|
15
|
+
let(:exception) { RuntimeError.new('foo') }
|
16
|
+
|
17
|
+
it 'returns error result' do
|
18
|
+
expect(object.call { fail exception })
|
19
|
+
.to eql(Mutant::Isolation::Result::Exception.new(exception))
|
20
|
+
end
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Mutant::Isolation::Result do
|
4
|
+
describe '#success?' do
|
5
|
+
let(:value) { double('Object') }
|
6
|
+
|
7
|
+
def apply
|
8
|
+
effective_class.new(value).success?
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'on success instance' do
|
12
|
+
let(:effective_class) { described_class::Success }
|
13
|
+
|
14
|
+
it 'returns true' do
|
15
|
+
expect(apply).to be(true)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'on error instance' do
|
20
|
+
let(:effective_class) { described_class::Exception }
|
21
|
+
|
22
|
+
it 'returns false' do
|
23
|
+
expect(apply).to be(false)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'add_error' do
|
29
|
+
let(:other) { described_class::Success.new(object) }
|
30
|
+
let(:value) { double('Object') }
|
31
|
+
let(:object) { described_class::Success.new(value) }
|
32
|
+
|
33
|
+
def apply
|
34
|
+
object.add_error(other)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns chain instance' do
|
38
|
+
expect(apply).to eql(described_class::ErrorChain.new(other, object))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -5,7 +5,7 @@ RSpec.describe Mutant::Loader, '.call' do
|
|
5
5
|
described_class.call(
|
6
6
|
binding: binding,
|
7
7
|
kernel: kernel,
|
8
|
-
|
8
|
+
source: source,
|
9
9
|
subject: mutation_subject
|
10
10
|
)
|
11
11
|
end
|
@@ -27,10 +27,6 @@ RSpec.describe Mutant::Loader, '.call' do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'performs expected kernel interaction' do
|
30
|
-
expect(Unparser).to receive(:unparse)
|
31
|
-
.with(node)
|
32
|
-
.and_return(source)
|
33
|
-
|
34
30
|
expect(kernel).to receive(:eval)
|
35
31
|
.with(
|
36
32
|
source,
|
@@ -26,8 +26,9 @@ RSpec.describe Mutant::Mutation do
|
|
26
26
|
describe '#insert' do
|
27
27
|
subject { object.insert(kernel) }
|
28
28
|
|
29
|
-
let(:
|
30
|
-
let(:kernel)
|
29
|
+
let(:expected_source) { '1' }
|
30
|
+
let(:kernel) { instance_double(Kernel) }
|
31
|
+
let(:root_node) { s(:int, 1) }
|
31
32
|
|
32
33
|
before do
|
33
34
|
expect(context).to receive(:root)
|
@@ -43,7 +44,7 @@ RSpec.describe Mutant::Mutation do
|
|
43
44
|
.with(
|
44
45
|
binding: TOPLEVEL_BINDING,
|
45
46
|
kernel: kernel,
|
46
|
-
|
47
|
+
source: expected_source,
|
47
48
|
subject: mutation_subject
|
48
49
|
)
|
49
50
|
.and_return(Mutant::Loader)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Mutant::Reporter::CLI::Printer::IsolationResult do
|
4
|
+
setup_shared_context
|
5
|
+
|
6
|
+
describe '.call' do
|
7
|
+
context 'on sucessful isolation' do
|
8
|
+
let(:reportable) do
|
9
|
+
Mutant::Isolation::Result::Success.new(mutation_a_test_result)
|
10
|
+
end
|
11
|
+
|
12
|
+
it_reports <<~'STR'
|
13
|
+
- 1 @ runtime: 1.0
|
14
|
+
- test-a
|
15
|
+
Test Output:
|
16
|
+
mutation a test result output
|
17
|
+
STR
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'on exception isolation error' do
|
21
|
+
let(:exception) do
|
22
|
+
Class.new(RuntimeError) do
|
23
|
+
def inspect
|
24
|
+
'<TestException>'
|
25
|
+
end
|
26
|
+
|
27
|
+
def backtrace
|
28
|
+
%w[first last]
|
29
|
+
end
|
30
|
+
end.new('foo')
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:reportable) do
|
34
|
+
Mutant::Isolation::Result::Exception.new(exception)
|
35
|
+
end
|
36
|
+
|
37
|
+
it_reports <<~'STR'
|
38
|
+
Killing the mutation resulted in an integration error.
|
39
|
+
This is the case when the tests selected for the current mutation
|
40
|
+
did not produce a test result, but instead an exception was raised.
|
41
|
+
|
42
|
+
This may point to the following problems:
|
43
|
+
* Bug in mutant
|
44
|
+
* Bug in the ruby interpreter
|
45
|
+
* Bug in your test suite
|
46
|
+
* Bug in your test suite under concurrency
|
47
|
+
|
48
|
+
The following exception was raised:
|
49
|
+
|
50
|
+
```
|
51
|
+
<TestException>
|
52
|
+
first
|
53
|
+
last
|
54
|
+
```
|
55
|
+
STR
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'on fork isolation error' do
|
59
|
+
let(:reportable) do
|
60
|
+
Mutant::Isolation::Fork::ForkError.new
|
61
|
+
end
|
62
|
+
|
63
|
+
it_reports <<~'STR'
|
64
|
+
Forking the child process to isolate the mutation in failed.
|
65
|
+
This meant that either the RubyVM or your OS was under too much
|
66
|
+
pressure to add another child process.
|
67
|
+
|
68
|
+
Possible solutions are:
|
69
|
+
* Reduce concurrency
|
70
|
+
* Reduce locks
|
71
|
+
STR
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'on child isolation error' do
|
75
|
+
let(:reportable) do
|
76
|
+
Mutant::Isolation::Fork::ChildError.new(
|
77
|
+
instance_double(
|
78
|
+
Process::Status,
|
79
|
+
'unsuccessful status'
|
80
|
+
)
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
it_reports <<~'STR'
|
85
|
+
Killfork exited nonzero. Its result (if any) was ignored:
|
86
|
+
#<InstanceDouble(Process::Status) "unsuccessful status">
|
87
|
+
STR
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'on child isolation error' do
|
91
|
+
let(:fork_error) do
|
92
|
+
Mutant::Isolation::Fork::ForkError.new
|
93
|
+
end
|
94
|
+
|
95
|
+
let(:child_error) do
|
96
|
+
Mutant::Isolation::Fork::ChildError.new(
|
97
|
+
instance_double(
|
98
|
+
Process::Status,
|
99
|
+
'unsuccessful status'
|
100
|
+
)
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
let(:reportable) do
|
105
|
+
Mutant::Isolation::Result::ErrorChain.new(
|
106
|
+
fork_error,
|
107
|
+
child_error
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
it_reports <<~'STR'
|
112
|
+
Forking the child process to isolate the mutation in failed.
|
113
|
+
This meant that either the RubyVM or your OS was under too much
|
114
|
+
pressure to add another child process.
|
115
|
+
|
116
|
+
Possible solutions are:
|
117
|
+
* Reduce concurrency
|
118
|
+
* Reduce locks
|
119
|
+
Killfork exited nonzero. Its result (if any) was ignored:
|
120
|
+
#<InstanceDouble(Process::Status) "unsuccessful status">
|
121
|
+
STR
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -6,7 +6,27 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationResult do
|
|
6
6
|
let(:reportable) { mutation_a_result }
|
7
7
|
|
8
8
|
describe '.call' do
|
9
|
-
context '
|
9
|
+
context 'isolation problem' do
|
10
|
+
let(:status) do
|
11
|
+
instance_double(Process::Status)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:mutation_a_isolation_result) do
|
15
|
+
Mutant::Isolation::Fork::ChildError.new(status)
|
16
|
+
end
|
17
|
+
|
18
|
+
it_reports(<<~'REPORT')
|
19
|
+
evil:subject-a:d27d2
|
20
|
+
@@ -1,2 +1,2 @@
|
21
|
+
-true
|
22
|
+
+false
|
23
|
+
Killfork exited nonzero. Its result (if any) was ignored:
|
24
|
+
#<InstanceDouble(Process::Status) (anonymous)>
|
25
|
+
-----------------------
|
26
|
+
REPORT
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'unsucessful result' do
|
10
30
|
with(:mutation_a_test_result) { { passed: true } }
|
11
31
|
|
12
32
|
context 'on evil mutation' do
|
@@ -80,11 +100,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationResult do
|
|
80
100
|
s(:true)
|
81
101
|
Unparsed Source:
|
82
102
|
true
|
83
|
-
Test Result:
|
84
|
-
- 1 @ runtime: 1.0
|
85
|
-
- test-a
|
86
|
-
Test Output:
|
87
|
-
mutation a test result output
|
88
103
|
-----------------------
|
89
104
|
REPORT
|
90
105
|
end
|
@@ -101,11 +116,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationResult do
|
|
101
116
|
---- Noop failure -----
|
102
117
|
No code was inserted. And the test did NOT PASS.
|
103
118
|
This is typically a problem of your specs not passing unmutated.
|
104
|
-
Test Result:
|
105
|
-
- 1 @ runtime: 1.0
|
106
|
-
- test-a
|
107
|
-
Test Output:
|
108
|
-
mutation a test result output
|
109
119
|
-----------------------
|
110
120
|
REPORT
|
111
121
|
end
|
@@ -5,13 +5,16 @@ RSpec.describe Mutant::Result::Env do
|
|
5
5
|
described_class.new(
|
6
6
|
runtime: instance_double(Float),
|
7
7
|
env: env,
|
8
|
-
subject_results:
|
8
|
+
subject_results: subject_results
|
9
9
|
)
|
10
10
|
end
|
11
11
|
|
12
|
+
let(:subject_results) { [subject_result] }
|
13
|
+
|
12
14
|
let(:env) do
|
13
15
|
instance_double(
|
14
16
|
Mutant::Env,
|
17
|
+
config: instance_double(Mutant::Config, fail_fast: fail_fast),
|
15
18
|
subjects: [instance_double(Mutant::Subject)],
|
16
19
|
mutations: [instance_double(Mutant::Mutation)]
|
17
20
|
)
|
@@ -22,12 +25,14 @@ RSpec.describe Mutant::Result::Env do
|
|
22
25
|
Mutant::Result::Subject,
|
23
26
|
amount_mutation_results: results,
|
24
27
|
amount_mutations_killed: killed,
|
25
|
-
success?:
|
28
|
+
success?: subject_success?
|
26
29
|
)
|
27
30
|
end
|
28
31
|
|
29
|
-
let(:
|
30
|
-
let(:killed)
|
32
|
+
let(:fail_fast) { false }
|
33
|
+
let(:killed) { 0 }
|
34
|
+
let(:results) { 1 }
|
35
|
+
let(:subject_success?) { true }
|
31
36
|
|
32
37
|
describe '#success?' do
|
33
38
|
subject { object.success? }
|
@@ -81,4 +86,46 @@ RSpec.describe Mutant::Result::Env do
|
|
81
86
|
|
82
87
|
it { should eql(1) }
|
83
88
|
end
|
89
|
+
|
90
|
+
describe '#stop?' do
|
91
|
+
subject { object.stop? }
|
92
|
+
|
93
|
+
context 'without fail fast' do
|
94
|
+
context 'on empty subjects' do
|
95
|
+
let(:subject_results) { [] }
|
96
|
+
|
97
|
+
it { should be(false) }
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'on failed subject' do
|
101
|
+
let(:subject_success?) { false }
|
102
|
+
|
103
|
+
it { should be(false) }
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'on successful subject' do
|
107
|
+
it { should be(false) }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with fail fast' do
|
112
|
+
let(:fail_fast) { true }
|
113
|
+
|
114
|
+
context 'on empty subjects' do
|
115
|
+
let(:subject_results) { [] }
|
116
|
+
|
117
|
+
it { should be(false) }
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'on failed subject' do
|
121
|
+
let(:subject_success?) { false }
|
122
|
+
|
123
|
+
it { should be(true) }
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'on successful subject' do
|
127
|
+
it { should be(false) }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
84
131
|
end
|
@@ -3,8 +3,9 @@
|
|
3
3
|
RSpec.describe Mutant::Result::Mutation do
|
4
4
|
let(:object) do
|
5
5
|
described_class.new(
|
6
|
-
|
7
|
-
|
6
|
+
isolation_result: isolation_result,
|
7
|
+
mutation: mutation,
|
8
|
+
runtime: 2.0
|
8
9
|
)
|
9
10
|
end
|
10
11
|
|
@@ -17,23 +18,53 @@ RSpec.describe Mutant::Result::Mutation do
|
|
17
18
|
)
|
18
19
|
end
|
19
20
|
|
21
|
+
let(:isolation_result) do
|
22
|
+
Mutant::Isolation::Result::Success.new(test_result)
|
23
|
+
end
|
24
|
+
|
25
|
+
shared_examples_for 'unsuccessful isolation' do
|
26
|
+
let(:isolation_result) do
|
27
|
+
Mutant::Isolation::Result::Exception.new(RuntimeError.new('foo'))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#killtime' do
|
32
|
+
subject { object.killtime }
|
33
|
+
|
34
|
+
context 'if isolation is successful' do
|
35
|
+
it { should eql(1.0) }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'if isolation is not successful' do
|
39
|
+
include_context 'unsuccessful isolation'
|
40
|
+
|
41
|
+
it { should eql(0.0) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
20
45
|
describe '#runtime' do
|
21
46
|
subject { object.runtime }
|
22
47
|
|
23
|
-
it { should eql(
|
48
|
+
it { should eql(2.0) }
|
24
49
|
end
|
25
50
|
|
26
51
|
describe '#success?' do
|
27
52
|
subject { object.success? }
|
28
53
|
|
29
|
-
|
54
|
+
context 'if isolation is successful' do
|
55
|
+
before do
|
56
|
+
expect(mutation.class).to receive(:success?)
|
57
|
+
.with(test_result)
|
58
|
+
.and_return(true)
|
59
|
+
end
|
30
60
|
|
31
|
-
|
32
|
-
expect(mutation.class).to receive(:success?)
|
33
|
-
.with(test_result)
|
34
|
-
.and_return(result)
|
61
|
+
it { should be(true) }
|
35
62
|
end
|
36
63
|
|
37
|
-
|
64
|
+
context 'if isolation is not successful' do
|
65
|
+
include_context 'unsuccessful isolation'
|
66
|
+
|
67
|
+
it { should be(false) }
|
68
|
+
end
|
38
69
|
end
|
39
70
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: abstract_type
|
@@ -412,6 +412,7 @@ files:
|
|
412
412
|
- lib/mutant/reporter/cli/printer/config.rb
|
413
413
|
- lib/mutant/reporter/cli/printer/env_progress.rb
|
414
414
|
- lib/mutant/reporter/cli/printer/env_result.rb
|
415
|
+
- lib/mutant/reporter/cli/printer/isolation_result.rb
|
415
416
|
- lib/mutant/reporter/cli/printer/mutation_progress_result.rb
|
416
417
|
- lib/mutant/reporter/cli/printer/mutation_result.rb
|
417
418
|
- lib/mutant/reporter/cli/printer/status.rb
|
@@ -570,6 +571,7 @@ files:
|
|
570
571
|
- spec/unit/mutant/integration_spec.rb
|
571
572
|
- spec/unit/mutant/isolation/fork_spec.rb
|
572
573
|
- spec/unit/mutant/isolation/none_spec.rb
|
574
|
+
- spec/unit/mutant/isolation/result_spec.rb
|
573
575
|
- spec/unit/mutant/loader_spec.rb
|
574
576
|
- spec/unit/mutant/matcher/chain_spec.rb
|
575
577
|
- spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb
|
@@ -600,6 +602,7 @@ files:
|
|
600
602
|
- spec/unit/mutant/reporter/cli/printer/config_spec.rb
|
601
603
|
- spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb
|
602
604
|
- spec/unit/mutant/reporter/cli/printer/env_result_spec.rb
|
605
|
+
- spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb
|
603
606
|
- spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb
|
604
607
|
- spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb
|
605
608
|
- spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb
|
@@ -659,7 +662,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
659
662
|
version: '0'
|
660
663
|
requirements: []
|
661
664
|
rubyforge_project:
|
662
|
-
rubygems_version:
|
665
|
+
rubygems_version: 3.0.0.beta2
|
663
666
|
signing_key:
|
664
667
|
specification_version: 4
|
665
668
|
summary: Mutation testing tool for ruby under MRI and Rubinius
|
@@ -704,6 +707,7 @@ test_files:
|
|
704
707
|
- spec/unit/mutant/integration_spec.rb
|
705
708
|
- spec/unit/mutant/isolation/fork_spec.rb
|
706
709
|
- spec/unit/mutant/isolation/none_spec.rb
|
710
|
+
- spec/unit/mutant/isolation/result_spec.rb
|
707
711
|
- spec/unit/mutant/loader_spec.rb
|
708
712
|
- spec/unit/mutant/matcher/chain_spec.rb
|
709
713
|
- spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb
|
@@ -734,6 +738,7 @@ test_files:
|
|
734
738
|
- spec/unit/mutant/reporter/cli/printer/config_spec.rb
|
735
739
|
- spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb
|
736
740
|
- spec/unit/mutant/reporter/cli/printer/env_result_spec.rb
|
741
|
+
- spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb
|
737
742
|
- spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb
|
738
743
|
- spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb
|
739
744
|
- spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb
|