right_develop 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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