stopdropandrew_ci_reporter 1.7.0.1

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