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.
@@ -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