beaker 2.29.1 → 2.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.gitignore +1 -0
- data/HISTORY.md +268 -2
- data/Rakefile +5 -4
- data/docs/How-to-Write-a-Beaker-Test-for-a-Module.md +11 -4
- data/lib/beaker/cli.rb +7 -1
- data/lib/beaker/dsl/install_utils/foss_utils.rb +6 -0
- data/lib/beaker/dsl/roles.rb +15 -12
- data/lib/beaker/hypervisor/vagrant.rb +1 -1
- data/lib/beaker/hypervisor/vcloud.rb +6 -1
- data/lib/beaker/options/command_line_parser.rb +6 -0
- data/lib/beaker/options/presets.rb +1 -0
- data/lib/beaker/platform.rb +8 -0
- data/lib/beaker/runner/mini_test/test_suite.rb +58 -0
- data/lib/beaker/runner/native/test_case.rb +193 -0
- data/lib/beaker/runner/native/test_suite.rb +410 -0
- data/lib/beaker/test_case.rb +2 -176
- data/lib/beaker/test_suite.rb +9 -399
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/dsl/install_utils/foss_utils_spec.rb +2 -0
- data/spec/beaker/dsl/install_utils/pe_utils_spec.rb +4 -0
- data/spec/beaker/dsl/install_utils/puppet_utils_spec.rb +6 -0
- data/spec/beaker/dsl/roles_spec.rb +118 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +4 -4
- data/spec/beaker/options/beaker_options_spec.rb +34 -0
- data/spec/beaker/platform_spec.rb +17 -1
- data/spec/beaker/runner/native/test_case_spec.rb +147 -0
- data/spec/beaker/runner/native/test_suite_spec.rb +303 -0
- data/spec/beaker/test_suite_spec.rb +9 -306
- data/spec/helpers.rb +1 -1
- metadata +8 -2
data/lib/beaker/version.rb
CHANGED
@@ -87,6 +87,8 @@ describe ClassMixedWithDSLInstallUtils do
|
|
87
87
|
|
88
88
|
it 'uses aio paths for hosts with aio type (backwards compatability)' do
|
89
89
|
hosts.each do |host|
|
90
|
+
host[:pe_ver] = nil
|
91
|
+
host[:version] = nil
|
90
92
|
host[:type] = 'aio'
|
91
93
|
end
|
92
94
|
expect(subject).to receive(:add_aio_defaults_on).exactly(hosts.length).times
|
@@ -49,6 +49,8 @@ describe ClassMixedWithDSLInstallUtils do
|
|
49
49
|
context '#configure_pe_defaults_on' do
|
50
50
|
it 'uses aio paths for hosts of role aio' do
|
51
51
|
hosts.each do |host|
|
52
|
+
host[:pe_ver] = nil
|
53
|
+
host[:version] = nil
|
52
54
|
host[:roles] = host[:roles] | ['aio']
|
53
55
|
end
|
54
56
|
expect(subject).to receive(:add_pe_defaults_on).exactly(hosts.length).times
|
@@ -71,6 +73,8 @@ describe ClassMixedWithDSLInstallUtils do
|
|
71
73
|
|
72
74
|
it 'uses aio paths for hosts of type aio' do
|
73
75
|
hosts.each do |host|
|
76
|
+
host[:pe_ver] = nil
|
77
|
+
host[:version] = nil
|
74
78
|
host[:type] = 'aio'
|
75
79
|
end
|
76
80
|
expect(subject).to receive(:add_aio_defaults_on).exactly(hosts.length).times
|
@@ -83,6 +83,8 @@ describe ClassMixedWithDSLInstallUtils do
|
|
83
83
|
|
84
84
|
it "adds aio defaults to foss hosts when they have an aio foss puppet version" do
|
85
85
|
hosts.each do |host|
|
86
|
+
host[:pe_ver] = nil
|
87
|
+
host[:version] = nil
|
86
88
|
host['type'] = 'foss'
|
87
89
|
host['version'] = '4.0'
|
88
90
|
end
|
@@ -93,6 +95,8 @@ describe ClassMixedWithDSLInstallUtils do
|
|
93
95
|
|
94
96
|
it "adds aio defaults to foss hosts when they have type foss-aio" do
|
95
97
|
hosts.each do |host|
|
98
|
+
host[:pe_ver] = nil
|
99
|
+
host[:version] = nil
|
96
100
|
host['type'] = 'foss-aio'
|
97
101
|
end
|
98
102
|
expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
|
@@ -102,6 +106,8 @@ describe ClassMixedWithDSLInstallUtils do
|
|
102
106
|
|
103
107
|
it "can set aio defaults for aio type (backwards compatability)" do
|
104
108
|
hosts.each do |host|
|
109
|
+
host[:pe_ver] = nil
|
110
|
+
host[:version] = nil
|
105
111
|
host['type'] = 'aio'
|
106
112
|
end
|
107
113
|
expect(subject).to receive(:add_aio_defaults_on).exactly(hosts.length).times
|
@@ -163,6 +163,124 @@ describe ClassMixedWithDSLRoles do
|
|
163
163
|
agent1[:type] = 'aio-foss'
|
164
164
|
expect( subject.aio_version?(agent1) ).to be === true
|
165
165
|
end
|
166
|
+
it 'can take an empty string for pe_ver' do
|
167
|
+
agent1[:pe_ver] = ''
|
168
|
+
expect{ subject.aio_version?(agent1) }.not_to raise_error
|
169
|
+
end
|
170
|
+
it 'can take an empty string for FOSS version' do
|
171
|
+
agent1[:version] = ''
|
172
|
+
expect{ subject.aio_version?(agent1) }.not_to raise_error
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'truth table-type testing' do
|
176
|
+
|
177
|
+
before :each do
|
178
|
+
@old_pe_ver = agent1[:pe_ver]
|
179
|
+
@old_version = agent1[:version]
|
180
|
+
@old_roles = agent1[:roles]
|
181
|
+
@old_type = agent1[:type]
|
182
|
+
end
|
183
|
+
|
184
|
+
after :each do
|
185
|
+
agent1[:pe_ver] = @old_pe_ver
|
186
|
+
agent1[:version] = @old_version
|
187
|
+
agent1[:roles] = @old_roles
|
188
|
+
agent1[:type] = @old_type
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'version values table' do
|
192
|
+
# pe_ver, version, answer
|
193
|
+
versions_table = [
|
194
|
+
[nil, nil, false],
|
195
|
+
[nil, '', false],
|
196
|
+
[nil, '3.9', false],
|
197
|
+
[nil, '4.0', true ],
|
198
|
+
[nil, '2015.1', true ],
|
199
|
+
\
|
200
|
+
['', nil, false],
|
201
|
+
['', '', false],
|
202
|
+
['', '3.9', false],
|
203
|
+
['', '4.0', true ],
|
204
|
+
['', '2015.1', true ],
|
205
|
+
\
|
206
|
+
['3.9', nil, false],
|
207
|
+
['3.9', '', false],
|
208
|
+
['3.9', '3.9', false],
|
209
|
+
['3.9', '4.0', false],
|
210
|
+
['3.9', '2015.1', false],
|
211
|
+
\
|
212
|
+
['4.0', nil, true],
|
213
|
+
['4.0', '', true],
|
214
|
+
['4.0', '3.9', true],
|
215
|
+
['4.0', '4.0', true],
|
216
|
+
['4.0', '2015.1', true],
|
217
|
+
\
|
218
|
+
['2015.1', nil, true],
|
219
|
+
['2015.1', '', true],
|
220
|
+
['2015.1', '3.9', true],
|
221
|
+
['2015.1', '4.0', true],
|
222
|
+
['2015.1', '2015.1', true],
|
223
|
+
]
|
224
|
+
|
225
|
+
versions_table.each do |answers_row|
|
226
|
+
it "acts with values #{answers_row} correctly" do
|
227
|
+
agent1[:pe_ver] = answers_row[0]
|
228
|
+
agent1[:version] = answers_row[1]
|
229
|
+
agent1[:roles] = nil
|
230
|
+
agent1[:type] = nil
|
231
|
+
expect( subject.aio_version?(agent1) ).to be === answers_row[2]
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context 'roles values table' do
|
237
|
+
roles_table = [
|
238
|
+
[nil, false],
|
239
|
+
[[], false],
|
240
|
+
[['aio'], true ],
|
241
|
+
[['gun'], false],
|
242
|
+
[['a', 'b'], false],
|
243
|
+
[['c', 'aio'], true ],
|
244
|
+
]
|
245
|
+
|
246
|
+
roles_table.each do |answers_row|
|
247
|
+
it "acts with values #{answers_row} correctly" do
|
248
|
+
agent1[:pe_ver] = nil
|
249
|
+
agent1[:version] = nil
|
250
|
+
agent1[:roles] = answers_row[0]
|
251
|
+
agent1[:type] = nil
|
252
|
+
expect( subject.aio_version?(agent1) ).to be === answers_row[1]
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'type values table' do
|
258
|
+
type_table = [
|
259
|
+
[nil, false],
|
260
|
+
['', false],
|
261
|
+
['cheese', false],
|
262
|
+
['paionts', false],
|
263
|
+
['aioch', false],
|
264
|
+
['chaio', false],
|
265
|
+
['aio', true ],
|
266
|
+
['aio-', true ],
|
267
|
+
['ew-aio-ji', true ],
|
268
|
+
['id-aiot', false],
|
269
|
+
]
|
270
|
+
|
271
|
+
type_table.each do |answers_row|
|
272
|
+
it "acts with values #{answers_row} correctly" do
|
273
|
+
agent1[:pe_ver] = nil
|
274
|
+
agent1[:version] = nil
|
275
|
+
agent1[:roles] = nil
|
276
|
+
agent1[:type] = answers_row[0]
|
277
|
+
expect( subject.aio_version?(agent1) ).to be === answers_row[1]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|
283
|
+
|
166
284
|
end
|
167
285
|
describe '#aio_agent?' do
|
168
286
|
it 'returns false if agent_only check doesn\'t pass' do
|
@@ -37,12 +37,13 @@ module Beaker
|
|
37
37
|
vagrant.make_vfile( @hosts )
|
38
38
|
|
39
39
|
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
40
|
+
puts "file is #{path}\n"
|
40
41
|
expect( vagrantfile ).to be === <<-EOF
|
41
42
|
Vagrant.configure("2") do |c|
|
42
43
|
c.ssh.insert_key = false
|
43
44
|
c.vm.define 'vm1' do |v|
|
44
45
|
v.vm.hostname = 'vm1'
|
45
|
-
v.vm.box = '
|
46
|
+
v.vm.box = 'vm2vm1_of_my_box'
|
46
47
|
v.vm.box_url = 'http://address.for.my.box.vm1'
|
47
48
|
v.vm.box_check_update = 'true'
|
48
49
|
v.vm.network :private_network, ip: "ip.address.for.vm1", :netmask => "255.255.0.0", :mac => "0123456789"
|
@@ -54,7 +55,7 @@ Vagrant.configure("2") do |c|
|
|
54
55
|
end
|
55
56
|
c.vm.define 'vm2' do |v|
|
56
57
|
v.vm.hostname = 'vm2'
|
57
|
-
v.vm.box = '
|
58
|
+
v.vm.box = 'vm2vm2_of_my_box'
|
58
59
|
v.vm.box_url = 'http://address.for.my.box.vm2'
|
59
60
|
v.vm.box_check_update = 'true'
|
60
61
|
v.vm.network :private_network, ip: "ip.address.for.vm2", :netmask => "255.255.0.0", :mac => "0123456789"
|
@@ -66,7 +67,7 @@ Vagrant.configure("2") do |c|
|
|
66
67
|
end
|
67
68
|
c.vm.define 'vm3' do |v|
|
68
69
|
v.vm.hostname = 'vm3'
|
69
|
-
v.vm.box = '
|
70
|
+
v.vm.box = 'vm2vm3_of_my_box'
|
70
71
|
v.vm.box_url = 'http://address.for.my.box.vm3'
|
71
72
|
v.vm.box_check_update = 'true'
|
72
73
|
v.vm.network :private_network, ip: "ip.address.for.vm3", :netmask => "255.255.0.0", :mac => "0123456789"
|
@@ -246,7 +247,6 @@ EOF
|
|
246
247
|
expect{ vagrant.get_ip_from_vagrant_file(host.name) }.to raise_error
|
247
248
|
end
|
248
249
|
end
|
249
|
-
|
250
250
|
end
|
251
251
|
|
252
252
|
describe "provisioning and cleanup" do
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
# safely set values for ARGV in block, restoring original value on block leave
|
4
|
+
def with_ARGV(value, &block)
|
5
|
+
if defined? ARGV
|
6
|
+
defined_ARGV, old_ARGV = true, ARGV
|
7
|
+
Object.send(:remove_const, :ARGV)
|
8
|
+
else
|
9
|
+
defined_ARGV, old_ARGV = false, nil
|
10
|
+
end
|
11
|
+
|
12
|
+
Object.send(:const_set, :ARGV, value)
|
13
|
+
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
Object.send(:remove_const, :ARGV)
|
17
|
+
Object.send(:const_set, :ARGV, old_ARGV) if defined_ARGV
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "Beaker Options" do
|
21
|
+
let (:parser) { Beaker::Options::Parser.new }
|
22
|
+
|
23
|
+
it "defaults :runner to 'native'" do
|
24
|
+
with_ARGV([]) do
|
25
|
+
expect(parser.parse_args[:runner]).to be == "native"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "accepts :runner from command-line" do
|
30
|
+
with_ARGV(["--runner", "minitest"]) do
|
31
|
+
expect(parser.parse_args[:runner]).to be == "minitest"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -128,6 +128,22 @@ module Beaker
|
|
128
128
|
|
129
129
|
end
|
130
130
|
|
131
|
-
|
131
|
+
context 'round tripping from yaml', if: RUBY_VERSION =~ /^1\.9/ do
|
132
|
+
before do
|
133
|
+
@name = 'ubuntu-14.04-x86_64'
|
134
|
+
end
|
135
|
+
|
136
|
+
let(:round_tripped) { YAML.load(YAML.dump(platform)) }
|
132
137
|
|
138
|
+
[:variant, :arch, :version, :codename].each do |field|
|
139
|
+
it "deserializes the '#{field}' field" do
|
140
|
+
expect(round_tripped.send(field)).to eq platform.send(field)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'properly sets the string contents' do
|
145
|
+
expect(round_tripped.to_s).to eq @name
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
133
149
|
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
module Runner
|
5
|
+
module Native
|
6
|
+
describe TestCase do
|
7
|
+
let(:logger) { double('logger').as_null_object }
|
8
|
+
let(:path) { @path || '/tmp/nope' }
|
9
|
+
let(:testcase) { TestCase.new({}, logger, {}, path) }
|
10
|
+
|
11
|
+
context 'run_test' do
|
12
|
+
it 'defaults to test_status :pass on success' do
|
13
|
+
path = 'test.rb'
|
14
|
+
File.open(path, 'w') do |f|
|
15
|
+
f.write ""
|
16
|
+
end
|
17
|
+
@path = path
|
18
|
+
expect( testcase ).to_not receive( :log_and_fail_test )
|
19
|
+
testcase.run_test
|
20
|
+
status = testcase.instance_variable_get(:@test_status)
|
21
|
+
expect(status).to be === :pass
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'updates test_status to :skip on SkipTest' do
|
25
|
+
path = 'test.rb'
|
26
|
+
File.open(path, 'w') do |f|
|
27
|
+
f.write "raise SkipTest"
|
28
|
+
end
|
29
|
+
@path = path
|
30
|
+
expect( testcase ).to_not receive( :log_and_fail_test )
|
31
|
+
testcase.run_test
|
32
|
+
status = testcase.instance_variable_get(:@test_status)
|
33
|
+
expect(status).to be === :skip
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'updates test_status to :pending on PendingTest' do
|
37
|
+
path = 'test.rb'
|
38
|
+
File.open(path, 'w') do |f|
|
39
|
+
f.write "raise PendingTest"
|
40
|
+
end
|
41
|
+
@path = path
|
42
|
+
expect( testcase ).to_not receive( :log_and_fail_test )
|
43
|
+
testcase.run_test
|
44
|
+
status = testcase.instance_variable_get(:@test_status)
|
45
|
+
expect(status).to be === :pending
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'updates test_status to :fail on FailTest' do
|
49
|
+
path = 'test.rb'
|
50
|
+
File.open(path, 'w') do |f|
|
51
|
+
f.write "raise FailTest"
|
52
|
+
end
|
53
|
+
@path = path
|
54
|
+
expect( testcase ).to_not receive( :log_and_fail_test )
|
55
|
+
testcase.run_test
|
56
|
+
status = testcase.instance_variable_get(:@test_status)
|
57
|
+
expect(status).to be === :fail
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'correctly handles RuntimeError' do
|
61
|
+
path = 'test.rb'
|
62
|
+
File.open(path, 'w') do |f|
|
63
|
+
f.write "raise RuntimeError"
|
64
|
+
end
|
65
|
+
@path = path
|
66
|
+
expect( testcase ).to receive( :log_and_fail_test ).once.with(kind_of(RuntimeError))
|
67
|
+
testcase.run_test
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'correctly handles ScriptError' do
|
71
|
+
path = 'test.rb'
|
72
|
+
File.open(path, 'w') do |f|
|
73
|
+
f.write "raise ScriptError"
|
74
|
+
end
|
75
|
+
@path = path
|
76
|
+
expect( testcase ).to receive( :log_and_fail_test ).once.with(kind_of(ScriptError))
|
77
|
+
testcase.run_test
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'correctly handles Timeout::Error' do
|
81
|
+
path = 'test.rb'
|
82
|
+
File.open(path, 'w') do |f|
|
83
|
+
f.write "raise Timeout::Error"
|
84
|
+
end
|
85
|
+
@path = path
|
86
|
+
expect( testcase ).to receive( :log_and_fail_test ).once.with(kind_of(Timeout::Error))
|
87
|
+
testcase.run_test
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'correctly handles CommandFailure' do
|
91
|
+
path = 'test.rb'
|
92
|
+
File.open(path, 'w') do |f|
|
93
|
+
f.write "raise Host::CommandFailure"
|
94
|
+
end
|
95
|
+
@path = path
|
96
|
+
expect( testcase ).to receive( :log_and_fail_test ).once.with(kind_of(Host::CommandFailure))
|
97
|
+
testcase.run_test
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'records a test failure if an assertion fails in a teardown block' do
|
101
|
+
path = 'test.rb'
|
102
|
+
File.open(path, 'w') do |f|
|
103
|
+
f.write <<-EOF
|
104
|
+
teardown do
|
105
|
+
assert_equal(1, 2, 'Oh noes!')
|
106
|
+
end
|
107
|
+
EOF
|
108
|
+
end
|
109
|
+
@path = path
|
110
|
+
expect( testcase ).to receive( :log_and_fail_test ).once.with(kind_of(Minitest::Assertion))
|
111
|
+
testcase.run_test
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'metadata' do
|
116
|
+
it 'sets the filename correctly from the path' do
|
117
|
+
answer = 'jacket'
|
118
|
+
path = "#{answer}.rb"
|
119
|
+
File.open(path, 'w') do |f|
|
120
|
+
f.write ""
|
121
|
+
end
|
122
|
+
@path = path
|
123
|
+
testcase.run_test
|
124
|
+
metadata = testcase.instance_variable_get(:@metadata)
|
125
|
+
expect(metadata[:case][:file_name]).to be === answer
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'resets the step name' do
|
129
|
+
path = 'test.rb'
|
130
|
+
File.open(path, 'w') do |f|
|
131
|
+
f.write ""
|
132
|
+
end
|
133
|
+
@path = path
|
134
|
+
# we have to create a TestCase by hand, so that we can set old
|
135
|
+
tc = TestCase.new({}, logger, {}, path)
|
136
|
+
# metadata on it, so that we can test that it's being reset correctly
|
137
|
+
old_metadata = { :step => { :name => 'CharlieBrown' } }
|
138
|
+
tc.instance_variable_set(:@metadata, old_metadata)
|
139
|
+
tc.run_test
|
140
|
+
metadata = tc.instance_variable_get(:@metadata)
|
141
|
+
expect(metadata[:step][:name]).to be_nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Beaker
|
5
|
+
module Runner
|
6
|
+
module Native
|
7
|
+
describe TestSuite do
|
8
|
+
context 'new' do
|
9
|
+
let(:test_dir) { 'tmp/tests' }
|
10
|
+
let(:options) { {'name' => create_files(@files)} }
|
11
|
+
let(:rb_test) { File.expand_path(test_dir + '/my_ruby_file.rb') }
|
12
|
+
let(:pl_test) { File.expand_path(test_dir + '/my_perl_file.pl') }
|
13
|
+
let(:sh_test) { File.expand_path(test_dir + '/my_shell_file.sh') }
|
14
|
+
|
15
|
+
it 'fails without test files' do
|
16
|
+
expect { Beaker::Runner::Native::TestSuite.new('name', 'hosts', Hash.new, Time.now, :stop_on_error) }.to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'includes specific files as test file when explicitly passed' do
|
20
|
+
@files = [ rb_test ]
|
21
|
+
ts = Beaker::Runner::Native::TestSuite.new('name', 'hosts', options, Time.now, :stop_on_error)
|
22
|
+
|
23
|
+
tfs = ts.instance_variable_get(:@test_files)
|
24
|
+
expect(tfs).to include rb_test
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'defaults to :slow fail_mode if not provided through parameter or options' do
|
28
|
+
@files = [ rb_test ]
|
29
|
+
ts = Beaker::Runner::Native::TestSuite.new('name', 'hosts', options, Time.now)
|
30
|
+
tfm = ts.instance_variable_get(:@fail_mode)
|
31
|
+
expect(tfm).to be == :slow
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'uses provided parameter fail_mode' do
|
35
|
+
@files = [ rb_test ]
|
36
|
+
ts = Beaker::Runner::Native::TestSuite.new('name', 'hosts', options, Time.now, :fast)
|
37
|
+
tfm = ts.instance_variable_get(:@fail_mode)
|
38
|
+
expect(tfm).to be == :fast
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'uses options fail_mode if fail_mode parameter is not provided' do
|
42
|
+
@files = [ rb_test ]
|
43
|
+
options[:fail_mode] = :fast
|
44
|
+
ts = Beaker::Runner::Native::TestSuite.new('name', 'hosts', options, Time.now)
|
45
|
+
tfm = ts.instance_variable_get(:@fail_mode)
|
46
|
+
expect(tfm).to be == :fast
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'run' do
|
51
|
+
let( :options ) { make_opts.merge({ :logger => double().as_null_object, 'name' => create_files(@files), :log_dated_dir => '.', :xml_dated_dir => '.'}) }
|
52
|
+
let(:broken_script) { "raise RuntimeError" }
|
53
|
+
let(:fail_script) { "raise Beaker::DSL::Outcomes::FailTest" }
|
54
|
+
let(:okay_script) { "true" }
|
55
|
+
let(:rb_test) { 'my_ruby_file.rb' }
|
56
|
+
let(:pl_test) { '/my_perl_file.pl' }
|
57
|
+
let(:sh_test) { '/my_shell_file.sh' }
|
58
|
+
let(:hosts) { make_hosts() }
|
59
|
+
|
60
|
+
it 'fails fast if fail_mode != :slow and runtime error is raised' do
|
61
|
+
allow( Logger ).to receive('new')
|
62
|
+
@files = [ rb_test, pl_test, sh_test]
|
63
|
+
File.open(rb_test, 'w') { |file| file.write(broken_script) }
|
64
|
+
File.open(pl_test, 'w') { |file| file.write(okay_script) }
|
65
|
+
File.open(sh_test, 'w') { |file| file.write(okay_script) }
|
66
|
+
|
67
|
+
ts = Beaker::Runner::Native::TestSuite.new( 'name', hosts, options, Time.now, :stop )
|
68
|
+
tsr = ts.instance_variable_get( :@test_suite_results )
|
69
|
+
allow( tsr ).to receive(:write_junit_xml).and_return( true )
|
70
|
+
allow( tsr ).to receive(:summarize).and_return( true )
|
71
|
+
|
72
|
+
ts.run
|
73
|
+
expect( tsr.errored_tests ).to be === 1
|
74
|
+
expect( tsr.failed_tests ).to be === 0
|
75
|
+
expect( tsr.test_count ).to be === 1
|
76
|
+
expect( tsr.passed_tests).to be === 0
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'fails fast if fail_mode != :slow and fail test is raised' do
|
80
|
+
allow( Logger ).to receive('new')
|
81
|
+
@files = [ rb_test, pl_test, sh_test]
|
82
|
+
File.open(rb_test, 'w') { |file| file.write(fail_script) }
|
83
|
+
File.open(pl_test, 'w') { |file| file.write(okay_script) }
|
84
|
+
File.open(sh_test, 'w') { |file| file.write(okay_script) }
|
85
|
+
|
86
|
+
ts = Beaker::Runner::Native::TestSuite.new( 'name', hosts, options, Time.now, :stop )
|
87
|
+
tsr = ts.instance_variable_get( :@test_suite_results )
|
88
|
+
allow( tsr ).to receive(:write_junit_xml).and_return( true )
|
89
|
+
allow( tsr ).to receive(:summarize).and_return( true )
|
90
|
+
|
91
|
+
ts.run
|
92
|
+
expect( tsr.errored_tests ).to be === 0
|
93
|
+
expect( tsr.failed_tests ).to be === 1
|
94
|
+
expect( tsr.test_count ).to be === 1
|
95
|
+
expect( tsr.passed_tests).to be === 0
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'fails slow if fail_mode = :slow, even if a test fails and there is a runtime error' do
|
99
|
+
allow( Logger ).to receive('new')
|
100
|
+
@files = [ rb_test, pl_test, sh_test]
|
101
|
+
File.open(rb_test, 'w') { |file| file.write(broken_script) }
|
102
|
+
File.open(pl_test, 'w') { |file| file.write(fail_script) }
|
103
|
+
File.open(sh_test, 'w') { |file| file.write(okay_script) }
|
104
|
+
|
105
|
+
ts = Beaker::Runner::Native::TestSuite.new( 'name', hosts, options, Time.now, :slow )
|
106
|
+
tsr = ts.instance_variable_get( :@test_suite_results )
|
107
|
+
allow( tsr ).to receive(:write_junit_xml).and_return( true )
|
108
|
+
allow( tsr ).to receive(:summarize).and_return( true )
|
109
|
+
|
110
|
+
ts.run
|
111
|
+
expect( tsr.errored_tests ).to be === 1
|
112
|
+
expect( tsr.failed_tests ).to be === 1
|
113
|
+
expect( tsr.test_count ).to be === 3
|
114
|
+
expect( tsr.passed_tests).to be === 1
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe TestSuite::TestSuiteResult do
|
119
|
+
let( :options ) { make_opts.merge({ :logger => double().as_null_object }) }
|
120
|
+
let( :hosts ) { make_hosts() }
|
121
|
+
let( :testcase1 ) { Beaker::Runner::Native::TestCase.new( hosts, options[:logger], options) }
|
122
|
+
let( :testcase2 ) { Beaker::Runner::Native::TestCase.new( hosts, options[:logger], options) }
|
123
|
+
let( :testcase3 ) { Beaker::Runner::Native::TestCase.new( hosts, options[:logger], options) }
|
124
|
+
let( :test_suite_result ) { TestSuite::TestSuiteResult.new( options, "my_suite") }
|
125
|
+
|
126
|
+
it 'supports adding test cases' do
|
127
|
+
expect( test_suite_result.test_count ).to be === 0
|
128
|
+
test_suite_result.add_test_case( testcase1 )
|
129
|
+
expect( test_suite_result.test_count ).to be === 1
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'calculates passed tests' do
|
133
|
+
testcase1.instance_variable_set(:@test_status, :pass)
|
134
|
+
testcase2.instance_variable_set(:@test_status, :pass)
|
135
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
136
|
+
test_suite_result.add_test_case( testcase1 )
|
137
|
+
test_suite_result.add_test_case( testcase2 )
|
138
|
+
test_suite_result.add_test_case( testcase3 )
|
139
|
+
expect( test_suite_result.passed_tests ).to be == 2
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'calculates failed tests' do
|
143
|
+
testcase1.instance_variable_set(:@test_status, :pass)
|
144
|
+
testcase2.instance_variable_set(:@test_status, :pass)
|
145
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
146
|
+
test_suite_result.add_test_case( testcase1 )
|
147
|
+
test_suite_result.add_test_case( testcase2 )
|
148
|
+
test_suite_result.add_test_case( testcase3 )
|
149
|
+
expect( test_suite_result.failed_tests ).to be == 1
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'calculates errored tests' do
|
153
|
+
testcase1.instance_variable_set(:@test_status, :error)
|
154
|
+
testcase2.instance_variable_set(:@test_status, :pass)
|
155
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
156
|
+
test_suite_result.add_test_case( testcase1 )
|
157
|
+
test_suite_result.add_test_case( testcase2 )
|
158
|
+
test_suite_result.add_test_case( testcase3 )
|
159
|
+
expect( test_suite_result.errored_tests ).to be == 1
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'calculates skipped tests' do
|
163
|
+
testcase1.instance_variable_set(:@test_status, :error)
|
164
|
+
testcase2.instance_variable_set(:@test_status, :skip)
|
165
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
166
|
+
test_suite_result.add_test_case( testcase1 )
|
167
|
+
test_suite_result.add_test_case( testcase2 )
|
168
|
+
test_suite_result.add_test_case( testcase3 )
|
169
|
+
expect( test_suite_result.skipped_tests ).to be == 1
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'calculates pending tests' do
|
173
|
+
testcase1.instance_variable_set(:@test_status, :error)
|
174
|
+
testcase2.instance_variable_set(:@test_status, :pending)
|
175
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
176
|
+
test_suite_result.add_test_case( testcase1 )
|
177
|
+
test_suite_result.add_test_case( testcase2 )
|
178
|
+
test_suite_result.add_test_case( testcase3 )
|
179
|
+
expect( test_suite_result.pending_tests ).to be == 1
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'calculates sum_failed as a sum of errored and failed TestCases' do
|
183
|
+
testcase1.instance_variable_set(:@test_status, :error)
|
184
|
+
testcase2.instance_variable_set(:@test_status, :pending)
|
185
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
186
|
+
test_suite_result.add_test_case( testcase1 )
|
187
|
+
test_suite_result.add_test_case( testcase2 )
|
188
|
+
test_suite_result.add_test_case( testcase3 )
|
189
|
+
expect( test_suite_result.sum_failed ).to be == 2
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'reports success with no errors/failures' do
|
193
|
+
testcase1.instance_variable_set(:@test_status, :pass)
|
194
|
+
testcase2.instance_variable_set(:@test_status, :pending)
|
195
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
196
|
+
test_suite_result.add_test_case( testcase1 )
|
197
|
+
test_suite_result.add_test_case( testcase2 )
|
198
|
+
test_suite_result.add_test_case( testcase3 )
|
199
|
+
expect( test_suite_result.success? ).to be == false
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'reports failed if any tests error/fail' do
|
203
|
+
testcase1.instance_variable_set(:@test_status, :pass)
|
204
|
+
testcase2.instance_variable_set(:@test_status, :pending)
|
205
|
+
testcase3.instance_variable_set(:@test_status, :fail)
|
206
|
+
test_suite_result.add_test_case( testcase1 )
|
207
|
+
test_suite_result.add_test_case( testcase2 )
|
208
|
+
test_suite_result.add_test_case( testcase3 )
|
209
|
+
expect( test_suite_result.failed? ).to be == true
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'can calculate the sum of all TestCase runtimes' do
|
213
|
+
testcase1.instance_variable_set(:@runtime, 1)
|
214
|
+
testcase2.instance_variable_set(:@runtime, 10)
|
215
|
+
testcase3.instance_variable_set(:@runtime, 100)
|
216
|
+
test_suite_result.add_test_case( testcase1 )
|
217
|
+
test_suite_result.add_test_case( testcase2 )
|
218
|
+
test_suite_result.add_test_case( testcase3 )
|
219
|
+
expect( test_suite_result.elapsed_time ).to be == 111
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#write_junit_xml' do
|
223
|
+
let( :options ) { make_opts.merge({ :logger => double().as_null_object, 'name' => create_files(@files), :log_dated_dir => '.', :xml_dated_dir => '.'}) }
|
224
|
+
let(:rb_test) { 'my_ruby_file.rb' }
|
225
|
+
|
226
|
+
it 'doesn\'t re-order test cases themselves on time_sort' do
|
227
|
+
nokogiri_mock = Hash.new
|
228
|
+
allow( nokogiri_mock ).to receive( :add_child )
|
229
|
+
allow( Nokogiri::XML::Node ).to receive( :new ) { nokogiri_mock }
|
230
|
+
allow( LoggerJunit ).to receive( :write_xml ).and_yield( Object.new, nokogiri_mock )
|
231
|
+
|
232
|
+
@files = [ rb_test, rb_test, rb_test]
|
233
|
+
ts = Beaker::Runner::Native::TestSuite.new( 'name', hosts, options, Time.now, :fast )
|
234
|
+
tsr = ts.instance_variable_get( :@test_suite_results )
|
235
|
+
|
236
|
+
allow( tsr ).to receive( :start_time ).and_return(0)
|
237
|
+
allow( tsr ).to receive( :stop_time ).and_return(10)
|
238
|
+
expect( tsr.instance_variable_get( :@logger ) ).to receive( :error ).never
|
239
|
+
|
240
|
+
test_cases = []
|
241
|
+
3.times do
|
242
|
+
tc = Beaker::Runner::Native::TestCase.new( hosts, options[:logger], options, rb_test)
|
243
|
+
allow( tc ).to receive( :sublog ).and_return( false )
|
244
|
+
test_cases << tc
|
245
|
+
end
|
246
|
+
test_cases[0].instance_variable_set(:@runtime, 3)
|
247
|
+
test_cases[1].instance_variable_set(:@runtime, 301)
|
248
|
+
test_cases[2].instance_variable_set(:@runtime, 101)
|
249
|
+
test_cases.map { |tc| tsr.add_test_case( tc ) }
|
250
|
+
|
251
|
+
original_testcase_order = test_suite_result.instance_variable_get( :@test_cases ).dup
|
252
|
+
tsr.write_junit_xml( 'fakeFilePath07', 'fakeFileToLink09', true )
|
253
|
+
after_testcase_order = test_suite_result.instance_variable_get( :@test_cases ).dup
|
254
|
+
expect( after_testcase_order ).to be === original_testcase_order
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe '#log_path' do
|
260
|
+
let( :sh_test ) { '/my_shell_file.sh' }
|
261
|
+
let( :files ) { @files ? @files : [sh_test] }
|
262
|
+
let( :options ) { make_opts.merge({ :logger => double().as_null_object, 'name' => create_files(files) }) }
|
263
|
+
let( :hosts ) { make_hosts() }
|
264
|
+
let( :testsuite ) { Beaker::Runner::Native::TestSuite.new( 'name', hosts, options, Time.now, :stop ) }
|
265
|
+
|
266
|
+
it 'returns the simple joining of the log dir & file as required' do
|
267
|
+
expect(testsuite.log_path('foo.txt', 'man/date')).to be === 'man/date/foo.txt'
|
268
|
+
end
|
269
|
+
|
270
|
+
describe 'builds the base directory correctly' do
|
271
|
+
# the base directory is where the latest symlink itself should live
|
272
|
+
it 'in the usual case' do
|
273
|
+
expect( File.symlink?('man/latest') ).to be_falsy
|
274
|
+
testsuite.log_path('foo.txt', 'man/date')
|
275
|
+
expect( File.symlink?('man/latest') ).to be_truthy
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'if given a nested directory' do
|
279
|
+
expect( File.symlink?('a/latest') ).to be_falsy
|
280
|
+
testsuite.log_path('foo.txt', 'a/b/c/d/e/f')
|
281
|
+
expect( File.symlink?('a/latest') ).to be_truthy
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
describe 'builds the symlink directory correctly' do
|
286
|
+
# the symlink directory is where the symlink points to
|
287
|
+
it 'in the usual case' do
|
288
|
+
expect( File.symlink?('d/latest') ).to be_falsy
|
289
|
+
testsuite.log_path('foo.txt', 'd/e')
|
290
|
+
expect( File.readlink('d/latest') ).to be === 'e'
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'if given a nested directory' do
|
294
|
+
expect( File.symlink?('f/latest') ).to be_falsy
|
295
|
+
testsuite.log_path('foo.txt', 'f/g/h/i/j/k')
|
296
|
+
expect( File.readlink('f/latest') ).to be === 'g/h/i/j/k'
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|