stopdropandrew_ci_reporter 1.7.0.1

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,224 @@
1
+ # Copyright (c) 2012 Alexander Shcherbinin <alexander.shcherbinin@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ require 'ci/reporter/core'
6
+
7
+ require 'minitest/unit'
8
+
9
+ module CI
10
+ module Reporter
11
+ class Failure
12
+ def self.new(fault, type = nil, meth = nil)
13
+ return MiniTestSkipped.new(fault) if type == :skip
14
+ return MiniTestFailure.new(fault, meth) if type == :failure
15
+ MiniTestError.new(fault)
16
+ end
17
+ end
18
+
19
+ class FailureCore
20
+ def location(e)
21
+ last_before_assertion = ""
22
+ e.backtrace.reverse_each do |s|
23
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
24
+ last_before_assertion = s
25
+ end
26
+ last_before_assertion.sub(/:in .*$/, '')
27
+ end
28
+ end
29
+
30
+ class MiniTestSkipped < FailureCore
31
+ def initialize(fault) @fault = fault end
32
+ def failure?() false end
33
+ def error?() false end
34
+ def name() @fault.class.name end
35
+ def message() @fault.message end
36
+ def location() super @fault end
37
+ end
38
+
39
+ class MiniTestFailure < FailureCore
40
+ def initialize(fault, meth) @fault = fault; @meth = meth end
41
+ def failure?() true end
42
+ def error?() false end
43
+ def name() @meth end
44
+ def message() @fault.message end
45
+ def location() super @fault end
46
+ end
47
+
48
+ class MiniTestError < FailureCore
49
+ def initialize(fault) @fault = fault end
50
+ def failure?() false end
51
+ def error?() true end
52
+ def name() @fault.exception.class.name end
53
+ def message() @fault.exception.message end
54
+ def location() @fault.exception.backtrace.join("\n") end
55
+ end
56
+
57
+ class Runner < MiniTest::Unit
58
+
59
+ @@out = $stdout
60
+
61
+ def initialize
62
+ super
63
+ @report_manager = ReportManager.new("test")
64
+ end
65
+
66
+ def _run_anything(type)
67
+ suites = MiniTest::Unit::TestCase.send "#{type}_suites"
68
+ return if suites.empty?
69
+
70
+ started_anything type
71
+
72
+ sync = output.respond_to? :"sync=" # stupid emacs
73
+ old_sync, output.sync = output.sync, true if sync
74
+
75
+ _run_suites(suites, type)
76
+
77
+ output.sync = old_sync if sync
78
+
79
+ finished_anything(type)
80
+ end
81
+
82
+ def _run_suites(suites, type)
83
+ suites.map { |suite| _run_suite suite, type }
84
+ end
85
+
86
+ def _run_suite(suite, type)
87
+ start_suite(suite)
88
+
89
+ header = "#{type}_suite_header"
90
+ puts send(header, suite) if respond_to? header
91
+
92
+ filter_suite_methods(suite, type).each do |method|
93
+ _run_test(suite, method)
94
+ end
95
+
96
+ finish_suite
97
+ end
98
+
99
+ def _run_test(suite, method)
100
+ start_case(method)
101
+
102
+ result = run_test(suite, method)
103
+
104
+ @assertion_count += result._assertions
105
+ @test_count += 1
106
+
107
+ finish_case
108
+ end
109
+
110
+ def puke(klass, meth, e)
111
+ e = case e
112
+ when MiniTest::Skip then
113
+ @skips += 1
114
+ fault(e, :skip)
115
+ return "S" unless @verbose
116
+ "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
117
+ when MiniTest::Assertion then
118
+ @failures += 1
119
+ fault(e, :failure, meth)
120
+ "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
121
+ else
122
+ @errors += 1
123
+ fault(e, :error)
124
+ bt = MiniTest::filter_backtrace(e.backtrace).join "\n "
125
+ "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n"
126
+ end
127
+ @report << e
128
+ e[0, 1]
129
+ end
130
+
131
+ private
132
+
133
+ def started_anything(type)
134
+ @test_count = 0
135
+ @assertion_count = 0
136
+ @last_assertion_count = 0
137
+ @result_assertion_count = 0
138
+ @start = Time.now
139
+
140
+ puts
141
+ puts "# Running #{type}s:"
142
+ puts
143
+ end
144
+
145
+ def finished_anything(type)
146
+ t = Time.now - @start
147
+ puts
148
+ puts
149
+ puts "Finished #{type}s in %.6fs, %.4f tests/s, %.4f assertions/s." %
150
+ [t, @test_count / t, @assertion_count / t]
151
+
152
+ report.each_with_index do |msg, i|
153
+ puts "\n%3d) %s" % [i + 1, msg]
154
+ end
155
+
156
+ puts
157
+
158
+ status
159
+ end
160
+
161
+ def filter_suite_methods(suite, type)
162
+ filter = options[:filter] || '/./'
163
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
164
+
165
+ suite.send("#{type}_methods").grep(filter)
166
+ end
167
+
168
+ def run_test(suite, method)
169
+ inst = suite.new method
170
+ inst._assertions = 0
171
+
172
+ print "#{suite}##{method} = " if @verbose
173
+
174
+ @start_time = Time.now
175
+ result = inst.run self
176
+ time = Time.now - @start_time
177
+
178
+ print "%.2f s = " % time if @verbose
179
+ print result
180
+ puts if @verbose
181
+
182
+ return inst
183
+ end
184
+
185
+ def start_suite(suite_name)
186
+ @current_suite = CI::Reporter::TestSuite.new(suite_name)
187
+ @current_suite.start
188
+ end
189
+
190
+ def finish_suite
191
+ if @current_suite
192
+ @current_suite.finish
193
+ @current_suite.assertions = @assertion_count - @last_assertion_count
194
+ @last_assertion_count = @assertion_count
195
+ @report_manager.write_report(@current_suite)
196
+ end
197
+ end
198
+
199
+ def start_case(test_name)
200
+ tc = CI::Reporter::TestCase.new(test_name)
201
+ tc.start
202
+ @current_suite.testcases << tc
203
+ end
204
+
205
+ def finish_case
206
+ tc = @current_suite.testcases.last
207
+ tc.finish
208
+ tc.assertions = @assertion_count - @result_assertion_count
209
+ @result_assertion_count = @assertion_count
210
+ end
211
+
212
+ def fault(fault, type = nil, meth = nil)
213
+ tc = @current_suite.testcases.last
214
+ if :skip == type
215
+ tc.skipped = true
216
+ else
217
+ tc.failures << Failure.new(fault, type, meth)
218
+ end
219
+ end
220
+
221
+ end
222
+
223
+ end
224
+ end
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ require File.expand_path('../utils', __FILE__)
6
+
7
+ namespace :ci do
8
+ namespace :setup do
9
+ task :cucumber_report_cleanup do
10
+ rm_rf ENV["CI_REPORTS"] || "features/reports"
11
+ end
12
+
13
+ task :cucumber => :cucumber_report_cleanup do
14
+ cuke_opts = ["--require", CI::Reporter.maybe_quote_filename("#{File.dirname(__FILE__)}/cucumber_loader.rb"),
15
+ "--format", "CI::Reporter::Cucumber"].join(" ")
16
+ ENV["CUCUMBER_OPTS"] = "#{ENV['CUCUMBER_OPTS']} #{cuke_opts}"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ $: << File.dirname(__FILE__) + "/../../.."
6
+ require 'ci/reporter/cucumber'
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2012 Alexander Shcherbinin <alexander.shcherbinin@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ require File.expand_path('../utils', __FILE__)
6
+
7
+ namespace :ci do
8
+ namespace :setup do
9
+ task :minitest do
10
+ rm_rf ENV["CI_REPORTS"] || "test/reports"
11
+ test_loader = CI::Reporter.maybe_quote_filename "#{File.dirname(__FILE__)}/minitest_loader.rb"
12
+ ENV["TESTOPTS"] = "#{ENV["TESTOPTS"]} #{test_loader}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2012 Alexander Shcherbinin <alexander.shcherbinin@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ $: << File.dirname(__FILE__) + "/../../.."
6
+ require 'ci/reporter/minitest'
7
+
8
+ # set defaults
9
+ MiniTest::Unit.runner = CI::Reporter::Runner.new
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ require File.expand_path('../utils', __FILE__)
6
+
7
+ namespace :ci do
8
+ namespace :setup do
9
+ task :spec_report_cleanup do
10
+ rm_rf ENV["CI_REPORTS"] || "spec/reports"
11
+ end
12
+
13
+ task :rspec => :spec_report_cleanup do
14
+ spec_opts = ["--require", CI::Reporter.maybe_quote_filename("#{File.dirname(__FILE__)}/rspec_loader.rb"),
15
+ "--format", "CI::Reporter::RSpec"].join(" ")
16
+ ENV["SPEC_OPTS"] = "#{ENV['SPEC_OPTS']} #{spec_opts}"
17
+ end
18
+
19
+ task :rspecdoc => :spec_report_cleanup do
20
+ spec_opts = ["--require", CI::Reporter.maybe_quote_filename("#{File.dirname(__FILE__)}/rspec_loader.rb"),
21
+ "--format", "CI::Reporter::RSpecDoc"].join(" ")
22
+ ENV["SPEC_OPTS"] = "#{ENV['SPEC_OPTS']} #{spec_opts}"
23
+ end
24
+
25
+ task :rspecbase => :spec_report_cleanup do
26
+ spec_opts = ["--require", CI::Reporter.maybe_quote_filename("#{File.dirname(__FILE__)}/rspec_loader.rb"),
27
+ "--format", "CI::Reporter::RSpecBase"].join(" ")
28
+ ENV["SPEC_OPTS"] = "#{ENV['SPEC_OPTS']} #{spec_opts}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ $: << File.dirname(__FILE__) + "/../../.."
6
+ require 'ci/reporter/rspec'
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ require File.expand_path('../utils', __FILE__)
6
+
7
+ namespace :ci do
8
+ namespace :setup do
9
+ task :testunit do
10
+ rm_rf ENV["CI_REPORTS"] || "test/reports"
11
+ test_loader = CI::Reporter.maybe_quote_filename "#{File.dirname(__FILE__)}/test_unit_loader.rb"
12
+ ENV["TESTOPTS"] = "#{ENV["TESTOPTS"]} #{test_loader}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ $: << File.dirname(__FILE__) + "/../../.."
6
+ require 'ci/reporter/test_unit'
7
+
8
+ # Intercepts mediator creation in ruby-test < 2.1
9
+ module Test #:nodoc:all
10
+ module Unit
11
+ module UI
12
+ module Console
13
+ class TestRunner
14
+ def create_mediator(suite)
15
+ # swap in our custom mediator
16
+ return CI::Reporter::TestUnit.new(suite)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # Intercepts mediator creation in ruby-test >= 2.1
25
+ module Test #:nodoc:all
26
+ module Unit
27
+ module UI
28
+ class TestRunner
29
+ def setup_mediator
30
+ # swap in our custom mediator
31
+ @mediator = CI::Reporter::TestUnit.new(@suite)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,14 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ module CI
6
+ module Reporter
7
+ def self.maybe_quote_filename(fn)
8
+ if fn =~ /\s/
9
+ fn = %{"#{fn}"}
10
+ end
11
+ fn
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
2
+ # See the file LICENSE.txt included with the distribution for
3
+ # software license details.
4
+
5
+ require 'fileutils'
6
+
7
+ module CI #:nodoc:
8
+ module Reporter #:nodoc:
9
+ class ReportManager
10
+ def initialize(prefix)
11
+ @basedir = ENV['CI_REPORTS'] || File.expand_path("#{Dir.getwd}/#{prefix.downcase}/reports")
12
+ @basename = "#{@basedir}/#{prefix.upcase}"
13
+ FileUtils.mkdir_p(@basedir)
14
+ end
15
+
16
+ def write_report(suite)
17
+ File.open(filename_for(suite), "w") do |f|
18
+ f << suite.to_xml
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+
25
+ # creates a uniqe filename per suite
26
+ # to prevent results from being overwritten
27
+ # if a result file is already written, it appends an index
28
+ # e.g.
29
+ # SPEC-MailsController.xml
30
+ # SPEC-MailsController.0.xml
31
+ # SPEC-MailsController.1.xml
32
+ # SPEC-MailsController...xml
33
+ # SPEC-MailsController.N.xml
34
+ #
35
+ # with N < 100000, to prevent endless sidestep loops
36
+ MAX_SIDESTEPS = 100000
37
+ MAX_FILENAME_SIZE = 240
38
+ #
39
+ def filename_for(suite)
40
+ basename = "#{@basename}-#{suite.name.gsub(/[^a-zA-Z0-9]+/, '-')}"
41
+ suffix = "xml"
42
+
43
+ # shorten basename if it exceeds 240 characters
44
+ # most filesystems have a 255 character limit
45
+ # so leave some room for the sidesteps
46
+ basename = basename[0..MAX_FILENAME_SIZE] if basename.length > MAX_FILENAME_SIZE
47
+
48
+ # the initial filename, e.g. SPEC-MailsController.xml
49
+ filename = [basename, suffix].join(".")
50
+
51
+ # if the initial filename is already in use
52
+ # do sidesteps, beginning with SPEC-MailsController.0.xml
53
+ i = 0
54
+ while File.exists?(filename) && i < MAX_SIDESTEPS
55
+ filename = [basename, i, suffix].join(".")
56
+ i += 1
57
+ end
58
+
59
+ filename
60
+ end
61
+ end
62
+ end
63
+ end