right_develop 1.1.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.
- data/.rspec +4 -0
- data/CHANGELOG.rdoc +3 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +92 -0
- data/LICENSE +20 -0
- data/README.rdoc +50 -0
- data/Rakefile +67 -0
- data/VERSION +1 -0
- data/features/cucumber.feature +27 -0
- data/features/rake_integration.feature +27 -0
- data/features/rspec1.feature +67 -0
- data/features/rspec2.feature +67 -0
- data/features/step_definitions/http_client_steps.rb +27 -0
- data/features/step_definitions/request_balancer_steps.rb +93 -0
- data/features/step_definitions/ruby_steps.rb +206 -0
- data/features/step_definitions/serialization_steps.rb +96 -0
- data/features/step_definitions/server_steps.rb +134 -0
- data/features/support/env.rb +84 -0
- data/features/support/file_utils_bundler_mixin.rb +45 -0
- data/lib/right_develop.rb +32 -0
- data/lib/right_develop/ci.rb +40 -0
- data/lib/right_develop/ci/java_cucumber_formatter.rb +60 -0
- data/lib/right_develop/ci/java_spec_formatter.rb +191 -0
- data/lib/right_develop/ci/rake_task.rb +127 -0
- data/lib/right_develop/net.rb +60 -0
- data/lib/right_develop/parsers.rb +10 -0
- data/lib/right_develop/parsers/sax_parser.rb +139 -0
- data/lib/right_develop/parsers/xml_post_parser.rb +113 -0
- data/right_develop.gemspec +140 -0
- data/right_develop.rconf +8 -0
- data/spec/right_develop/parsers/sax_parser_spec.rb +202 -0
- data/spec/spec_helper.rb +28 -0
- metadata +593 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright: Copyright (c) 2010- RightScale, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require 'tmpdir'
|
25
|
+
|
26
|
+
require 'rubygems'
|
27
|
+
require 'bundler/setup'
|
28
|
+
|
29
|
+
require 'right_develop'
|
30
|
+
|
31
|
+
module RubyAppHelper
|
32
|
+
def ruby_app_root
|
33
|
+
@ruby_app_root ||= Dir.mktmpdir('right_develop_cucumber_ruby')
|
34
|
+
end
|
35
|
+
|
36
|
+
def ruby_app_path(*args)
|
37
|
+
path = ruby_app_root
|
38
|
+
until args.empty?
|
39
|
+
item = args.shift
|
40
|
+
path = File.join(path, item)
|
41
|
+
end
|
42
|
+
path
|
43
|
+
end
|
44
|
+
|
45
|
+
# Run a shell command in app_dir, e.g. a rake task
|
46
|
+
def ruby_app_shell(cmd, options={})
|
47
|
+
ignore_errors = options[:ignore_errors] || false
|
48
|
+
log = !!(Cucumber.logger)
|
49
|
+
|
50
|
+
all_output = ''
|
51
|
+
Dir.chdir(ruby_app_root) do
|
52
|
+
Cucumber.logger.debug("bash> #{cmd}\n") if log
|
53
|
+
Bundler.with_clean_env do
|
54
|
+
IO.popen("#{cmd} 2>&1", 'r') do |output|
|
55
|
+
output.sync = true
|
56
|
+
done = false
|
57
|
+
until done
|
58
|
+
begin
|
59
|
+
line = output.readline + "\n"
|
60
|
+
all_output << line
|
61
|
+
Cucumber.logger.debug(line) if log
|
62
|
+
rescue EOFError
|
63
|
+
done = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
$?.success?.should(be_true) unless ignore_errors
|
71
|
+
all_output
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
module RightDevelopWorld
|
76
|
+
include RubyAppHelper
|
77
|
+
end
|
78
|
+
|
79
|
+
# The Cucumber world
|
80
|
+
World(RightDevelopWorld)
|
81
|
+
|
82
|
+
After do
|
83
|
+
FileUtils.rm_rf(ruby_app_root) if File.directory?(ruby_app_root)
|
84
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Copyright (c) 2012- RightScale Inc
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
# Magic hooks that is necessary due to Bundler/RVM craziness interfering with
|
23
|
+
# our own Cucumbers. This is necessary because our Cucumber scenarios need to create a
|
24
|
+
# Ruby app that has a distinct, separate bundle from right_develop's own Gemfile, e.g. we
|
25
|
+
# need to test what happens when RSpec or Cucumber isn't available. Therefore the subprocesses
|
26
|
+
# that RightDevelop's Cucumber suite launches, should not inherit our bundle.
|
27
|
+
module FileUtilsBundlerMixin
|
28
|
+
def self.included(base)
|
29
|
+
if base.respond_to?(:sh) && !base.respond_to?(:sh_without_bundler_taint)
|
30
|
+
base.instance_eval {
|
31
|
+
alias_method :sh_without_bundler_taint, :sh
|
32
|
+
alias_method :sh, :sh_with_bundler_taint
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def sh_with_bundler_taint(*params)
|
38
|
+
Bundler.with_clean_env do
|
39
|
+
sh_without_bundler_taint(*params)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Install the magic hook.
|
45
|
+
Kernel.instance_eval { include(::FileUtilsBundlerMixin) }
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'right_support'
|
24
|
+
|
25
|
+
# Autoload everything possible
|
26
|
+
module RightDevelop
|
27
|
+
autoload :CI, 'right_develop/ci'
|
28
|
+
autoload :Parsers, 'right_develop/parsers'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Automatically include RightSupport networking extensions
|
32
|
+
require 'right_develop/net'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
# Ensure the main gem is required, since this module might be loaded using ruby -r
|
24
|
+
require 'right_develop'
|
25
|
+
|
26
|
+
module RightDevelop
|
27
|
+
module CI
|
28
|
+
# Defer loading the Rake task; it mixes the Rake DSL into everything!
|
29
|
+
# Only the Rakefiles themselves should refer to this constant.
|
30
|
+
autoload :RakeTask, 'right_develop/ci/rake_task'
|
31
|
+
|
32
|
+
# Cucumber does not support a -r hook, but it does let you specify class names. Autoload
|
33
|
+
# to the rescue!
|
34
|
+
autoload :JavaCucumber, 'right_develop/ci/java_cucumber_formatter'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Explicitly require everything else to avoid overreliance on autoload (1-module-deep rule)
|
39
|
+
require 'right_develop/ci/java_cucumber_formatter'
|
40
|
+
require 'right_develop/ci/java_spec_formatter'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
# Cucumber naïvely requires JUST this file without necessarily requiring
|
24
|
+
# RightDevelop's main file. Make up for Cucumber's shortcomings.
|
25
|
+
|
26
|
+
# Cucumber sometimes avoids loading us; not sure why!
|
27
|
+
require 'right_develop'
|
28
|
+
|
29
|
+
require 'cucumber'
|
30
|
+
require 'cucumber/formatter/junit'
|
31
|
+
|
32
|
+
module RightDevelop::CI
|
33
|
+
class JavaCucumberFormatter < Cucumber::Formatter::Junit
|
34
|
+
private
|
35
|
+
|
36
|
+
def build_testcase(duration, status, exception = nil, suffix = "")
|
37
|
+
@time += duration
|
38
|
+
# Use "cucumber" as a pseudo-package, and the feature name as a pseudo-class
|
39
|
+
classname = "cucumber.#{@feature_name}"
|
40
|
+
name = "#{@scenario}#{suffix}"
|
41
|
+
pending = [:pending, :undefined].include?(status)
|
42
|
+
passed = (status == :passed || (pending && !@options[:strict]))
|
43
|
+
|
44
|
+
@builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
|
45
|
+
unless passed
|
46
|
+
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
|
47
|
+
@builder.cdata! @output
|
48
|
+
@builder.cdata!(format_exception(exception)) if exception
|
49
|
+
end
|
50
|
+
@failures += 1
|
51
|
+
end
|
52
|
+
if passed and (status == :skipped || pending)
|
53
|
+
@builder.skipped
|
54
|
+
@skipped += 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
@tests += 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'time'
|
24
|
+
|
25
|
+
require 'builder'
|
26
|
+
|
27
|
+
# Try to load RSpec 2.x - 1.x formatters
|
28
|
+
['rspec/core/formatters', 'spec/runner/formatter/base_text_formatter'].each do |f|
|
29
|
+
begin
|
30
|
+
require f
|
31
|
+
rescue LoadError
|
32
|
+
# no-op, we will raise later
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module RightDevelop::CI
|
37
|
+
if defined?(::RSpec::Core)
|
38
|
+
# RSpec 2.x
|
39
|
+
class JavaSpecFormatter < RSpec::Core::Formatters::BaseFormatter
|
40
|
+
def initialize(*args)
|
41
|
+
super(*args)
|
42
|
+
@test_results = []
|
43
|
+
end
|
44
|
+
|
45
|
+
def example_passed(example)
|
46
|
+
@test_results << example
|
47
|
+
end
|
48
|
+
|
49
|
+
def example_failed(example)
|
50
|
+
@test_results << example
|
51
|
+
end
|
52
|
+
|
53
|
+
def example_pending(example)
|
54
|
+
@test_results << example
|
55
|
+
end
|
56
|
+
|
57
|
+
def failure_details_for(example)
|
58
|
+
exception = example.exception
|
59
|
+
exception.nil? ? "" : "#{exception.message}\n#{format_backtrace(exception.backtrace, example).join("\n")}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def classname_for(example)
|
63
|
+
klass = example.example_group.described_class || example.example_group.top_level_description
|
64
|
+
"rspec.#{klass}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
68
|
+
builder = Builder::XmlMarkup.new :indent => 2
|
69
|
+
builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
70
|
+
builder.testsuite :errors => 0, :failures => failure_count, :skipped => pending_count, :tests => example_count, :time => duration, :timestamp => Time.now.iso8601 do
|
71
|
+
builder.properties
|
72
|
+
@test_results.each do |test|
|
73
|
+
classname = classname_for(test)
|
74
|
+
full_description = test.full_description
|
75
|
+
time = test.metadata[:execution_result][:run_time]
|
76
|
+
|
77
|
+
# The full description always begins with the classname, but this is useless info when
|
78
|
+
# generating the XML report.
|
79
|
+
if full_description.start_with?(classname)
|
80
|
+
full_description = full_description[classname.length..-1].strip
|
81
|
+
end
|
82
|
+
|
83
|
+
builder.testcase(:classname => classname, :name => full_description, :time => time) do
|
84
|
+
case test.metadata[:execution_result][:status]
|
85
|
+
when "failed"
|
86
|
+
builder.failure :message => "failed #{full_description}", :type => "failed" do
|
87
|
+
builder.cdata! failure_details_for test
|
88
|
+
end
|
89
|
+
when "pending" then
|
90
|
+
builder.skipped
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
output.puts builder.target!
|
96
|
+
end
|
97
|
+
end
|
98
|
+
elsif defined?(::Spec::Runner)
|
99
|
+
# RSpec 1.x
|
100
|
+
class JavaSpecFormatter < Spec::Runner::Formatter::BaseTextFormatter
|
101
|
+
def initialize(*args)
|
102
|
+
super(*args)
|
103
|
+
@current_example_group = nil
|
104
|
+
@test_times = {}
|
105
|
+
@test_groups = {}
|
106
|
+
@test_results = {}
|
107
|
+
@test_failures = {}
|
108
|
+
end
|
109
|
+
|
110
|
+
def example_group_started(example)
|
111
|
+
@current_example_group = example
|
112
|
+
end
|
113
|
+
|
114
|
+
def example_started(example)
|
115
|
+
@test_groups[example] = @current_example_group
|
116
|
+
@example_started_at = Time.now
|
117
|
+
end
|
118
|
+
|
119
|
+
def example_passed(example)
|
120
|
+
@test_times[example] = Time.now - @example_started_at
|
121
|
+
@test_results[example] = 'passed'
|
122
|
+
end
|
123
|
+
|
124
|
+
def example_failed(example, counter, failure)
|
125
|
+
@test_times[example] = Time.now - @example_started_at
|
126
|
+
@test_results[example] = 'failed'
|
127
|
+
@test_failures[example] = failure
|
128
|
+
end
|
129
|
+
|
130
|
+
def example_pending(example, message, deprecated_pending_location=nil)
|
131
|
+
@test_times[example] = Time.now - @example_started_at
|
132
|
+
@test_results[example] = 'pending'
|
133
|
+
end
|
134
|
+
|
135
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
136
|
+
builder = Builder::XmlMarkup.new :indent => 2
|
137
|
+
builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
138
|
+
builder.testsuite :errors => 0, :failures => failure_count, :skipped => pending_count, :tests => example_count, :time => duration, :timestamp => Time.now.iso8601 do
|
139
|
+
builder.properties
|
140
|
+
@test_results.each_pair do |test, result|
|
141
|
+
classname = classname_for(test)
|
142
|
+
full_description = test.description
|
143
|
+
|
144
|
+
# The full description always begins with the classname, but this is useless info when
|
145
|
+
# generating the XML report.
|
146
|
+
if full_description.start_with?(classname)
|
147
|
+
full_description = full_description[classname.length..-1].strip
|
148
|
+
end
|
149
|
+
|
150
|
+
builder.testcase(:classname => classname, :name => full_description, :time => @test_times[test]) do
|
151
|
+
case result
|
152
|
+
when "failed"
|
153
|
+
builder.failure :message => "failed #{full_description}", :type => "failed" do
|
154
|
+
builder.cdata! failure_details_for(test)
|
155
|
+
end
|
156
|
+
when "pending" then
|
157
|
+
builder.skipped
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
output.puts builder.target!
|
163
|
+
end
|
164
|
+
|
165
|
+
def dump_failure(counter, failure)
|
166
|
+
# no-op; our summary contains everything
|
167
|
+
end
|
168
|
+
|
169
|
+
def dump_pending()
|
170
|
+
# no-op; our summary contains everything
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def failure_details_for(example)
|
176
|
+
exception = @test_failures[example].exception
|
177
|
+
exception.nil? ? "" : "#{exception.message}\n#{format_backtrace(exception.backtrace)}"
|
178
|
+
end
|
179
|
+
|
180
|
+
def classname_for(example)
|
181
|
+
# Take our best guess, by looking at the description of the example group
|
182
|
+
# and assuming the first word is a class name
|
183
|
+
group = @test_groups[example]
|
184
|
+
klass = group.description.split(/\s+/).first
|
185
|
+
"rspec.#{klass}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
else
|
189
|
+
raise LoadError, "Cannot define RightDevelop::CI::JavaSpecFormatter: unsupported RSpec version"
|
190
|
+
end
|
191
|
+
end
|