mutant 0.7.8 → 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- 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%
|