beaker 3.22.0 → 3.23.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -32,18 +32,23 @@ that are needed for it. An example `.fog` file is below:
32
32
 
33
33
  # External Hypervisors
34
34
 
35
- Puppetlabs and its community have made several gems that support different hypervisors with beaker, the reason for this is that we're looking to decrease Beaker's
35
+ Puppet and its community have made several gems that support different
36
+ hypervisors with beaker, the reason for this is that we're looking to decrease Beaker's
36
37
  dependency footprint, and hypervisors are one of the places where we can often
37
38
  increase the load across all Beaker uses to benefit a small group that uses a
38
39
  particular hypervisor.
39
40
 
40
- In order to offset this, we've made a listing of gems and community-supported forks that support other external hypervisors. Please check them out if you'd like to use those hypervisors, hopefully it'll save you from spending time trying to support a new hypervisor yourself.
41
+ In order to offset this, we've made a listing of gems and community-supported forks
42
+ that support other external hypervisors. Please check them out if you'd like to use
43
+ those hypervisors, hopefully it'll save you from spending time trying to support a
44
+ new hypervisor yourself.
41
45
 
42
- Hypervisor gems made by puppet (pre-included in beaker 3.x):
46
+ ### Hypervisor gems made by puppet (pre-included in beaker 3.x):
43
47
 
44
48
  | Hypervisor | Fork |
45
49
  | :----------------------: | :---------------------------------------------------------: |
