reportTestUnit 1.0.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/README ADDED
@@ -0,0 +1,112 @@
1
+ == ReportTestUnit
2
+
3
+ Version 1.0.0 - 2007-09-14
4
+
5
+
6
+ ReportTestUnit is an add on to the Test::Unit package. It leverage's the full support
7
+ of Test:Unit to write out html based reports of each test case. ReportTestUnit is
8
+ designed to work with cruisecontrol.rb - but not limited to it.
9
+
10
+
11
+ === Installation
12
+
13
+ Installed as a gem:
14
+ gem install reportTestUnit-x.y.z.gem (where x.y.z is the revision number)
15
+ or directly from rubyforge.net
16
+ gem install reportTestUnit
17
+
18
+ === Dependencies
19
+
20
+ ReportTestUnit is built on top of Test::Unit which is part of the core package of ruby 1.8
21
+
22
+
23
+ === Usage
24
+
25
+ ReportTestUnit subclasses the Test::Unit package, as such it is used similarly to
26
+ Test::Unit (Please see the Test::Unit rdoc for information on how to use Test::Unit).
27
+
28
+ A test suite might look like the following:
29
+
30
+ ts_test.rb
31
+
32
+ require 'reportUnitTest'
33
+ require 'test_cases/tc_test1.rb'
34
+
35
+ class TS_MyTests
36
+ def self.suite
37
+ suite = Test::Unit::TestSuite.new
38
+ suite << TestTc_test.suite
39
+ return suite
40
+ end
41
+ end
42
+ Report::TestUnit::UI::Report::TestRunner.run(TS_MyTests, 3) # 3 is verbose
43
+
44
+ And a test case might look like:
45
+
46
+ test_cases/tc_test1.rb
47
+
48
+ require 'test/unit'
49
+
50
+ # test class is written exactly the same as for Test::Unit only its subclasses Report::TestUnit::TestCase
51
+ # instead of Test::Unit::TestCase (Report::TestUnit::TestCase is a subclass of Test::Unit:TestCase
52
+
53
+ class TestTc_test < Report::TestUnit::TestCase
54
+ def setup
55
+ # override default settings if needed
56
+ end
57
+
58
+ def teardown
59
+ # override default settings if needed
60
+ end
61
+
62
+ def test_get_user_id
63
+ assert_equal(100, 99+1) # (test cases written exactly the same as for Test::Unit
64
+ end
65
+ end
66
+
67
+ The html report will be dropped in a directory specified by the ENV var UNIT_TEST_REPORT_DIR under this directory an index.html file will be created along with a classes directory populated with html files for each test_case class.
68
+ To integrate with CruiseControl.rb add the following line to your rakefile:
69
+ ENV['UNIT_TEST_REPORT_DIR']="#{ENV['CC_BUILD_ARTIFACTS']}/unitTestReport"
70
+
71
+
72
+ === Acknowledgements
73
+
74
+ As this package is built on Test::Unit all the credit must go to those guys for
75
+ providing excellent opertunities to plug in extra functionality.
76
+
77
+ === License
78
+
79
+
80
+
81
+ This program is free software; you can redistribute it and/or
82
+
83
+ modify it under the terms of the GNU General Public License
84
+
85
+ as published by the Free Software Foundation; either version 2
86
+
87
+ of the License, or (at your option) any later version.
88
+
89
+
90
+
91
+ This program is distributed in the hope that it will be useful,
92
+
93
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
94
+
95
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96
+
97
+ GNU General Public License for more details.
98
+
99
+
100
+
101
+ You should have received a copy of the GNU General Public License
102
+
103
+ along with this program; if not, write to the Free Software
104
+
105
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
106
+
107
+
108
+
109
+
110
+
111
+
112
+
@@ -0,0 +1,21 @@
1
+ require 'test/unit/util/backtracefilter'
2
+
3
+ module Report
4
+ module TestUnit
5
+ class Error < Test::Unit::Error
6
+
7
+ def initialize(test_name, exception)
8
+ super(test_name, exception)
9
+ end
10
+
11
+ # Returns the first line of the backtrace
12
+ # (the line that caises the exception)
13
+ def location_disp
14
+ location=filter_backtrace(@exception.backtrace)
15
+ location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
16
+ "#{location_display}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,22 @@
1
+ module Report
2
+ module TestUnit
3
+ # Encapsulates a test failure. Created by Test::Unit::TestCase
4
+ # when an assertion fails.
5
+ class Failure < Test::Unit::Failure
6
+ def initialize(test_name, location, message)
7
+ super(test_name, location, message)
8
+ end
9
+ # Returns the first line of the backtrace
10
+ # (the line that caises the exception)
11
+ def location_disp
12
+ if "#{location.class}" == "NilClass"
13
+ "No backtrace"
14
+ else
15
+ location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
16
+ "#{location_display}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,53 @@
1
+ #--
2
+ #
3
+ # Author:: Nathaniel Talbott.
4
+ # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
5
+ # License:: Ruby license.
6
+
7
+ require 'test/unit/util/backtracefilter'
8
+
9
+ module Report
10
+ module TestUnit
11
+
12
+ # Encapsulates a success in a test. Created by
13
+ # Report::TestUnit::TestCase when no exceptions were thrown
14
+ # during the processing of a test.
15
+ class Success
16
+
17
+ attr_reader(:test_name, :exception)
18
+
19
+ SINGLE_CHARACTER = 'S'
20
+
21
+ # Creates a new Success with the given test_name and
22
+ def initialize(test_name)
23
+ @test_name = test_name
24
+ end
25
+
26
+ # Returns a single character representation of the status (S).
27
+ def single_character_display
28
+ SINGLE_CHARACTER
29
+ end
30
+
31
+ # Returns the message "Successfully passed".
32
+ def message
33
+ "Successfully passed"
34
+ end
35
+
36
+ # Returns a brief message "test_name: Success"
37
+ def short_display
38
+ "#@test_name: SUCCESS"
39
+ end
40
+
41
+ # Returns a verbose version a success text "Success:
42
+ # test_name: Successfully passed"
43
+ def long_display
44
+ "SUCCESS:\n#@test_name: #{message}"
45
+ end
46
+
47
+ # Overridden to return long_display.
48
+ def to_s
49
+ long_display
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,70 @@
1
+ module Report
2
+ module TestUnit
3
+
4
+ # This is a direct subclass of Test::Unit::TestCase, so everthing
5
+ # you can do with Test::Unit::TestCase you can do here along with
6
+ # getting notified of a successfully passed test.
7
+ # Please see the rdoc for Test::Unit::TestCase for more information.
8
+ class TestCase < Test::Unit::TestCase
9
+ include Test::Unit::Assertions
10
+ include Test::Unit::Util::BacktraceFilter
11
+
12
+ def initialize(test_method_name)
13
+ super(test_method_name)
14
+ end
15
+
16
+ # Runs the individual test method represented by this instance of the
17
+ # fixture, collecting statistics, failures and errors in result.
18
+ def run(result)
19
+ yield(STARTED, name)
20
+ @_result = result
21
+ test_success=true
22
+ begin
23
+ setup
24
+ __send__(@method_name)
25
+ rescue Test::Unit::AssertionFailedError => e
26
+ test_success=false
27
+ add_failure(e.message, e.backtrace)
28
+ rescue Exception
29
+ test_success=false
30
+ raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
31
+ add_error($!)
32
+ ensure
33
+ begin
34
+ teardown
35
+ rescue Test::Unit::AssertionFailedError => e
36
+ add_failure(e.message, e.backtrace)
37
+ rescue Exception
38
+ raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
39
+ add_error($!)
40
+ end
41
+ end
42
+ if test_success
43
+ add_success()
44
+ else
45
+ test_success=true
46
+ end
47
+ result.add_run
48
+ yield(FINISHED, name)
49
+ end
50
+ def add_success()
51
+ @_result.add_success(Success.new(name))
52
+ end
53
+ private :add_success
54
+
55
+ def add_error(exception)
56
+ @test_passed = false
57
+ @_result.add_error(Report::TestUnit::Error.new(name, exception))
58
+ end
59
+ private :add_error
60
+
61
+ def add_failure(message, all_locations=caller())
62
+ @test_passed = false
63
+ @_result.add_failure(Report::TestUnit::Failure.new(name, filter_backtrace(all_locations), message))
64
+ end
65
+ private :add_failure
66
+
67
+ end
68
+ end
69
+ end
70
+
@@ -0,0 +1,27 @@
1
+ require 'test/unit/util/observable'
2
+ require 'test/unit/testresult'
3
+ module Report
4
+ module TestUnit
5
+
6
+ # Collects Report::TestUnit::Failure, Report::TestUnit::Error
7
+ # and Report::TestUnit::Success so that they can be displayed
8
+ # to the user. To this end, observers can be added to it,
9
+ # allowing the dynamic updating of, say, a UI.
10
+ class TestResult < Test::Unit::TestResult
11
+
12
+ SUCCESS = "SUCCESS"
13
+ # Constructs a new, empty TestResult.
14
+ def initialize
15
+ super
16
+ @success = Array.new
17
+ end
18
+
19
+ # Records a Report::TestUnit::Success.
20
+ def add_success(success)
21
+ @success << success
22
+ notify_listeners(SUCCESS, success)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,358 @@
1
+ require 'test/unit/ui/testrunnermediator'
2
+ require 'test/unit/ui/testrunnerutilities'
3
+
4
+ module Report
5
+ module TestUnit
6
+ module UI
7
+ module Report
8
+
9
+ # Runs a Test::Unit::TestSuite on the console.
10
+ class TestRunner
11
+ extend Test::Unit::UI::TestRunnerUtilities
12
+ # because we're using a different namespace - re-declare these here
13
+ SILENT = 0
14
+ PROGRESS_ONLY = 1
15
+ NORMAL = 2
16
+ VERBOSE = 3
17
+
18
+ # Creates a new TestRunner for running the passed
19
+ # suite. If quiet_mode is true, the output while
20
+ # running is limited to progress dots, errors and
21
+ # failures, and the final result. io specifies
22
+ # where runner output should go to; defaults to
23
+ # STDOUT.
24
+ # The html report will be dropped in a directory
25
+ # specified by the ENV var UNIT_TEST_REPORT_DIR
26
+ # under this directory an index.html file will be
27
+ # created along with a classes directory populated
28
+ # with html files for each test_case class.
29
+ def initialize(suite, output_level=NORMAL, io=STDOUT)
30
+ @coverage_report_dir_stub=ENV['UNIT_TEST_REPORT_DIR'] || "/tmp"
31
+ if (suite.respond_to?(:suite))
32
+ @suite = suite.suite
33
+ else
34
+ @suite = suite
35
+ end
36
+ @output_level = output_level
37
+ @io = io
38
+ @reportio=File.open("#{@coverage_report_dir_stub}/index.html", "w")
39
+ @already_outputted = false
40
+ @faults = []
41
+ @classHash=Hash.new
42
+ end
43
+
44
+ def setup_html_page
45
+ html_text = <<-EOT
46
+ <HTML>
47
+ <HEAD>
48
+ <TITLE>Unit test results</TITLE>
49
+ <STYLE TYPE="text/css">
50
+ <!--
51
+ @page { size: 8.5in 11in; margin: 0.79in }
52
+ P { margin-bottom: 0.08in }
53
+ TD P { margin-bottom: 0in }
54
+ -->
55
+ </STYLE>
56
+ </HEAD>
57
+ <BODY LANG="en-GB" DIR="LTR">
58
+ <P><BR><h2>Unit test results for date #{Time.now}</h2><BR></P>
59
+ <TABLE WIDTH=100% BORDER=1 BORDERCOLOR="#000000" CELLPADDING=4 CELLSPACING=0>
60
+ <COL WIDTH=80*>
61
+ <COL WIDTH=78*>
62
+ <COL WIDTH=49*>
63
+ <COL WIDTH=48*>
64
+ <TR VALIGN=TOP>
65
+ <TD WIDTH=60%>
66
+ <P ALIGN=CENTER>CLASS NAME</P>
67
+ </TD>
68
+ <TD WIDTH=10%>
69
+ <P ALIGN=CENTER>Tests</P>
70
+ </TD>
71
+ <TD WIDTH=10%>
72
+ <P ALIGN=CENTER>Errors</P>
73
+ </TD>
74
+ <TD WIDTH=10%>
75
+ <P ALIGN=CENTER>Failures</P>
76
+ </TD>
77
+ <TD WIDTH=10%>
78
+ <P ALIGN=CENTER>Success</P>
79
+ </TD>
80
+ </TR>
81
+ EOT
82
+ output_report(@reportio, html_text)
83
+ end
84
+
85
+ def setup_class_page(class_name)
86
+ if @classHash[class_name]["fh"] == nil
87
+ if !(Dir.entries(@coverage_report_dir_stub).include?("classes"))
88
+ Dir.mkdir("#{@coverage_report_dir_stub}/classes")
89
+ end
90
+ @classHash[class_name]["fh"]=File.open("#{@coverage_report_dir_stub}/classes/#{class_name}.html", "w")
91
+ end
92
+ html_text = <<-EOT
93
+ <HTML>
94
+ <HEAD>
95
+ <TITLE>Unit test results</TITLE>
96
+ <STYLE TYPE="text/css">
97
+ <!--
98
+ @page { size: 8.5in 11in; margin: 0.79in }
99
+ P { margin-bottom: 0.08in }
100
+ TD P { margin-bottom: 0in }
101
+ -->
102
+ </STYLE>
103
+ </HEAD>
104
+ <BODY LANG="en-GB" DIR="LTR">
105
+ <P><BR><h2>Unit test results for date #{Time.now}</h2><BR></P>
106
+ <P><h3>Class: #{class_name}</h3></P>
107
+ <TABLE WIDTH=100% BORDER=1 BORDERCOLOR="#000000" CELLPADDING=4 CELLSPACING=0>
108
+ <COL WIDTH=80*>
109
+ <COL WIDTH=78*>
110
+ <COL WIDTH=49*>
111
+ <COL WIDTH=48*>
112
+ <TR VALIGN=TOP>
113
+ <TD WIDTH=21%>
114
+ <P ALIGN=CENTER>METHOD NAME</P>
115
+ </TD>
116
+ <TD WIDTH=5%>
117
+ <P ALIGN=CENTER>STATUS</P>
118
+ </TD>
119
+ <TD WIDTH=23%>
120
+ <P ALIGN=CENTER>FAULT LOCATION</P>
121
+ </TD>
122
+ <TD WIDTH=51%>
123
+ <P ALIGN=CENTER>FAULT MESSAGE</P>
124
+ </TD>
125
+ </TR>
126
+ EOT
127
+ output_report(@classHash[class_name]["fh"], html_text)
128
+ end
129
+
130
+ def close_class_page(class_name)
131
+ html_text = <<-EOT
132
+ </TABLE>
133
+ <P STYLE="margin-bottom: 0in"><BR>
134
+ </P>
135
+ </BODY>
136
+ </HTML>
137
+ EOT
138
+ output_report(@classHash[class_name]["fh"], html_text)
139
+ end
140
+
141
+ def finish_html
142
+ html_text = <<-EOT
143
+ <P STYLE="margin-bottom: 0in"><BR>
144
+ </P>
145
+ </BODY>
146
+ </HTML>
147
+ EOT
148
+ output_report(@reportio, html_text)
149
+ end
150
+
151
+ # Begins the test run.
152
+ def start
153
+ setup_mediator
154
+ attach_to_mediator
155
+ return start_mediator
156
+ end
157
+
158
+ private
159
+ def setup_mediator
160
+ @mediator = create_mediator(@suite)
161
+ suite_name = @suite.to_s
162
+ if ( @suite.kind_of?(Module) )
163
+ suite_name = @suite.name
164
+ end
165
+ output("Loaded suite #{suite_name}")
166
+ end
167
+
168
+ def create_mediator(suite)
169
+ return UI::TestRunnerMediator.new(suite)
170
+ end
171
+
172
+ def attach_to_mediator
173
+ @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
174
+ @mediator.add_listener(TestResult::SUCCESS, &method(:add_success))
175
+ @mediator.add_listener(UI::TestRunnerMediator::STARTED, &method(:started))
176
+ @mediator.add_listener(UI::TestRunnerMediator::FINISHED, &method(:finished))
177
+ @mediator.add_listener(TestCase::STARTED, &method(:test_started))
178
+ @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
179
+ end
180
+
181
+
182
+ def add_success(result)
183
+ format_table(result.test_name, "Success", ".", ".")
184
+ end
185
+
186
+ def start_mediator
187
+ return @mediator.run_suite
188
+ end
189
+
190
+ def format_table(name, status, location, message)
191
+ names=name.split("\(")
192
+ method_name=names[0]
193
+ class_name=names[1].chop
194
+ case status
195
+ when "Success"
196
+ colour="#000000"
197
+ when "Failure"
198
+ colour="#ff3366"
199
+ when "Error"
200
+ colour="#ff3366"
201
+ end
202
+ html_text = <<-EOT
203
+ <TR VALIGN=TOP>
204
+ <TD WIDTH=21%>
205
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{method_name}</FONT></P>
206
+ </TD>
207
+ <TD WIDTH=5%>
208
+ <P><FONT COLOR=\"#{colour}\">#{status}</FONT></P>
209
+ </TD>
210
+ <TD WIDTH=23%>
211
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{location}</FONT></P>
212
+ </TD>
213
+ <TD WIDTH=41%>
214
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{message}</FONT></P>
215
+ </TD>
216
+ </TR>
217
+ EOT
218
+ increment_stats(name, status, html_text)
219
+ end
220
+
221
+ def output_summary(fh, class_name, total, error, failures, success)
222
+ if (failures > 0 || error > 0)
223
+ colour="#ff3366"
224
+ else
225
+ colour="#000000"
226
+ end
227
+ html_text = <<-EOT
228
+ <TR VALIGN=TOP>
229
+ <TD WIDTH=60%>
230
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{class_name}</FONT></P>
231
+ </TD>
232
+ <TD WIDTH=10%>
233
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{total}</FONT></P>
234
+ </TD>
235
+ <TD WIDTH=10%>
236
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{error}</FONT></P>
237
+ </TD>
238
+ <TD WIDTH=10%>
239
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{failures}</FONT></P>
240
+ </TD>
241
+ <TD WIDTH=10%>
242
+ <P><FONT SIZE=2 COLOR=\"#{colour}\">#{success}</FONT></P>
243
+ </TD>
244
+ </TR>
245
+ EOT
246
+ output_report(fh, html_text)
247
+ end
248
+
249
+ def initialize_hash(class_name)
250
+ @classHash[class_name]={"total" => 0,
251
+ "success" => 0,
252
+ "failure" => 0,
253
+ "error" => 0,
254
+ "message" => [],
255
+ "fh" => nil
256
+ }
257
+ end
258
+ def increment_stats(name, status, text)
259
+ names=name.split("\(")
260
+ method_name=names[0]
261
+ class_name=names[1].chop
262
+ if @classHash[class_name] == nil
263
+ # first time meeting this class
264
+ initialize_hash(class_name)
265
+ end
266
+ @classHash[class_name]["total"]+=1
267
+ case status
268
+ when "Success"
269
+ @classHash[class_name]["success"]+=1
270
+ @classHash[class_name]["message"].push(text)
271
+ when "Error"
272
+ @classHash[class_name]["error"]+=1
273
+ @classHash[class_name]["message"].push(text)
274
+ when "Failure"
275
+ @classHash[class_name]["failure"]+=1
276
+ @classHash[class_name]["message"].push(text)
277
+ else
278
+ output("invalid status #{status} for #{class_name}, #{method_name}")
279
+ end
280
+ end
281
+
282
+ def add_fault(fault)
283
+ @faults << fault
284
+ if fault.single_character_display == "F"
285
+ format_table(fault.test_name, "Failure", fault.location_disp, fault.message)
286
+ elsif fault.single_character_display == "E"
287
+ format_table(fault.test_name, "Error", fault.location_disp, fault.message.gsub(/([<>])/, '_'))
288
+ end
289
+ output_single("name = #{fault.test_name}\nscd = #{fault.single_character_display}\nmessage = #{fault.message}\nlong_display = #{fault.long_display}\nshort_display = #{fault.short_display}\n", PROGRESS_ONLY)
290
+ @already_outputted = true
291
+ end
292
+
293
+ def started(result)
294
+ @result = result
295
+ output("Started")
296
+ end
297
+
298
+ def finished(elapsed_time)
299
+ nl
300
+ output("Finished in #{elapsed_time} seconds.")
301
+ @faults.each_with_index do |fault, index|
302
+ nl
303
+ output("%3d) %s" % [index + 1, fault.long_display])
304
+ end
305
+ nl
306
+ output(@result)
307
+ setup_html_page
308
+ @classHash.each do |class_name, attributes|
309
+ output_summary(@reportio, "<A HREF=\"./classes/#{class_name}.html\">#{class_name}</A>", attributes["total"], attributes["error"], attributes["failure"], attributes["success"])
310
+ setup_class_page(class_name)
311
+ attributes["message"].each do |record|
312
+ output_report(attributes["fh"], record)
313
+ end
314
+ close_class_page(class_name)
315
+ end
316
+ output_report(@reportio, "</TABLE>")
317
+ output_report(@reportio, "<p>#{@result}<\p>")
318
+ output_report(@reportio, "<p>Total time taken for all tests is #{elapsed_time}<\p>")
319
+ finish_html
320
+ end
321
+
322
+ def test_started(name)
323
+ output_single(name + ": ", VERBOSE)
324
+ end
325
+
326
+ def test_finished(name)
327
+ output_single(name + "finished.", PROGRESS_ONLY) unless (@already_outputted)
328
+ nl(VERBOSE)
329
+ @already_outputted = false
330
+ end
331
+
332
+ def nl(level=NORMAL)
333
+ output("", level)
334
+ end
335
+
336
+ def output_report(fh, something)
337
+ fh.puts(something)
338
+ fh.flush
339
+ end
340
+
341
+ def output(something, level=NORMAL)
342
+ @io.puts(something) if (output?(level))
343
+ @io.flush
344
+ end
345
+
346
+ def output_single(something, level=NORMAL)
347
+ @io.write(something) if (output?(level))
348
+ @io.flush
349
+ end
350
+
351
+ def output?(level)
352
+ level <= @output_level
353
+ end
354
+ end
355
+ end
356
+ end
357
+ end
358
+ end
@@ -0,0 +1,53 @@
1
+ require 'test/unit'
2
+ require 'test/unit/util/observable'
3
+ require 'test/unit/testresult'
4
+
5
+ module Report
6
+ module TestUnit
7
+ module UI
8
+ # Subclass of Test::Unit::UI::TestRunnerMediator
9
+ # to override the run_suite to add an extra listener for a
10
+ # SUCCESS result
11
+ class TestRunnerMediator < Test::Unit::UI::TestRunnerMediator
12
+ def initialize(suite)
13
+ super(suite)
14
+ end
15
+
16
+ def run_suite
17
+ Test::Unit.run = true
18
+ begin_time = Time.now
19
+ notify_listeners(UI::TestRunnerMediator::RESET, @suite.size)
20
+ result = create_result
21
+ notify_listeners(UI::TestRunnerMediator::STARTED, result)
22
+ result_listener = result.add_listener(TestResult::CHANGED) do |updated_result|
23
+ notify_listeners(TestResult::CHANGED, updated_result)
24
+ end
25
+
26
+ fault_listener = result.add_listener(TestResult::FAULT) do |fault|
27
+ notify_listeners(TestResult::FAULT, fault)
28
+ end
29
+
30
+ success_listener = result.add_listener(TestResult::SUCCESS) do |success|
31
+ notify_listeners(TestResult::SUCCESS, success)
32
+ end
33
+
34
+
35
+ @suite.run(result) do |channel, value|
36
+ notify_listeners(channel, value)
37
+ end
38
+
39
+ result.remove_listener(TestResult::FAULT, fault_listener)
40
+ result.remove_listener(TestResult::CHANGED, result_listener)
41
+ end_time = Time.now
42
+ elapsed_time = end_time - begin_time
43
+ notify_listeners(UI::TestRunnerMediator::FINISHED, elapsed_time) #"Finished in #{elapsed_time} seconds.")
44
+ return result
45
+ end
46
+ def create_result
47
+ return TestResult.new
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+ require 'report/testunit/ui/report/testrunner'
3
+ require 'report/testunit/testcase'
4
+ require 'report/testunit/ui/testrunnermediator'
5
+ require 'report/testunit/testresult'
6
+ require 'report/testunit/success'
7
+ require 'report/testunit/failure'
8
+ require 'report/testunit/error'
9
+
10
+
@@ -0,0 +1,27 @@
1
+ # tc_error.rb
2
+ # September 18, 2007
3
+ #
4
+
5
+
6
+ class TestTc_error < Test::Unit::TestCase
7
+
8
+ def a
9
+ raise "boom"
10
+ end
11
+
12
+ def b
13
+ a()
14
+ end
15
+
16
+ def test_location_disp
17
+ errorTest=Report::TestUnit::Error.new("TestError", Exception.new("testError"))
18
+ assert_equal("No backtrace", errorTest.location_disp())
19
+ begin
20
+ b()
21
+ rescue => detail
22
+ errorTest=Report::TestUnit::Error.new("TestError", detail)
23
+ end
24
+ assert_match(/.*\/testunit\/tc_error.rb:9\]/, errorTest.location_disp())
25
+ end
26
+
27
+ end
@@ -0,0 +1,28 @@
1
+ # tc_error.rb
2
+ # September 18, 2007
3
+ #
4
+
5
+
6
+ class TestTc_failure < Test::Unit::TestCase
7
+
8
+ def a
9
+ raise "boom"
10
+ end
11
+
12
+ def b
13
+ a()
14
+ end
15
+
16
+ def test_location_disp
17
+ e=Exception.new("testFailure")
18
+ failureTest=Report::TestUnit::Failure.new("TestFailure", e.backtrace(), "testFailure")
19
+ assert_equal("No backtrace", failureTest.location_disp())
20
+ begin
21
+ b()
22
+ rescue => detail
23
+ errorTest=Report::TestUnit::Failure.new("TestFailure", detail.backtrace(), detail.message())
24
+ end
25
+ assert_match(/.*\/testunit\/tc_failure.rb:9\]/, errorTest.location_disp())
26
+ end
27
+
28
+ end
@@ -0,0 +1,33 @@
1
+ # tc_success.rb
2
+ # September 18, 2007
3
+ #
4
+
5
+
6
+ class TestTc_success < Test::Unit::TestCase
7
+ def setup
8
+ @testSuccess=Report::TestUnit::Success.new("testSuccess")
9
+ end
10
+
11
+ def teardown
12
+ @testSuccess=nil
13
+ end
14
+
15
+ def test_constant
16
+ assert_equal("S", Report::TestUnit::Success::SINGLE_CHARACTER)
17
+ assert_equal("S", @testSuccess.single_character_display())
18
+ end
19
+
20
+ def test_message
21
+ assert_equal("Successfully passed", @testSuccess.message())
22
+ end
23
+
24
+ def test_short_display
25
+ assert_equal("testSuccess: SUCCESS", @testSuccess.short_display())
26
+ end
27
+
28
+ def test_long_display
29
+ assert_equal("SUCCESS:\ntestSuccess: Successfully passed", @testSuccess.long_display())
30
+ assert_equal("SUCCESS:\ntestSuccess: Successfully passed", @testSuccess.to_s())
31
+ end
32
+
33
+ end
@@ -0,0 +1,164 @@
1
+ # tc_testcase.rb
2
+ # September 18, 2007
3
+ #
4
+
5
+
6
+ class TestTc_testcase < Test::Unit::TestCase
7
+
8
+ def test_success
9
+ rd, wr = IO.pipe
10
+ TESTCASES::TestRunner.run(TESTCASES::TS_MyTestSuite1, 3, wr)
11
+ wr.close
12
+ result = rd.read
13
+ rd.close
14
+ assert_equal("test_success1(TESTCASES::TestTc_testCase1), Success, ., .\n", result)
15
+ end
16
+
17
+ def test_failure
18
+ rd, wr = IO.pipe
19
+ TESTCASES::TestRunner.run(TESTCASES::TS_MyTestSuite2, 3, wr)
20
+ wr.close
21
+ result = rd.read
22
+ rd.close
23
+ assert_equal("test_failure2(TESTCASES::TestTc_testCase2), Failure\n", result)
24
+ end
25
+
26
+ def test_error
27
+ rd, wr = IO.pipe
28
+ TESTCASES::TestRunner.run(TESTCASES::TS_MyTestSuite3, 3, wr)
29
+ wr.close
30
+ result = rd.read
31
+ rd.close
32
+ assert_equal("test_error3(TESTCASES::TestTc_testCase3), Error\n", result)
33
+ end
34
+
35
+ end
36
+
37
+ module TESTCASES
38
+ class TestTc_testCase1 < Report::TestUnit::TestCase
39
+ def test_success1
40
+ assert_equal(1, 1)
41
+ end
42
+
43
+ end
44
+
45
+ class TS_MyTestSuite1
46
+ def self.suite
47
+ suite = Test::Unit::TestSuite.new
48
+ suite << TestTc_testCase1.suite
49
+ return suite
50
+ end
51
+ end
52
+
53
+ class TestTc_testCase2 < Report::TestUnit::TestCase
54
+ def test_failure2
55
+ assert_equal(1, 2)
56
+ end
57
+
58
+ end
59
+
60
+ class TS_MyTestSuite2
61
+ def self.suite
62
+ suite = Test::Unit::TestSuite.new
63
+ suite << TestTc_testCase2.suite
64
+ return suite
65
+ end
66
+ end
67
+
68
+ class TestTc_testCase3 < Report::TestUnit::TestCase
69
+ def test_error3
70
+ assert_equal(1)
71
+ end
72
+
73
+ end
74
+
75
+ class TS_MyTestSuite3
76
+ def self.suite
77
+ suite = Test::Unit::TestSuite.new
78
+ suite << TestTc_testCase3.suite
79
+ return suite
80
+ end
81
+ end
82
+
83
+
84
+ class TestRunner
85
+ extend Test::Unit::UI::TestRunnerUtilities
86
+ def self.run(suite, output_level=NORMAL, io=STDOUT)
87
+ return new(suite, output_level, io).start
88
+ end
89
+
90
+ SILENT = 0
91
+ PROGRESS_ONLY = 1
92
+ NORMAL = 2
93
+ VERBOSE = 3
94
+
95
+ def initialize(suite, output_level=NORMAL, io=STDOUT)
96
+ if (suite.respond_to?(:suite))
97
+ @suite = suite.suite
98
+ else
99
+ @suite = suite
100
+ end
101
+ @already_outputted = false
102
+ @faults = []
103
+ @io=io
104
+ end
105
+
106
+ def start
107
+ setup_mediator
108
+ attach_to_mediator
109
+ return start_mediator
110
+ end
111
+
112
+ private
113
+ def setup_mediator
114
+ @mediator = create_mediator(@suite)
115
+ suite_name = @suite.to_s
116
+ if ( @suite.kind_of?(Module) )
117
+ suite_name = @suite.name
118
+ end
119
+ end
120
+
121
+ def create_mediator(suite)
122
+ return Report::TestUnit::UI::TestRunnerMediator.new(suite)
123
+ end
124
+
125
+ def attach_to_mediator
126
+ @mediator.add_listener(Report::TestUnit::TestResult::FAULT, &method(:add_fault))
127
+ @mediator.add_listener(Report::TestUnit::TestResult::SUCCESS, &method(:add_success))
128
+ @mediator.add_listener(Report::TestUnit::UI::TestRunnerMediator::STARTED, &method(:started))
129
+ @mediator.add_listener(Report::TestUnit::UI::TestRunnerMediator::FINISHED, &method(:finished))
130
+ @mediator.add_listener(Report::TestUnit::TestCase::STARTED, &method(:test_started))
131
+ @mediator.add_listener(Report::TestUnit::TestCase::FINISHED, &method(:test_finished))
132
+ end
133
+
134
+ def add_success(result)
135
+ @io.puts "#{result.test_name}, Success, ., ."
136
+ end
137
+
138
+ def start_mediator
139
+ return @mediator.run_suite
140
+ end
141
+
142
+ def add_fault(fault)
143
+ if fault.single_character_display == "F"
144
+ @io.puts "#{fault.test_name}, Failure"
145
+ elsif fault.single_character_display == "E"
146
+ @io.puts "#{fault.test_name}, Error"
147
+ end
148
+ end
149
+
150
+ def started(result)
151
+ @result = result
152
+ end
153
+
154
+ def finished(elapsed_time)
155
+ end
156
+
157
+ def test_started(name)
158
+ end
159
+
160
+ def test_finished(name)
161
+ @already_outputted = false
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,16 @@
1
+ # tc_testresukt.rb
2
+ # September 18, 2007
3
+ #
4
+
5
+
6
+ class TestTc_testresult < Test::Unit::TestCase
7
+
8
+ def test_constant
9
+ assert_equal("SUCCESS", Report::TestUnit::TestResult::SUCCESS)
10
+ end
11
+ def test_add_success()
12
+ testResult=Report::TestUnit::TestResult.new()
13
+ assert_nothing_raised {testResult.add_success(Report::TestUnit::Success.new("testReport"))}
14
+ end
15
+
16
+ end
@@ -0,0 +1,55 @@
1
+ # tc_testrunner.rb
2
+ # September 19, 2007
3
+ #
4
+
5
+
6
+ class TestTc_testrunner < Test::Unit::TestCase
7
+
8
+ def test_constants
9
+ assert_equal(0, Report::TestUnit::UI::Report::TestRunner::SILENT)
10
+ assert_equal(1, Report::TestUnit::UI::Report::TestRunner::PROGRESS_ONLY)
11
+ assert_equal(2, Report::TestUnit::UI::Report::TestRunner::NORMAL)
12
+ assert_equal(3, Report::TestUnit::UI::Report::TestRunner::VERBOSE)
13
+ end
14
+
15
+ def test_rest
16
+ Report::TestUnit::UI::Report::TestRunner.run(TESTCASES::TS_MyTestSuite4, 3)
17
+ assert_equal(true, FileTest::exists?("#{ENV['UNIT_TEST_REPORT_DIR']}/index.html"))
18
+ index=File.open("#{ENV['UNIT_TEST_REPORT_DIR']}/index.html", "r")
19
+ indexdata=index.read()
20
+ assert_equal(0, indexdata =~ /.*TESTCASES\:\:TestTc_testCase4\.html.*>3<.*>1<.*>1<.*>1<.*>3 tests\, 2 assertions\, 1 failures\, 1 errors<.*/m)
21
+
22
+ assert_equal(true, FileTest::exists?("#{ENV['UNIT_TEST_REPORT_DIR']}/classes/TESTCASES::TestTc_testCase4.html"))
23
+ index=File.open("#{ENV['UNIT_TEST_REPORT_DIR']}/classes/TESTCASES::TestTc_testCase4.html", "r")
24
+ indexdata=index.read()
25
+ assert_equal(0, indexdata =~ /.*>test_error4<.*>Error<.*>test_failure4<.*>Failure<.*>test_success4<.*>Success<.*/m)
26
+ end
27
+
28
+
29
+ end
30
+
31
+
32
+ module TESTCASES
33
+ class TestTc_testCase4 < Report::TestUnit::TestCase
34
+ def test_success4
35
+ assert_equal(1, 1)
36
+ end
37
+
38
+ def test_error4
39
+ assert_equal(1)
40
+ end
41
+
42
+ def test_failure4
43
+ assert_equal(1,2)
44
+ end
45
+ end
46
+
47
+ class TS_MyTestSuite4
48
+ def self.suite
49
+ suite = Test::Unit::TestSuite.new
50
+ suite << TestTc_testCase4.suite
51
+ return suite
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,31 @@
1
+ # tc_test.rb
2
+ # September 19, 2007
3
+ #
4
+
5
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
6
+
7
+ require 'test/unit'
8
+
9
+ class TestTc_test < Test::Unit::TestCase
10
+ # def setup
11
+ # end
12
+ #
13
+ # def teardown
14
+ # end
15
+
16
+ def test_fail
17
+ assert(false, 'Assertion was false.')
18
+ end
19
+
20
+ def test_foo
21
+ # assert_equal("foo", bar)
22
+
23
+ # assert, assert_block, assert_equal, assert_in_delta, assert_instance_of,
24
+ # assert_kind_of, assert_match, assert_nil, assert_no_match, assert_not_equal,
25
+ # assert_not_nil, assert_not_same, assert_nothing_raised, assert_nothing_thrown,
26
+ # assert_operator, assert_raise, assert_raises, assert_respond_to, assert_same,
27
+ # assert_send, assert_throws
28
+
29
+ flunk "TODO: Write test"
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ # ts_reportTestUnit.rb
2
+ # September 18, 2007
3
+ #
4
+
5
+ require 'rubygems'
6
+ require 'reportTestUnit'
7
+ require 'test/unit/ui/console/testrunner'
8
+
9
+ require 'testunit/tc_testcase'
10
+ require 'testunit/tc_success'
11
+ require 'testunit/tc_failure'
12
+ require 'testunit/tc_error'
13
+ require 'testunit/tc_testresult'
14
+ require 'testunit/ui/report/tc_testrunner'
15
+
16
+
17
+ ENV['UNIT_TEST_REPORT_DIR']="/tmp"
18
+
19
+
20
+ class TS_MyTests
21
+ def self.suite
22
+ suite = Test::Unit::TestSuite.new("testcases")
23
+ suite << TestTc_testcase.suite
24
+ suite << TestTc_testrunner.suite
25
+ suite << TestTc_testresult.suite
26
+ suite << TestTc_success.suite
27
+ suite << TestTc_failure.suite
28
+ suite << TestTc_error.suite
29
+ return suite
30
+ end
31
+ end
32
+
33
+ Test::Unit::UI::Console::TestRunner.run(TS_MyTests, 3)
34
+
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: reportTestUnit
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2007-09-19 00:00:00 +01:00
8
+ summary: An Extension to the Test::Unit platform to produce html reports
9
+ require_paths:
10
+ - lib
11
+ email: erobson@tssg.org
12
+ homepage: http://tssgrb.rubyforge.org/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: reportTestUnit
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Eric Robson
31
+ files:
32
+ - lib/report
33
+ - lib/reportTestUnit.rb
34
+ - lib/report/testunit
35
+ - lib/report/testunit/error.rb
36
+ - lib/report/testunit/failure.rb
37
+ - lib/report/testunit/success.rb
38
+ - lib/report/testunit/testcase.rb
39
+ - lib/report/testunit/testresult.rb
40
+ - lib/report/testunit/ui
41
+ - lib/report/testunit/ui/report
42
+ - lib/report/testunit/ui/testrunnermediator.rb
43
+ - lib/report/testunit/ui/report/testrunner.rb
44
+ - test/report
45
+ - test/report/testunit
46
+ - test/report/ts_reportTestUnit.rb
47
+ - test/report/testunit/tc_error.rb
48
+ - test/report/testunit/tc_failure.rb
49
+ - test/report/testunit/tc_success.rb
50
+ - test/report/testunit/tc_testcase.rb
51
+ - test/report/testunit/tc_testresult.rb
52
+ - test/report/testunit/ui
53
+ - test/report/testunit/ui/report
54
+ - test/report/testunit/ui/tc_test.rb
55
+ - test/report/testunit/ui/report/tc_testrunner.rb
56
+ - README
57
+ test_files:
58
+ - test/report/ts_reportTestUnit.rb
59
+ rdoc_options: []
60
+
61
+ extra_rdoc_files:
62
+ - README
63
+ executables: []
64
+
65
+ extensions: []
66
+
67
+ requirements: []
68
+
69
+ dependencies: []
70
+