mutant 0.7.8 → 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Changelog.md +5 -0
  4. data/README.md +11 -29
  5. data/config/flay.yml +1 -1
  6. data/config/reek.yml +1 -0
  7. data/lib/mutant.rb +3 -3
  8. data/lib/mutant/cli.rb +12 -9
  9. data/lib/mutant/integration.rb +13 -0
  10. data/lib/mutant/meta/example.rb +2 -2
  11. data/lib/mutant/reporter/cli.rb +3 -2
  12. data/lib/mutant/reporter/cli/printer.rb +2 -2
  13. data/lib/mutant/reporter/cli/tput.rb +29 -11
  14. data/lib/mutant/result.rb +0 -2
  15. data/lib/mutant/version.rb +1 -1
  16. data/meta/and.rb +0 -2
  17. data/meta/and_asgn.rb +0 -2
  18. data/meta/array.rb +0 -2
  19. data/meta/begin.rb +0 -2
  20. data/meta/block.rb +0 -2
  21. data/meta/block_pass.rb +0 -2
  22. data/meta/blockarg.rb +0 -2
  23. data/meta/boolean.rb +0 -2
  24. data/meta/break.rb +0 -2
  25. data/meta/case.rb +0 -2
  26. data/meta/casgn.rb +0 -2
  27. data/meta/cbase.rb +0 -2
  28. data/meta/const.rb +0 -2
  29. data/meta/cvar.rb +0 -2
  30. data/meta/cvasgn.rb +0 -2
  31. data/meta/def.rb +0 -2
  32. data/meta/defined.rb +0 -2
  33. data/meta/dstr.rb +0 -2
  34. data/meta/dsym.rb +0 -2
  35. data/meta/ensure.rb +0 -2
  36. data/meta/false.rb +0 -2
  37. data/meta/float.rb +0 -2
  38. data/meta/gvar.rb +0 -2
  39. data/meta/gvasgn.rb +0 -2
  40. data/meta/hash.rb +0 -2
  41. data/meta/if.rb +0 -2
  42. data/meta/int.rb +0 -2
  43. data/meta/ivasgn.rb +0 -2
  44. data/meta/kwbegin.rb +0 -2
  45. data/meta/lvar.rb +0 -2
  46. data/meta/lvasgn.rb +0 -2
  47. data/meta/masgn.rb +0 -2
  48. data/meta/match_current_line.rb +0 -2
  49. data/meta/next.rb +0 -2
  50. data/meta/nil.rb +0 -2
  51. data/meta/nthref.rb +0 -2
  52. data/meta/op_assgn.rb +0 -2
  53. data/meta/or.rb +0 -2
  54. data/meta/or_asgn.rb +0 -2
  55. data/meta/range.rb +0 -2
  56. data/meta/redo.rb +0 -2
  57. data/meta/regex.rb +0 -2
  58. data/meta/rescue.rb +0 -2
  59. data/meta/restarg.rb +0 -2
  60. data/meta/return.rb +0 -2
  61. data/meta/self.rb +0 -2
  62. data/meta/send.rb +0 -2
  63. data/meta/str.rb +0 -2
  64. data/meta/super.rb +0 -2
  65. data/meta/symbol.rb +0 -2
  66. data/meta/true.rb +0 -2
  67. data/meta/until.rb +0 -2
  68. data/meta/while.rb +0 -2
  69. data/meta/yield.rb +0 -2
  70. data/mutant-rspec.gemspec +1 -1
  71. data/mutant.gemspec +3 -3
  72. data/spec/integration/mutant/rspec_spec.rb +3 -39
  73. data/spec/shared/framework_integration_behavior.rb +35 -0
  74. data/spec/unit/mutant/cli_spec.rb +34 -1
  75. data/spec/unit/mutant/env_spec.rb +0 -1
  76. data/spec/unit/mutant/integration/rspec_spec.rb +193 -0
  77. data/spec/unit/mutant/loader/eval_spec.rb +1 -1
  78. data/spec/unit/mutant/matcher/methods/instance_spec.rb +22 -21
  79. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +21 -19
  80. data/spec/unit/mutant/parallel/worker_spec.rb +0 -2
  81. data/spec/unit/mutant/reporter/cli/tput_spec.rb +48 -0
  82. data/spec/unit/mutant/reporter/cli_spec.rb +29 -9
  83. data/test_app/Gemfile.rspec3.0 +1 -0
  84. data/test_app/Gemfile.rspec3.1 +1 -0
  85. data/test_app/Gemfile.rspec3.2 +1 -0
  86. data/test_app/lib/test_app.rb +1 -1
  87. data/test_app/lib/test_app/literal.rb +0 -2
  88. data/test_app/spec/spec_helper.rb +0 -2
  89. data/test_app/spec/unit/test_app/literal_spec.rb +22 -0
  90. metadata +15 -5
  91. data/test_app/spec/unit/test_app/literal/command_spec.rb +0 -11
  92. 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
