beaker 2.29.1 → 2.30.0
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 +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
|