46
50
  | Vmpooler | [beaker-vmpooler](https://github.com/puppetlabs/beaker-vmpooler) |
51
+ | Vcloud | [beaker-vcloud](https://github.com/puppetlabs/beaker-vcloud) |
47
52
  | AWS | [beaker-aws](https://github.com/puppetlabs/beaker-aws) |
48
53
  | Vagrant | [beaker-vagrant](https://github.com/puppetlabs/beaker-vagrant) |
49
54
  | VMware/Vsphere | [beaker-vmware](https://github.com/puppetlabs/beaker-vmware) |
@@ -51,7 +56,19 @@ Hypervisor gems made by puppet (pre-included in beaker 3.x):
51
56
  | Openstack | [beaker-openstack](https://github.com/puppetlabs/beaker-openstack) |
52
57
  | Google Compute | [beaker-google](https://github.com/puppetlabs/beaker-google) |
53
58
 
54
- Hypervisor gems and beaker forks made by community:
59
+
60
+ ### beaker-abs
61
+
62
+ There is another hypervisor made and used internally by puppet,
63
+ [beaker-abs](https://github.com/puppetlabs/beaker-abs), but it isn't included
64
+ in beaker 3.x. If you'd like to use beaker-abs, you'll have to include it yourself.
65
+
66
+ You do that by requiring beaker-abs in your Gemfile as a sibling to beaker itself
67
+ and then using `abs` as your hypervisor value in your hosts file. Please check the
68
+ [beaker-abs README](https://github.com/puppetlabs/beaker-abs/blob/master/README.md)
69
+ for more information.
70
+
71
+ ### Hypervisor gems and beaker forks made by community:
55
72
 
56
73
  | Hypervisor | Fork |
57
74
  |:------------:|:--------------------------------------------------------------------:|
@@ -83,13 +83,4 @@ The platform's format is `/^OSFAMILY-VERSION-ARCH.*$/` where `OSFAMILY` is one o
83
83
 
84
84
  `VERSION`'s format is not enforced, but should reflect the `OSFAMILY` selected (ie, ubuntu-1204-i386-master, scientific-6-i386-agent, etc). `ARCH`'s format is also not enforced, but should be appropriate to the `OSFAMILY` selected (ie, ubuntu-1204-i386-master, sles-11-x86_64-master, debian-7-amd64-master, etc).
85
85
 
86
- ## Supported Virtualization Providers ##
87
- * [AWS](../how_to/hypervisors/aws.md)
88
- * [VMWare Fusion](../how_to/hypervisors/vmware_fusion.md)
89
- * [EC2](../how_to/hypervisors/ec2.md)
90
- * [vSphere](../how_to/hypervisors/vsphere.md)
91
- * [Vagrant](../how_to/hypervisors/vagrant.md)
92
- * [Google Compute Engine](../how_to/hypervisors/google_compute_engine.md)
93
- * [Docker Support](../how_to/hypervisors/docker.md)
94
- * [Openstack](../how_to/hypervisors/openstack.md)
95
- * [Solaris](../how_to/hypervisors/solaris.md)
86
+ ## [Supported Virtualization Providers](../how_to/hypervisors/README.md#external-hypervisors) ##
@@ -1,7 +1,7 @@
1
1
  require 'rubygems' unless defined?(Gem)
2
2
  module Beaker
3
3
 
4
- %w( version platform test_suite result command options network_manager cli perf logger_junit subcommand ).each do |lib|
4
+ %w( version platform test_suite test_suite_result result command options network_manager cli perf logger_junit subcommand ).each do |lib|
5
5
  begin
6
6
  require "beaker/#{lib}"
7
7
  rescue LoadError
@@ -31,7 +31,7 @@ module Beaker
31
31
  # end
32
32
  #
33
33
  module Structure
34
-
34
+ require 'pry'
35
35
  # Provides a method to help structure tests into coherent steps.
36
36
  # @param [String] step_name The name of the step to be logged.
37
37
  # @param [Proc] block The actions to be performed in this step.
@@ -40,7 +40,16 @@ module Beaker
40
40
  set_current_step_name(step_name)
41
41
  if block_given?
42
42
  logger.step_in()
43
- yield
43
+ begin
44
+ yield
45
+ rescue Exception => e
46
+ if(@options.has_key?(:debug_errors) && @options[:debug_errors] == true)
47
+ logger.info("Exception raised during step execution and debug-errors option is set, entering pry. Exception was: #{e.inspect}")
48
+ logger.info("HINT: Use the pry 'backtrace' and 'up' commands to navigate to the test code")
49
+ binding.pry
50
+ end
51
+ raise e
52
+ end
44
53
  logger.step_out()
45
54
  end
46
55
  end
@@ -74,7 +74,7 @@ module Unix::Pkg
74
74
  def install_package(name, cmdline_args = '', version = nil, opts = {})
75
75
  case self['platform']
76
76
  when /sles-/
77
- execute("zypper --non-interactive in #{name}", opts)
77
+ execute("zypper --non-interactive --gpg-auto-import-keys in #{name}", opts)
78
78
  when /el-4/
79
79
  @logger.debug("Package installation not supported on rhel4")
80
80
  when /fedora-(2[2-9])/
@@ -1,10 +1,11 @@
1
+ require 'rexml/document'
1
2
  module Beaker
2
3
  # The Beaker JUnit Logger class
3
4
  # This module handles message reporting from Beaker to the JUnit format
4
5
  #
5
6
  # There is a specific pattern for using this class.
6
7
  # Here's a list of example usages:
7
- # - {Beaker::TestSuite::TestSuiteResult#write_junit_xml}
8
+ # - {Beaker::TestSuiteResult#write_junit_xml}
8
9
  module LoggerJunit
9
10
 
10
11
  # writes the xml created in the block to the xml file given
@@ -34,14 +35,14 @@ module Beaker
34
35
 
35
36
  # writes out xml content for a doc
36
37
  #
37
- # @param [Nokogiri::XML] doc Nokogiri doc containing content to write
38
+ # @param [REXML::Document] doc doc containing content to write
38
39
  # @param [String] xml_file Path to the xml file to write
39
40
  #
40
41
  # @return nil
41
42
  def self.finish(doc, xml_file)
42
43
  # junit/name.xml will be created in a directory relative to the CWD
43
- # -- JLS 2/12
44
- File.open(xml_file, 'w') { |fh| fh.write(doc.to_xml) }
44
+
45
+ File.open(xml_file, 'w') { |f| doc.write(f, 2) }
45
46
  end
46
47
 
47
48
  # gets the xml doc & suites in order to build your xml output on top of
@@ -50,8 +51,8 @@ module Beaker
50
51
  # @param [String] name Name of the testsuite you're writing
51
52
  # @param [String] stylesheet Path to the stylesheet file
52
53
  #
53
- # @return [Nokogiri::XML] doc to use for your xml content
54
- # @return [Nokogiri::XML::Node] suites to add your content to
54
+ # @return [REXML::Document] doc to use for your xml content
55
+ # @return [REXML::Element] suites to add your content to
55
56
  def self.get_xml_contents(xml_file, name, stylesheet)
56
57
  self.copy_stylesheet_into_xml_dir(stylesheet, xml_file)
57
58
  xml_file_already_exists = File.file?(xml_file)
@@ -74,24 +75,23 @@ module Beaker
74
75
 
75
76
  # sets up doc & gives us the suites for the testsuite named
76
77
  #
77
- # @param [Nokogiri::XML] doc Doc that you're getting suites from
78
+ # @param [REXML::Document] doc Doc that you're getting suites from
78
79
  # @param [String] name Testsuite node name
79
80
  # @param [Boolean] already_existed Whether or not the doc already existed
80
81
  #
81
- # @return [Nokogiri::XML::Node] testsuites
82
+ # @return [Rexml::Element] testsuites
82
83
  def self.get_testsuites_from_doc(doc, name, already_existed)
83
84
  #check to see if an output file already exists, if it does add or replace test suite data
84
85
  if already_existed
85
- suites = doc.at_xpath('testsuites')
86
+ suites = REXML::XPath.first(doc, "testsuites")
86
87
  #remove old data
87
- doc.search("//testsuite").each do |node|
88
- if node['name'] =~ /#{name}/
89
- node.unlink
88
+ suites.elements.each("testsuite") do |e|
89
+ if e.name =~ /#{name}/
90
+ suites.delete_element e
90
91
  end
91
92
  end
92
93
  else
93
- suites = Nokogiri::XML::Node.new('testsuites', doc)
94
- suites.parent = doc
94
+ suites = doc.add_element(REXML::Element.new('testsuites'))
95
95
  end
96
96
  return suites
97
97
  end
@@ -102,16 +102,16 @@ module Beaker
102
102
  # @param [String] stylesheet Path to the stylesheet for this doc
103
103
  # @param [Boolean] already_exists Whether or not the file already exists
104
104
  #
105
- # @return [Nokogiri::XML] Doc that you want to write in
105
+ # @return [REXML::Document] Doc that you want to write in
106
106
  def self.get_doc_for_filename(filename, stylesheet, already_exists)
107
107
  if already_exists
108
- doc = Nokogiri::XML(File.open(filename, 'r'))
108
+ doc = REXML::Document.new File.open(filename)
109
109
  else
110
110
  #no existing file, create a new one
111
- doc = Nokogiri::XML::Document.new()
112
- doc.encoding = 'UTF-8'
113
- pi = Nokogiri::XML::ProcessingInstruction.new(doc, "xml-stylesheet", "type=\"text/xsl\" href=\"#{File.basename(stylesheet)}\"")
114
- pi.parent = doc
111
+ doc = REXML::Document.new
112
+ doc << REXML::XMLDecl.new(version="1.0", encoding="UTF-8")
113
+ instruction_content = "type='text/xsl' href='#{File.basename(stylesheet)}'"
114
+ doc << REXML::Instruction.new(target="xml-stylesheet", content=instruction_content)
115
115
  end
116
116
  return doc
117
117
  end
@@ -154,4 +154,4 @@ module Beaker
154
154
  end
155
155
 
156
156
  end
157
- end
157
+ end
@@ -88,6 +88,12 @@ module Beaker
88
88
  @cmd_options[:preserve_hosts] = mode || 'always'
89
89
  end
90
90
 
91
+ opts.on '--debug-errors',
92
+ 'Enter a pry console if or when a test fails',
93
+ '(default: false)' do |bool|
94
+ @cmd_options[:debug_errors] = bool
95
+ end
96
+
91
97
  opts.on '--root-keys',
92
98
  'Install puppetlabs pubkeys for superuser',
93
99
  '(default: false)' do |bool|
@@ -51,6 +51,7 @@ module Beaker
51
51
  class_option :tag, :type => :string, :group => 'Beaker run'
52
52
  class_option :'exclude-tags', :type => :string, :group => 'Beaker run'
53
53
  class_option :'xml-time-order', :type => :boolean, :group => 'Beaker run'
54
+ class_option :'debug-errors', :type => :boolean, :group => 'Beaker run'
54
55
 
55
56
  # The following are listed as deprecated in beaker --help, but needed now for
56
57
  # feature parity for beaker 3.x.
@@ -1,7 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
- require 'nokogiri'
3
2
  require 'fileutils'
4
- [ 'test_case', 'logger' ].each do |lib|
3
+ [ 'test_case', 'logger', 'test_suite_result'].each do |lib|
5
4
  require "beaker/#{lib}"
6
5
  end
7
6
 
@@ -10,264 +9,6 @@ module Beaker
10
9
  #Handles executing the set of {TestCase} instances and reporting results as post summary text and JUnit XML.
11
10
  class TestSuite
12
11
 
13
- #Holds the output of a test suite, formats in plain text or xml
14
- class TestSuiteResult
15
- attr_accessor :start_time, :stop_time, :total_tests
16
-
17
- #Create a {TestSuiteResult} instance.
18
- #@param [Hash{Symbol=>String}] options Options for this object
19
- #@option options [Logger] :logger The Logger object to report information to
20
- #@param [String] name The name of the {TestSuite} that the results are for
21
- def initialize( options, name )
22
- @options = options
23
- @logger = options[:logger]
24
- @name = name
25
- @test_cases = []
26
- #Set some defaults, just in case you attempt to print without including them
27
- start_time = Time.at(0)
28
- stop_time = Time.at(1)
29
- end
30
-
31
- #Add a {TestCase} to this {TestSuiteResult} instance, used in calculating {TestSuiteResult} data.
32
- #@param [TestCase] test_case An individual, completed {TestCase} to be included in this set of {TestSuiteResult}.
33
- def add_test_case( test_case )
34
- @test_cases << test_case
35
- end
36
-
37
- #How many {TestCase} instances are in this {TestSuiteResult}
38
- def test_count
39
- @test_cases.length
40
- end
41
-
42
- #How many passed {TestCase} instances are in this {TestSuiteResult}
43
- def passed_tests
44
- @test_cases.select { |c| c.test_status == :pass }.length
45
- end
46
-
47
- #How many errored {TestCase} instances are in this {TestSuiteResult}
48
- def errored_tests
49
- @test_cases.select { |c| c.test_status == :error }.length
50
- end
51
-
52
- #How many failed {TestCase} instances are in this {TestSuiteResult}
53
- def failed_tests
54
- @test_cases.select { |c| c.test_status == :fail }.length
55
- end
56
-
57
- #How many skipped {TestCase} instances are in this {TestSuiteResult}
58
- def skipped_tests
59
- @test_cases.select { |c| c.test_status == :skip }.length
60
- end
61
-
62
- #How many pending {TestCase} instances are in this {TestSuiteResult}
63
- def pending_tests
64
- @test_cases.select {|c| c.test_status == :pending}.length
65
- end
66
-
67
- #How many {TestCase} instances failed in this {TestSuiteResult}
68
- def sum_failed
69
- failed_tests + errored_tests
70
- end
71
-
72
- #Did all the {TestCase} instances in this {TestSuiteResult} pass?
73
- def success?
74
- sum_failed == 0
75
- end
76
-
77
- #Did one or more {TestCase} instances in this {TestSuiteResult} fail?
78
- def failed?
79
- !success?
80
- end
81
-
82
- #The sum of all {TestCase} runtimes in this {TestSuiteResult}
83
- def elapsed_time
84
- @test_cases.inject(0.0) {|r, t| r + t.runtime.to_f }
85
- end
86
-
87
- #Plain text summay of test suite
88
- #@param [Logger] summary_logger The logger we will print the summary to
89
- def summarize(summary_logger)
90
-
91
- summary_logger.notify <<-HEREDOC
92
- Test Suite: #{@name} @ #{start_time}
93
-
94
- - Host Configuration Summary -
95
- HEREDOC
96
-
97
- average_test_time = elapsed_time / test_count
98
-
99
- summary_logger.notify %Q[
100
-
101
- - Test Case Summary for suite '#{@name}' -
102
- Total Suite Time: %.2f seconds
103
- Average Test Time: %.2f seconds
104
- Attempted: #{test_count}
105
- Passed: #{passed_tests}
106
- Failed: #{failed_tests}
107
- Errored: #{errored_tests}
108
- Skipped: #{skipped_tests}
109
- Pending: #{pending_tests}
110
- Total: #{@total_tests}
111
-
112
- - Specific Test Case Status -
113
- ] % [elapsed_time, average_test_time]
114
-
115
- grouped_summary = @test_cases.group_by{|test_case| test_case.test_status }
116
-
117
- summary_logger.notify "Failed Tests Cases:"
118
- (grouped_summary[:fail] || []).each do |test_case|
119
- summary_logger.notify print_test_result(test_case)
120
- end
121
-
122
- summary_logger.notify "Errored Tests Cases:"
123
- (grouped_summary[:error] || []).each do |test_case|
124
- summary_logger.notify print_test_result(test_case)
125
- end
126
-
127
- summary_logger.notify "Skipped Tests Cases:"
128
- (grouped_summary[:skip] || []).each do |test_case|
129
- summary_logger.notify print_test_result(test_case)
130
- end
131
-
132
- summary_logger.notify "Pending Tests Cases:"
133
- (grouped_summary[:pending] || []).each do |test_case|
134
- summary_logger.notify print_test_result(test_case)
135
- end
136
-
137
- summary_logger.notify("\n\n")
138
- end
139
-
140
- #A convenience method for printing the results of a {TestCase}
141
- #@param [TestCase] test_case The {TestCase} to examine and print results for
142
- def print_test_result(test_case)
143
- if test_case.exception
144
- test_file_trace = ""
145
- test_case.exception.backtrace.each do |line|
146
- if line.include?(test_case.path)
147
- test_file_trace = "\r\n Test line: #{line}"
148
- break
149
- end
150
- end if test_case.exception.backtrace && test_case.path
151
- test_reported = "reported: #{test_case.exception.inspect}#{test_file_trace}"
152
- else
153
- test_case.test_status
154
- end
155
- " Test Case #{test_case.path} #{test_reported}"
156
- end
157
-
158
- # Writes Junit XML of this {TestSuiteResult}
159
- #
160
- # @param [String] xml_file Path to the XML file (from Beaker's running directory)
161
- # @param [String] file_to_link Path to the paired file that should be linked
162
- # from this one (this is relative to the XML
163
- # file itself, so it would just be the different
164
- # file name if they're in the same directory)
165
- # @param [Boolean] time_sort Whether the test results should be output in
166
- # order of time spent in the test, or in the
167
- # order of test execution (default)
168
- #
169
- # @return nil
170
- # @api private
171
- def write_junit_xml(xml_file, file_to_link = nil, time_sort = false)
172
- stylesheet = File.join(@options[:project_root], @options[:xml_stylesheet])
173
-
174
- begin
175
- LoggerJunit.write_xml(xml_file, stylesheet) do |doc, suites|
176
-
177
- meta_info = Nokogiri::XML::Node.new('meta_test_info', doc)
178
- unless file_to_link.nil?
179
- meta_info['page_active'] = time_sort ? 'performance' : 'execution'
180
- meta_info['link_url'] = file_to_link
181
- else
182
- meta_info['page_active'] = 'no-links'
183
- meta_info['link_url'] = ''
184
- end
185
- suites.add_child(meta_info)
186
-
187
- suite = Nokogiri::XML::Node.new('testsuite', doc)
188
- suite['name'] = @name
189
- suite['tests'] = test_count
190
- suite['errors'] = errored_tests
191
- suite['failures'] = failed_tests
192
- suite['skipped'] = skipped_tests
193
- suite['pending'] = pending_tests
194
- suite['total'] = @total_tests
195
- suite['time'] = "%f" % (stop_time - start_time)
196
- properties = Nokogiri::XML::Node.new('properties', doc)
197
- @options.each_pair do | name, value |
198
- property = Nokogiri::XML::Node.new('property', doc)
199
- property['name'] = name
200
- property['value'] = value
201
- properties.add_child(property)
202
- end
203
- suite.add_child(properties)
204
-
205
- test_cases_to_report = @test_cases
206
- test_cases_to_report = @test_cases.sort { |x,y| y.runtime <=> x.runtime } if time_sort
207
- test_cases_to_report.each do |test|
208
- item = Nokogiri::XML::Node.new('testcase', doc)
209
- item['classname'] = File.dirname(test.path)
210
- item['name'] = File.basename(test.path)
211
- item['time'] = "%f" % test.runtime
212
-
213
- #ugh. nokogiri!!! item can't take a hash, let alone an array.
214
- test.exports.each do |export|
215
- export.keys.each do |key|
216
- item[key] = export[key]
217
- end
218
- end
219
-
220
- # Did we fail? If so, report that.
221
- # We need to remove the escape character from colorized text, the
222
- # substitution of other entities is handled well by Rexml
223
- if test.test_status == :fail || test.test_status == :error then
224
- status = Nokogiri::XML::Node.new('failure', doc)
225
- status['type'] = test.test_status.to_s
226
- if test.exception then
227
- status['message'] = test.exception.to_s.gsub(/\e/, '')
228
- data = LoggerJunit.format_cdata(test.exception.backtrace.join('\n'))
229
- status.add_child(status.document.create_cdata(data))
230
- end
231
- item.add_child(status)
232
- end
233
-
234
- if test.test_status == :skip
235
- status = Nokogiri::XML::Node.new('skipped', doc)
236
- status['type'] = test.test_status.to_s
237
- item.add_child(status)
238
- end
239
-
240
- if test.test_status == :pending
241
- status = Nokogiri::XML::Node.new('pending', doc)
242
- status['type'] = test.test_status.to_s
243
- item.add_child(status)
244
- end
245
-
246
- if test.sublog then
247
- stdout = Nokogiri::XML::Node.new('system-out', doc)
248
- data = LoggerJunit.format_cdata(test.sublog)
249
- stdout.add_child(stdout.document.create_cdata(data))
250
- item.add_child(stdout)
251
- end
252
-
253
- if test.last_result and test.last_result.stderr and not test.last_result.stderr.empty? then
254
- stderr = Nokogiri::XML::Node.new('system-err', doc)
255
- data = LoggerJunit.format_cdata(test.last_result.stderr)
256
- stderr.add_child(stderr.document.create_cdata(data))
257
- item.add_child(stderr)
258
- end
259
-
260
- suite.add_child(item)
261
- end
262
- suites.add_child(suite)
263
- end
264
- rescue Exception => e
265
- @logger.error "failure in XML output:\n#{e.to_s}\n" + e.backtrace.join("\n")
266
- end
267
-
268
- end
269
- end
270
-
271
12
  attr_reader :name, :options, :fail_mode
272
13
 
273
14
  #Create {TestSuite} instance