reportTestUnit 1.0.0

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