beaker 3.22.0 → 3.23.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 +3 -0
- data/beaker.gemspec +5 -8
- data/docs/how_to/debug_beaker_tests.md +404 -0
- data/docs/how_to/hypervisors/README.md +21 -4
- data/docs/tutorials/creating_a_test_environment.md +1 -10
- data/lib/beaker.rb +1 -1
- data/lib/beaker/dsl/structure.rb +11 -2
- data/lib/beaker/host/unix/pkg.rb +1 -1
- data/lib/beaker/logger_junit.rb +21 -21
- data/lib/beaker/options/command_line_parser.rb +6 -0
- data/lib/beaker/subcommand.rb +1 -0
- data/lib/beaker/test_suite.rb +1 -260
- data/lib/beaker/test_suite_result.rb +256 -0
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/logger_junit_spec.rb +3 -5
- data/spec/beaker/test_suite_spec.rb +20 -24
- metadata +44 -29
- data/docs/how_to/access_the_live_test_console_with_pry.md +0 -305
@@ -32,18 +32,23 @@ that are needed for it. An example `.fog` file is below:
|
|
32
32
|
|
33
33
|
# External Hypervisors
|
34
34
|
|
35
|
-
|
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
|
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
|
-
|
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) ##
|
data/lib/beaker.rb
CHANGED
@@ -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
|
data/lib/beaker/dsl/structure.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/beaker/host/unix/pkg.rb
CHANGED
@@ -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])/
|
data/lib/beaker/logger_junit.rb
CHANGED
@@ -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::
|
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 [
|
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
|
-
|
44
|
-
File.open(xml_file, 'w') { |
|
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 [
|
54
|
-
# @return [
|
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 [
|
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 [
|
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 =
|
86
|
+
suites = REXML::XPath.first(doc, "testsuites")
|
86
87
|
#remove old data
|
87
|
-
|
88
|
-
if
|
89
|
-
|
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
|
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 [
|
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 =
|
108
|
+
doc = REXML::Document.new File.open(filename)
|
109
109
|
else
|
110
110
|
#no existing file, create a new one
|
111
|
-
doc =
|
112
|
-
doc.encoding
|
113
|
-
|
114
|
-
|
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|
|
data/lib/beaker/subcommand.rb
CHANGED
@@ -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.
|
data/lib/beaker/test_suite.rb
CHANGED
@@ -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
|