@@ -2,7 +2,7 @@ RSpec.describe Mutant::Loader::Eval, '.call' do
2
2
 
3
3
  subject { object.call(node, mutation_subject) }
4
4
 
5
- let(:object) { described_class }
5
+ let(:object) { Class.new(described_class) }
6
6
  let(:path) { __FILE__ }
7
7
  let(:line) { 1 }
8
8
 
@@ -1,39 +1,40 @@
1
1
  RSpec.describe Mutant::Matcher::Methods::Instance, '#each' do
2
- let(:object) { described_class.new(env, Foo) }
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
- module Bar
10
- def method_d
11
- end
9
+ let(:class_under_test) do
10
+ parent = Module.new do
11
+ def method_d
12
+ end
12
13
 
13
- def method_e
14
+ def method_e
15
+ end
14
16
  end
15
- end
16
17
 
17
- class Foo
18
- include Bar
18
+ Class.new do
19
+ include parent
19
20
 
20
- private :method_d
21
+ private :method_d
21
22
 
22
- public
23
+ public
23
24
 
24
- def method_a
25
- end
25
+ def method_a
26
+ end
26
27
 
27
- protected
28
+ protected
28
29
 
29
- def method_b
30
- end
30
+ def method_b
31
+ end
31
32
 
32
- private
33
+ private
33
34
 
34
- def method_c
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, Foo, Foo.instance_method(:method_a)).and_return([subject_a])
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, Foo, Foo.instance_method(:method_b)).and_return([subject_b])
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, Foo, Foo.instance_method(:method_c)).and_return([subject_c])
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, Foo) }
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
- module Bar
10
- def method_d
11
- end
9
+ let(:class_under_test) do
10
+ parent = Module.new do
11
+ def method_d
12
+ end
12
13
 
13
- def method_e
14
+ def method_e
15
+ end
14
16
  end
15
- end
16
17
 
17
- class Foo
18
- extend Bar
18
+ Class.new do
19
+ extend parent
19
20
 
20
- def self.method_a
21
- end
21
+ def self.method_a
22
+ end
22
23
 
23
- def self.method_b
24
- end
25
- class << self; protected :method_b; end
24
+ def self.method_b
25
+ end
26
+ class << self; protected :method_b; end
26
27
 
27
- def self.method_c
28
- end
29
- private_class_method :method_c
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, Foo, Foo.method(:method_a)).and_return([subject_a])
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, Foo, Foo.method(:method_b)).and_return([subject_b])
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, Foo, Foo.method(:method_c)).and_return([subject_c])
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
@@ -29,8 +29,6 @@ RSpec.describe Mutant::Parallel::Worker do
29
29
 
30
30
  context 'when receving :job command' do
31
31
 
32
- let(:test_result) { double('Test Result') }
33
-
34
32
  before do
35
33
  expect(processor).to receive(:call).with(payload).and_return(result_payload)
36
34
 
@@ -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: described_class::Tput::UNAVAILABLE
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: described_class::Tput::INSTANCE
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
- it { should eql(described_class.new(output, framed_format)) }
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%