mutant 0.7.8 → 0.7.9
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/.travis.yml +1 -1
- data/Changelog.md +5 -0
- data/README.md +11 -29
- data/config/flay.yml +1 -1
- data/config/reek.yml +1 -0
- data/lib/mutant.rb +3 -3
- data/lib/mutant/cli.rb +12 -9
- data/lib/mutant/integration.rb +13 -0
- data/lib/mutant/meta/example.rb +2 -2
- data/lib/mutant/reporter/cli.rb +3 -2
- data/lib/mutant/reporter/cli/printer.rb +2 -2
- data/lib/mutant/reporter/cli/tput.rb +29 -11
- data/lib/mutant/result.rb +0 -2
- data/lib/mutant/version.rb +1 -1
- data/meta/and.rb +0 -2
- data/meta/and_asgn.rb +0 -2
- data/meta/array.rb +0 -2
- data/meta/begin.rb +0 -2
- data/meta/block.rb +0 -2
- data/meta/block_pass.rb +0 -2
- data/meta/blockarg.rb +0 -2
- data/meta/boolean.rb +0 -2
- data/meta/break.rb +0 -2
- data/meta/case.rb +0 -2
- data/meta/casgn.rb +0 -2
- data/meta/cbase.rb +0 -2
- data/meta/const.rb +0 -2
- data/meta/cvar.rb +0 -2
- data/meta/cvasgn.rb +0 -2
- data/meta/def.rb +0 -2
- data/meta/defined.rb +0 -2
- data/meta/dstr.rb +0 -2
- data/meta/dsym.rb +0 -2
- data/meta/ensure.rb +0 -2
- data/meta/false.rb +0 -2
- data/meta/float.rb +0 -2
- data/meta/gvar.rb +0 -2
- data/meta/gvasgn.rb +0 -2
- data/meta/hash.rb +0 -2
- data/meta/if.rb +0 -2
- data/meta/int.rb +0 -2
- data/meta/ivasgn.rb +0 -2
- data/meta/kwbegin.rb +0 -2
- data/meta/lvar.rb +0 -2
- data/meta/lvasgn.rb +0 -2
- data/meta/masgn.rb +0 -2
- data/meta/match_current_line.rb +0 -2
- data/meta/next.rb +0 -2
- data/meta/nil.rb +0 -2
- data/meta/nthref.rb +0 -2
- data/meta/op_assgn.rb +0 -2
- data/meta/or.rb +0 -2
- data/meta/or_asgn.rb +0 -2
- data/meta/range.rb +0 -2
- data/meta/redo.rb +0 -2
- data/meta/regex.rb +0 -2
- data/meta/rescue.rb +0 -2
- data/meta/restarg.rb +0 -2
- data/meta/return.rb +0 -2
- data/meta/self.rb +0 -2
- data/meta/send.rb +0 -2
- data/meta/str.rb +0 -2
- data/meta/super.rb +0 -2
- data/meta/symbol.rb +0 -2
- data/meta/true.rb +0 -2
- data/meta/until.rb +0 -2
- data/meta/while.rb +0 -2
- data/meta/yield.rb +0 -2
- data/mutant-rspec.gemspec +1 -1
- data/mutant.gemspec +3 -3
- data/spec/integration/mutant/rspec_spec.rb +3 -39
- data/spec/shared/framework_integration_behavior.rb +35 -0
- data/spec/unit/mutant/cli_spec.rb +34 -1
- data/spec/unit/mutant/env_spec.rb +0 -1
- data/spec/unit/mutant/integration/rspec_spec.rb +193 -0
- data/spec/unit/mutant/loader/eval_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +22 -21
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +21 -19
- data/spec/unit/mutant/parallel/worker_spec.rb +0 -2
- data/spec/unit/mutant/reporter/cli/tput_spec.rb +48 -0
- data/spec/unit/mutant/reporter/cli_spec.rb +29 -9
- data/test_app/Gemfile.rspec3.0 +1 -0
- data/test_app/Gemfile.rspec3.1 +1 -0
- data/test_app/Gemfile.rspec3.2 +1 -0
- data/test_app/lib/test_app.rb +1 -1
- data/test_app/lib/test_app/literal.rb +0 -2
- data/test_app/spec/spec_helper.rb +0 -2
- data/test_app/spec/unit/test_app/literal_spec.rb +22 -0
- metadata +15 -5
- data/test_app/spec/unit/test_app/literal/command_spec.rb +0 -11
- data/test_app/spec/unit/test_app/literal/string_spec.rb +0 -11
@@ -19,7 +19,6 @@ RSpec.describe Mutant::Env do
|
|
19
19
|
)
|
20
20
|
end
|
21
21
|
|
22
|
-
let(:isolation) { Mutant::Isolation::None }
|
23
22
|
let(:integration) { double('Integration') }
|
24
23
|
let(:isolation) { double('Isolation') }
|
25
24
|
let(:mutation) { Mutant::Mutation::Evil.new(mutation_subject, Mutant::AST::Nodes::N_NIL) }
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'mutant/integration/rspec'
|
2
|
+
|
3
|
+
RSpec.describe Mutant::Integration::Rspec do
|
4
|
+
let(:object) { described_class.new }
|
5
|
+
|
6
|
+
let(:options) { double('options') }
|
7
|
+
let(:runner) { double('runner') }
|
8
|
+
|
9
|
+
let(:example_a) do
|
10
|
+
double(
|
11
|
+
'Example A',
|
12
|
+
metadata: {
|
13
|
+
location: 'example-a-location',
|
14
|
+
full_description: 'example-a-full-description'
|
15
|
+
}
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:example_b) do
|
20
|
+
double(
|
21
|
+
'Example B',
|
22
|
+
metadata: {
|
23
|
+
location: 'example-b-location',
|
24
|
+
full_description: 'example-b-full-description',
|
25
|
+
mutant: false
|
26
|
+
}
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:example_c) do
|
31
|
+
double(
|
32
|
+
'Example C',
|
33
|
+
metadata: {
|
34
|
+
location: 'example-c-location',
|
35
|
+
full_description: 'Example::C blah'
|
36
|
+
}
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:example_d) do
|
41
|
+
double(
|
42
|
+
'Example D',
|
43
|
+
metadata: {
|
44
|
+
location: 'example-d-location',
|
45
|
+
full_description: "Example::D\nblah"
|
46
|
+
}
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:example_e) do
|
51
|
+
double(
|
52
|
+
'Example E',
|
53
|
+
metadata: {
|
54
|
+
location: 'example-e-location',
|
55
|
+
full_description: 'Example::E',
|
56
|
+
mutant_expression: 'Foo'
|
57
|
+
}
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:examples) do
|
62
|
+
[
|
63
|
+
example_a,
|
64
|
+
example_b,
|
65
|
+
example_c,
|
66
|
+
example_d,
|
67
|
+
example_e
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:example_groups) do
|
72
|
+
[
|
73
|
+
double(
|
74
|
+
'root example group',
|
75
|
+
descendants: [
|
76
|
+
double('example group', examples: examples)
|
77
|
+
]
|
78
|
+
)
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
let(:filtered_examples) do
|
83
|
+
{
|
84
|
+
double('Key') => examples.dup
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
let(:world) do
|
89
|
+
double(
|
90
|
+
'world',
|
91
|
+
example_groups: example_groups,
|
92
|
+
filtered_examples: filtered_examples
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
let(:all_tests) do
|
97
|
+
[
|
98
|
+
Mutant::Test.new(
|
99
|
+
id: 'rspec:0:example-a-location/example-a-full-description',
|
100
|
+
expression: Mutant::Expression.parse('*')
|
101
|
+
),
|
102
|
+
Mutant::Test.new(
|
103
|
+
id: 'rspec:1:example-c-location/Example::C blah',
|
104
|
+
expression: Mutant::Expression.parse('Example::C')
|
105
|
+
),
|
106
|
+
Mutant::Test.new(
|
107
|
+
id: "rspec:2:example-d-location/Example::D\nblah",
|
108
|
+
expression: Mutant::Expression.parse('*')
|
109
|
+
),
|
110
|
+
Mutant::Test.new(
|
111
|
+
id: 'rspec:3:example-e-location/Example::E',
|
112
|
+
expression: Mutant::Expression.parse('Foo')
|
113
|
+
)
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
before do
|
118
|
+
expect(RSpec::Core::ConfigurationOptions).to receive(:new).with(%w[spec --fail-fast]).and_return(options)
|
119
|
+
expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(runner)
|
120
|
+
expect(RSpec).to receive(:world).with(no_args).and_return(world)
|
121
|
+
allow(Time).to receive(:now).and_return(Time.now)
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#all_tests' do
|
125
|
+
subject { object.all_tests }
|
126
|
+
|
127
|
+
it { should eql(all_tests) }
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#setup' do
|
131
|
+
subject { object.setup }
|
132
|
+
|
133
|
+
before do
|
134
|
+
expect(runner).to receive(:setup) do |error, output|
|
135
|
+
expect(error).to be($stderr)
|
136
|
+
output.write('foo')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it { should be(object) }
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#call' do
|
144
|
+
subject { object.call(tests) }
|
145
|
+
|
146
|
+
before do
|
147
|
+
expect(runner).to receive(:setup) do |_errors, output|
|
148
|
+
output.write('the-test-output')
|
149
|
+
end
|
150
|
+
|
151
|
+
object.setup
|
152
|
+
end
|
153
|
+
|
154
|
+
let(:tests) { [all_tests.fetch(0)] }
|
155
|
+
|
156
|
+
before do
|
157
|
+
expect(world).to receive(:ordered_example_groups) do
|
158
|
+
filtered_examples.values.flatten
|
159
|
+
end
|
160
|
+
expect(runner).to receive(:run_specs).with([example_a]).and_return(exit_status)
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'on unsuccessful exit' do
|
164
|
+
let(:exit_status) { 1 }
|
165
|
+
|
166
|
+
it 'should return failed result' do
|
167
|
+
expect(subject).to eql(
|
168
|
+
Mutant::Result::Test.new(
|
169
|
+
tests: tests,
|
170
|
+
output: 'the-test-output',
|
171
|
+
passed: false,
|
172
|
+
runtime: 0.0
|
173
|
+
)
|
174
|
+
)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'on successful exit' do
|
179
|
+
let(:exit_status) { 0 }
|
180
|
+
|
181
|
+
it 'should return passed result' do
|
182
|
+
expect(subject).to eql(
|
183
|
+
Mutant::Result::Test.new(
|
184
|
+
tests: tests,
|
185
|
+
output: 'the-test-output',
|
186
|
+
passed: true,
|
187
|
+
runtime: 0.0
|
188
|
+
)
|
189
|
+
)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -1,39 +1,40 @@
|
|
1
1
|
RSpec.describe Mutant::Matcher::Methods::Instance, '#each' do
|
2
|
-
let(:object) { described_class.new(env,
|
2
|
+
let(:object) { described_class.new(env, class_under_test) }
|
3
3
|
let(:env) { Fixtures::TEST_ENV }
|
4
4
|
|
5
5
|
subject { object.each { |matcher| yields << matcher } }
|
6
6
|
|
7
7
|
let(:yields) { [] }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
let(:class_under_test) do
|
10
|
+
parent = Module.new do
|
11
|
+
def method_d
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
+
def method_e
|
15
|
+
end
|
14
16
|
end
|
15
|
-
end
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
Class.new do
|
19
|
+
include parent
|
19
20
|
|
20
|
-
|
21
|
+
private :method_d
|
21
22
|
|
22
|
-
|
23
|
+
public
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
def method_a
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
+
protected
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
def method_b
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
+
private
|
33
34
|
|
34
|
-
|
35
|
+
def method_c
|
36
|
+
end
|
35
37
|
end
|
36
|
-
|
37
38
|
end
|
38
39
|
|
39
40
|
let(:subject_a) { double('Subject A') }
|
@@ -45,11 +46,11 @@ RSpec.describe Mutant::Matcher::Methods::Instance, '#each' do
|
|
45
46
|
before do
|
46
47
|
matcher = Mutant::Matcher::Method::Instance
|
47
48
|
allow(matcher).to receive(:new)
|
48
|
-
.with(env,
|
49
|
+
.with(env, class_under_test, class_under_test.instance_method(:method_a)).and_return([subject_a])
|
49
50
|
allow(matcher).to receive(:new)
|
50
|
-
.with(env,
|
51
|
+
.with(env, class_under_test, class_under_test.instance_method(:method_b)).and_return([subject_b])
|
51
52
|
allow(matcher).to receive(:new)
|
52
|
-
.with(env,
|
53
|
+
.with(env, class_under_test, class_under_test.instance_method(:method_c)).and_return([subject_c])
|
53
54
|
end
|
54
55
|
|
55
56
|
it 'should yield expected subjects' do
|
@@ -1,33 +1,35 @@
|
|
1
1
|
RSpec.describe Mutant::Matcher::Methods::Singleton, '#each' do
|
2
|
-
let(:object) { described_class.new(env,
|
2
|
+
let(:object) { described_class.new(env, class_under_test) }
|
3
3
|
let(:env) { Fixtures::TEST_ENV }
|
4
4
|
|
5
5
|
subject { object.each { |matcher| yields << matcher } }
|
6
6
|
|
7
7
|
let(:yields) { [] }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
let(:class_under_test) do
|
10
|
+
parent = Module.new do
|
11
|
+
def method_d
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
+
def method_e
|
15
|
+
end
|
14
16
|
end
|
15
|
-
end
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
Class.new do
|
19
|
+
extend parent
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
def self.method_a
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def self.method_b
|
25
|
+
end
|
26
|
+
class << self; protected :method_b; end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
def self.method_c
|
29
|
+
end
|
30
|
+
private_class_method :method_c
|
30
31
|
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
let(:subject_a) { double('Subject A') }
|
@@ -39,11 +41,11 @@ RSpec.describe Mutant::Matcher::Methods::Singleton, '#each' do
|
|
39
41
|
before do
|
40
42
|
matcher = Mutant::Matcher::Method::Singleton
|
41
43
|
allow(matcher).to receive(:new)
|
42
|
-
.with(env,
|
44
|
+
.with(env, class_under_test, class_under_test.method(:method_a)).and_return([subject_a])
|
43
45
|
allow(matcher).to receive(:new)
|
44
|
-
.with(env,
|
46
|
+
.with(env, class_under_test, class_under_test.method(:method_b)).and_return([subject_b])
|
45
47
|
allow(matcher).to receive(:new)
|
46
|
-
.with(env,
|
48
|
+
.with(env, class_under_test, class_under_test.method(:method_c)).and_return([subject_c])
|
47
49
|
end
|
48
50
|
|
49
51
|
it 'should yield expected subjects' do
|
@@ -0,0 +1,48 @@
|
|
1
|
+
RSpec.describe Mutant::Reporter::CLI::Tput do
|
2
|
+
describe '.detect' do
|
3
|
+
subject { described_class.detect }
|
4
|
+
|
5
|
+
def expect_command(command, stdout, success)
|
6
|
+
allow(Open3).to receive(:capture3).with(command).ordered.and_return(
|
7
|
+
[
|
8
|
+
stdout,
|
9
|
+
double('Stderr'),
|
10
|
+
double('Exitstatus', success?: success)
|
11
|
+
]
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:tput_reset?) { true }
|
16
|
+
let(:tput_sc?) { true }
|
17
|
+
let(:tput_rc?) { true }
|
18
|
+
let(:tput_ed?) { true }
|
19
|
+
|
20
|
+
before do
|
21
|
+
expect_command('tput reset', '[reset]', tput_reset?)
|
22
|
+
expect_command('tput sc', '[sc]', tput_sc?)
|
23
|
+
expect_command('tput rc', '[rc]', tput_rc?)
|
24
|
+
expect_command('tput ed', '[ed]', tput_ed?)
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when all tput commands are supported' do
|
28
|
+
its(:prepare) { should eql('[reset][sc]') }
|
29
|
+
its(:restore) { should eql('[rc][ed]') }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when tput reset fails' do
|
33
|
+
let(:tput_reset?) { false }
|
34
|
+
|
35
|
+
it { should be(nil) }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when ed fails' do
|
39
|
+
let(:tput_ed?) { false }
|
40
|
+
let(:tput_cd?) { true }
|
41
|
+
before do
|
42
|
+
expect_command('tput cd', '[cd]', tput_cd?)
|
43
|
+
end
|
44
|
+
its(:prepare) { should eql('[reset][sc]') }
|
45
|
+
its(:restore) { should eql('[rc][cd]') }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -2,12 +2,20 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
2
2
|
setup_shared_context
|
3
3
|
|
4
4
|
let(:object) { described_class.new(output, format) }
|
5
|
-
let(:output) { StringIO.new
|
5
|
+
let(:output) { StringIO.new }
|
6
|
+
|
7
|
+
let(:tput) do
|
8
|
+
double(
|
9
|
+
'tput',
|
10
|
+
restore: '[tput-restore]',
|
11
|
+
prepare: '[tput-prepare]'
|
12
|
+
)
|
13
|
+
end
|
6
14
|
|
7
15
|
let(:framed_format) do
|
8
16
|
described_class::Format::Framed.new(
|
9
17
|
tty: false,
|
10
|
-
tput:
|
18
|
+
tput: tput
|
11
19
|
)
|
12
20
|
end
|
13
21
|
|
@@ -43,7 +51,7 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
43
51
|
let(:framed_format) do
|
44
52
|
described_class::Format::Framed.new(
|
45
53
|
tty: true,
|
46
|
-
tput:
|
54
|
+
tput: tput
|
47
55
|
)
|
48
56
|
end
|
49
57
|
|
@@ -56,7 +64,19 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
56
64
|
let(:ci?) { false }
|
57
65
|
|
58
66
|
context 'when not on CI and on a tty' do
|
59
|
-
|
67
|
+
before do
|
68
|
+
expect(described_class::Tput).to receive(:detect).and_return(tput)
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'and tput is available' do
|
72
|
+
it { should eql(described_class.new(output, framed_format)) }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'and tput is not available' do
|
76
|
+
let(:tput) { nil }
|
77
|
+
|
78
|
+
it { should eql(described_class.new(output, progressive_format)) }
|
79
|
+
end
|
60
80
|
end
|
61
81
|
|
62
82
|
context 'when on CI' do
|
@@ -109,7 +129,7 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
109
129
|
end
|
110
130
|
|
111
131
|
context 'on framed format' do
|
112
|
-
it_reports ''
|
132
|
+
it_reports '[tput-prepare]'
|
113
133
|
end
|
114
134
|
end
|
115
135
|
|
@@ -144,7 +164,7 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
144
164
|
update(:env_result) { { subject_results: [] } }
|
145
165
|
|
146
166
|
it_reports <<-REPORT
|
147
|
-
Mutant configuration:
|
167
|
+
[tput-restore]Mutant configuration:
|
148
168
|
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
149
169
|
Integration: null
|
150
170
|
Expect Coverage: 100.00%
|
@@ -169,7 +189,7 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
169
189
|
update(:status) { { active_jobs: [].to_set } }
|
170
190
|
|
171
191
|
it_reports(<<-REPORT)
|
172
|
-
Mutant configuration:
|
192
|
+
[tput-restore]Mutant configuration:
|
173
193
|
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
174
194
|
Integration: null
|
175
195
|
Expect Coverage: 100.00%
|
@@ -196,7 +216,7 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
196
216
|
update(:mutation_a_test_result) { { passed: true } }
|
197
217
|
|
198
218
|
it_reports(<<-REPORT)
|
199
|
-
Mutant configuration:
|
219
|
+
[tput-restore]Mutant configuration:
|
200
220
|
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
201
221
|
Integration: null
|
202
222
|
Expect Coverage: 100.00%
|
@@ -224,7 +244,7 @@ RSpec.describe Mutant::Reporter::CLI do
|
|
224
244
|
|
225
245
|
context 'on success' do
|
226
246
|
it_reports(<<-REPORT)
|
227
|
-
Mutant configuration:
|
247
|
+
[tput-restore]Mutant configuration:
|
228
248
|
Matcher: #<Mutant::Matcher::Config match_expressions=[] subject_ignores=[] subject_selects=[]>
|
229
249
|
Integration: null
|
230
250
|
Expect Coverage: 100.00%
|