test-unit 2.0.0 → 2.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.
Files changed (39) hide show
  1. data/History.txt +30 -0
  2. data/Manifest.txt +20 -12
  3. data/README.txt +28 -12
  4. data/Rakefile +5 -0
  5. data/TODO +1 -0
  6. data/html/classic.html +15 -0
  7. data/html/index.html +25 -0
  8. data/html/index.html.ja +27 -0
  9. data/html/test-unit-classic.png +0 -0
  10. data/lib/test/unit.rb +62 -0
  11. data/lib/test/unit/assertions.rb +350 -66
  12. data/lib/test/unit/autorunner.rb +68 -13
  13. data/lib/test/unit/collector/load.rb +1 -1
  14. data/lib/test/unit/color-scheme.rb +85 -0
  15. data/lib/test/unit/color.rb +40 -5
  16. data/lib/test/unit/diff.rb +14 -0
  17. data/lib/test/unit/fixture.rb +2 -2
  18. data/lib/test/unit/runner/console.rb +8 -2
  19. data/lib/test/unit/testcase.rb +86 -2
  20. data/lib/test/unit/ui/console/testrunner.rb +51 -26
  21. data/lib/test/unit/version.rb +1 -1
  22. data/sample/test_user.rb +22 -0
  23. data/test/collector/{test_descendant.rb → test-descendant.rb} +0 -0
  24. data/test/collector/{test_load.rb → test-load.rb} +1 -1
  25. data/test/{test_attribute.rb → test-attribute.rb} +0 -0
  26. data/test/test-color-scheme.rb +55 -0
  27. data/test/{test_color.rb → test-color.rb} +10 -0
  28. data/test/{test_diff.rb → test-diff.rb} +0 -0
  29. data/test/{test_emacs_runner.rb → test-emacs-runner.rb} +0 -0
  30. data/test/test-fixture.rb +287 -0
  31. data/test/{test_notification.rb → test-notification.rb} +4 -4
  32. data/test/{test_omission.rb → test-omission.rb} +6 -6
  33. data/test/{test_pending.rb → test-pending.rb} +6 -6
  34. data/test/{test_priority.rb → test-priority.rb} +0 -0
  35. data/test/test_assertions.rb +366 -63
  36. data/test/test_testcase.rb +48 -0
  37. data/test/{testunit_test_util.rb → testunit-test-util.rb} +1 -1
  38. metadata +27 -29
  39. data/test/test_fixture.rb +0 -275
@@ -1,3 +1,33 @@
1
+ === 2.0.1 / 2008-11-09
2
+
3
+ * 19 major enhancements
4
+
5
+ * support ruby 1.9.1.
6
+ * add run_test method to be extensible.
7
+ * improve priority-mode auto off.
8
+ * improve startup/shutdown RDoc. [Daniel Berger]
9
+ * add assert_compare. [#20851] [Designing Patterns]
10
+ * add assert_fail_assertion. [#20851] [Designing Patterns]
11
+ * add assert_raise_message. [#20851] [Designing Patterns]
12
+ * support folded diff.
13
+ * add assert_raise_kind_of. [Daniel Berger]
14
+ * ingore inherited test for nested test case.
15
+ * add assert_const_defined.
16
+ * add assert_not_const_defined.
17
+ * support assert_raise with an exception object.
18
+ * support assert_raise with no arguments that asserts any
19
+ exception is raised. [#22602] [Daniel Berger]
20
+ * support folded dot progress.
21
+ * add --progress-row-max option.
22
+ * support color scheme customize.
23
+ * support configuration file. (YAML)
24
+ * recognize test-XXX.rb files as test files not only test_XXX.rb
25
+
26
+ * Thanks
27
+
28
+ * Daniel Berger
29
+ * Designing Patterns
30
+
1
31
  === 2.0.0 / 2008-06-18
2
32
 
3
33
  * 15 major enhancements
@@ -2,7 +2,12 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
+ TODO
5
6
  bin/testrb
7
+ html/classic.html
8
+ html/index.html
9
+ html/index.html.ja
10
+ html/test-unit-classic.png
6
11
  lib/test/unit.rb
7
12
  lib/test/unit/assertionfailederror.rb
8
13
  lib/test/unit/assertions.rb
@@ -13,6 +18,7 @@ lib/test/unit/collector/descendant.rb
13
18
  lib/test/unit/collector/dir.rb
14
19
  lib/test/unit/collector/load.rb
15
20
  lib/test/unit/collector/objectspace.rb
21
+ lib/test/unit/color-scheme.rb
16
22
  lib/test/unit/color.rb
17
23
  lib/test/unit/diff.rb
18
24
  lib/test/unit/error.rb
@@ -42,28 +48,30 @@ sample/adder.rb
42
48
  sample/subtracter.rb
43
49
  sample/tc_adder.rb
44
50
  sample/tc_subtracter.rb
51
+ sample/test_user.rb
45
52
  sample/ts_examples.rb
46
- test/collector/test_descendant.rb
53
+ test/collector/test-descendant.rb
54
+ test/collector/test-load.rb
47
55
  test/collector/test_dir.rb
48
- test/collector/test_load.rb
49
56
  test/collector/test_objectspace.rb
50
57
  test/run-test.rb
58
+ test/test-attribute.rb
59
+ test/test-color-scheme.rb
60
+ test/test-color.rb
61
+ test/test-diff.rb
62
+ test/test-emacs-runner.rb
63
+ test/test-fixture.rb
64
+ test/test-notification.rb
65
+ test/test-omission.rb
66
+ test/test-pending.rb
67
+ test/test-priority.rb
51
68
  test/test_assertions.rb
52
- test/test_attribute.rb
53
- test/test_color.rb
54
- test/test_diff.rb
55
- test/test_emacs_runner.rb
56
69
  test/test_error.rb
57
70
  test/test_failure.rb
58
- test/test_fixture.rb
59
- test/test_notification.rb
60
- test/test_omission.rb
61
- test/test_pending.rb
62
- test/test_priority.rb
63
71
  test/test_testcase.rb
64
72
  test/test_testresult.rb
65
73
  test/test_testsuite.rb
66
- test/testunit_test_util.rb
74
+ test/testunit-test-util.rb
67
75
  test/ui/test_testrunmediator.rb
68
76
  test/util/test_backtracefilter.rb
69
77
  test/util/test_observable.rb
data/README.txt CHANGED
@@ -1,13 +1,17 @@
1
- = Test::Unit (Classic)
1
+ = Test::Unit 2.x
2
2
 
3
3
  * http://rubyforge.org/projects/test-unit/
4
4
 
5
- == DESCRIPTION:
5
+ == DESCRIPTION
6
6
 
7
- Test::Unit (Classic) - Nathaniel Talbott's originial test-unit,
8
- externalized from the ruby project as a gem (for tool developers).
7
+ Test::Unit 2.x - Improved version of Test::Unit bundled in
8
+ Ruby 1.8.x.
9
9
 
10
- == FEATURES/PROBLEMS:
10
+ Ruby 1.9.x bundles miniunit not Test::Unit. Test::Unit
11
+ bundled in Ruby 1.8.x had not been improved but unbundled
12
+ Test::Unit (Test::Unit 2.x) will be improved actively.
13
+
14
+ == FEATURES
11
15
 
12
16
  * Test::Unit 1.2.3 is the original Test::Unit, taken
13
17
  straight from the ruby distribution. It is being
@@ -15,18 +19,30 @@ externalized from the ruby project as a gem (for tool developers).
15
19
  stand-alone package. (The test framework in ruby is going
16
20
  to radically change very soon).
17
21
 
18
- * DO NOT INSTALL THIS GEM unless you're active state or some other
19
- development tool provider! You don't need it.
22
+ * Test::Unit 2.x will be improved actively and may break
23
+ compatiblity with Test::Unit 1.2.3. (We will not hope it
24
+ if it isn't needed.)
25
+
26
+ * Some features exist as separated gems like GUI test
27
+ runner. (Tk, GTK+ and Fox) test-unit-full gem package
28
+ provides for installing all Test::Unit related gems
29
+ easily.
30
+
31
+ == INSTALL
20
32
 
21
- * Test::Unit 2.0.0 or later are extended versions of the
22
- original Test::Unit (== Tset::Unit 1.2.3).
33
+ % sudo gem install test-unit
23
34
 
24
- == INSTALL:
35
+ If you want to use full Test::Unit features:
25
36
 
26
- * sudo gem install test-unit
37
+ % sudo gem install test-unit-full
27
38
 
28
- == LICENSE:
39
+ == LICENSE
29
40
 
30
41
  (The Ruby License)
31
42
 
32
43
  This software is distributed under the same terms as ruby.
44
+
45
+ == Thanks
46
+
47
+ * Daniel Berger: suggestions.
48
+ * Designing Patterns: Suggestions.
data/Rakefile CHANGED
@@ -15,12 +15,17 @@ Hoe.new('test-unit', version) do |p|
15
15
  end
16
16
 
17
17
  task :check_manifest => :clean_test_result
18
+ task :check_manifest => :clean_coverage
18
19
 
19
20
  task :clean_test_result do
20
21
  test_results = Dir.glob("**/.test-result")
21
22
  sh("rm", "-rf", *test_results) unless test_results.empty?
22
23
  end
23
24
 
25
+ task :clean_coverage do
26
+ sh("rm", "-rf", "coverage")
27
+ end
28
+
24
29
  task :tag do
25
30
  message = "Released Test::Unit #{version}!"
26
31
  base = "svn+ssh://#{ENV['USER']}@rubyforge.org/var/svn/test-unit/"
data/TODO ADDED
@@ -0,0 +1 @@
1
+ * mock.
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html>
3
+ <head>
4
+ <title>Test::Unit (Classic)</title>
5
+ </head>
6
+ <body bgcolor="red">
7
+ <p style="text-align: center">
8
+ <img height="161" width="308" src="test-unit-classic.png">
9
+ <br>
10
+ <br>
11
+ <br>
12
+ Read the <a href="classic/test-unit/">rdoc</a>
13
+ </p>
14
+ </body>
15
+ </html>
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
6
+ <head>
7
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
8
+ <title>Test::Unit - a Unit Testing Framework for Ruby</title>
9
+ </head>
10
+ <body>
11
+ <h1>Test::Unit - a Unit Testing Framework for Ruby</h1>
12
+ <p>[<a href="index.html.ja">Japanese</a>]</p>
13
+ <ul>
14
+ <li><a href="http://rubyforge.org/projects/test-unit/">Project Page</a></li>
15
+ <li>
16
+ <a href="test-unit/">RDoc</a>
17
+ <!--(<a href="ja/test-unit/">ja</a>)-->
18
+ </li>
19
+ <li>
20
+ <a href="classic.html">Classic</a>
21
+ <!--(<a href="ja/classic.html">ja</a>)-->
22
+ </li>
23
+ </ul>
24
+ </body>
25
+ </html>
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
6
+ <head>
7
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
8
+ <title>Test::Unit - Ruby用単体テストフレームワーク</title>
9
+ </head>
10
+ <body>
11
+ <h1>Test::Unit - Ruby用単体テストフレームワーク</h1>
12
+ <p>[<a href="./">English</a>]</p>
13
+ <ul>
14
+ <li>
15
+ <a href="http://rubyforge.org/projects/test-unit/">プロジェクトページ</a>
16
+ </li>
17
+ <li>
18
+ <!--<a href="ja/test-unit/">RDoc</a>-->
19
+ RDoc(<a href="test-unit/">en</a>)
20
+ </li>
21
+ <li>
22
+ <!--<a href="classic.html.html">Classic</a>-->
23
+ Classic(<a href="classic.html">en</a>)
24
+ </li>
25
+ </ul>
26
+ </body>
27
+ </html>
@@ -253,6 +253,68 @@ module Test # :nodoc:
253
253
  # the dynamic suite using the console TestRunner.
254
254
  #
255
255
  #
256
+ # == Configuration file
257
+ #
258
+ # Test::Unit reads 'test-unit.yml' in the current working
259
+ # directory as Test::Unit's configuration file. It can
260
+ # contain the following configurations:
261
+ #
262
+ # * color scheme definitions
263
+ # * test runner to be used
264
+ # * test runner options
265
+ # * test collector to be used
266
+ #
267
+ # Except color scheme definitions, all of them are
268
+ # specified by command line option.
269
+ #
270
+ # Here are sample color scheme definitions:
271
+ #
272
+ # color_schemes:
273
+ # inverted:
274
+ # success:
275
+ # name: red
276
+ # bold: true
277
+ # failure:
278
+ # name: green
279
+ # bold: true
280
+ # other_scheme:
281
+ # ...
282
+ #
283
+ # Here are the syntax of color scheme definitions:
284
+ #
285
+ # color_schemes:
286
+ # SCHEME_NAME:
287
+ # EVENT_NAME:
288
+ # name: COLOR_NAME
289
+ # intensity: BOOLEAN
290
+ # bold: BOOLEAN
291
+ # italic: BOOLEAN
292
+ # underline: BOOLEAN
293
+ # ...
294
+ # ...
295
+ #
296
+ # SCHEME_NAME:: the name of the color scheme
297
+ # EVENT_NAME:: one of [success, failure, pending,
298
+ # omission, notification, error]
299
+ # COLOR_NAME:: one of [black, red, green, yellow, blue,
300
+ # magenta, cyan, white]
301
+ # BOOLEAN:: true or false
302
+ #
303
+ # You can use the above 'inverted' color scheme with the
304
+ # following configuration:
305
+ #
306
+ # runner: console
307
+ # console_options:
308
+ # color_scheme: inverted
309
+ # color_schemes:
310
+ # inverted:
311
+ # success:
312
+ # name: red
313
+ # bold: true
314
+ # failure:
315
+ # name: green
316
+ # bold: true
317
+ #
256
318
  # == Questions?
257
319
  #
258
320
  # I'd really like to get feedback from all levels of Ruby
@@ -77,21 +77,7 @@ module Test
77
77
 
78
78
  public
79
79
  def assert_equal(expected, actual, message=nil)
80
- diff = AssertionMessage.delayed_literal do
81
- if !expected.is_a?(String) or !actual.is_a?(String)
82
- expected = AssertionMessage.convert(expected)
83
- actual = AssertionMessage.convert(actual)
84
- end
85
- diff = Diff.readable(expected, actual)
86
- if /^[-+]/ !~ diff
87
- diff = ""
88
- elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff
89
- diff = "\n\ndiff:\n#{diff}"
90
- else
91
- diff = ""
92
- end
93
- diff
94
- end
80
+ diff = AssertionMessage.delayed_diff(expected, actual)
95
81
  full_message = build_message(message, <<EOT, expected, actual, diff)
96
82
  <?> expected but was
97
83
  <?>.?
@@ -99,53 +85,36 @@ EOT
99
85
  assert_block(full_message) { expected == actual }
100
86
  end
101
87
 
102
- private
103
- def _check_exception_class(args) # :nodoc:
104
- args.partition do |klass|
105
- next if klass.instance_of?(Module)
106
- assert(Exception >= klass, "Should expect a class of exception, #{klass}")
107
- true
108
- end
109
- end
110
-
111
- private
112
- def _expected_exception?(actual_exception, exceptions, modules) # :nodoc:
113
- exceptions.include?(actual_exception.class) or
114
- modules.any? {|mod| actual_exception.is_a?(mod)}
115
- end
116
-
117
88
  ##
118
- # Passes if the block raises one of the given exceptions.
89
+ # Passes if the block raises one of the expected
90
+ # exceptions. When an expected exception is an Exception
91
+ # object, passes if expected_exception == actual_exception.
119
92
  #
120
93
  # Example:
121
- # assert_raise RuntimeError, LoadError do
94
+ # assert_raise(RuntimeError, LoadError) do
122
95
  # raise 'Boom!!!'
123
- # end
124
-
96
+ # end # -> pass
97
+ #
98
+ # assert_raise do
99
+ # raise Exception, 'Any exception should be raised!!!'
100
+ # end # -> pass
101
+ #
102
+ # assert_raise(RuntimeError.new("XXX")) {raise "XXX"} # -> pass
103
+ # assert_raise(MyError.new("XXX")) {raise "XXX"} # -> fail
104
+ # assert_raise(RuntimeError.new("ZZZ")) {raise "XXX"} # -> fail
125
105
  public
126
- def assert_raise(*args)
127
- _wrap_assertion do
128
- if Module === args.last
129
- message = ""
130
- else
131
- message = args.pop
132
- end
133
- exceptions, modules = _check_exception_class(args)
134
- expected = args.size == 1 ? args.first : args
135
- actual_exception = nil
136
- full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
106
+ def assert_raise(*args, &block)
107
+ assert_expected_exception = Proc.new do |*_args|
108
+ message, assert_exception_helper, actual_exception = _args
109
+ expected = assert_exception_helper.expected_exceptions
110
+ full_message = build_message(message,
111
+ "<?> exception expected but was\n?",
112
+ expected, actual_exception)
137
113
  assert_block(full_message) do
138
- begin
139
- yield
140
- rescue Exception => actual_exception
141
- break
142
- end
143
- false
114
+ expected == [] or assert_exception_helper.expected?(actual_exception)
144
115
  end
145
- full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
146
- assert_block(full_message) {_expected_exception?(actual_exception, exceptions, modules)}
147
- actual_exception
148
116
  end
117
+ _assert_raise(assert_expected_exception, *args, &block)
149
118
  end
150
119
 
151
120
  ##
@@ -158,6 +127,30 @@ EOT
158
127
  assert_raise(*args, &block)
159
128
  end
160
129
 
130
+ ##
131
+ # Passes if the block raises one of the given
132
+ # exceptions or sub exceptions of the given exceptions.
133
+ #
134
+ # Example:
135
+ # assert_raise_kind_of(SystemCallError) do
136
+ # raise Errno::EACCES
137
+ # end
138
+ def assert_raise_kind_of(*args, &block)
139
+ assert_expected_exception = Proc.new do |*_args|
140
+ message, assert_exception_helper, actual_exception = _args
141
+ expected = assert_exception_helper.expected_exceptions
142
+ full_message = build_message(message,
143
+ "<?> family exception expected " +
144
+ "but was\n?",
145
+ expected, actual_exception)
146
+ assert_block(full_message) do
147
+ assert_exception_helper.expected?(actual_exception, :kind_of?)
148
+ end
149
+ end
150
+ _assert_raise(assert_expected_exception, *args, &block)
151
+ end
152
+
153
+
161
154
  ##
162
155
  # Passes if +object+ .instance_of? +klass+
163
156
  #
@@ -301,18 +294,20 @@ EOT
301
294
  public
302
295
  def assert_nothing_raised(*args)
303
296
  _wrap_assertion do
304
- if Module === args.last
305
- message = ""
306
- else
297
+ if args.last.is_a?(String)
307
298
  message = args.pop
299
+ else
300
+ message = ""
308
301
  end
309
- exceptions, modules = _check_exception_class(args)
302
+
303
+ assert_exception_helper = AssertExceptionHelper.new(self, args)
310
304
  begin
311
305
  yield
312
306
  rescue Exception => e
313
307
  if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
314
- _expected_exception?(e, exceptions, modules))
315
- assert_block(build_message(message, "Exception raised:\n?", e)){false}
308
+ assert_exception_helper.expected?(e))
309
+ failure_message = build_message(message, "Exception raised:\n?", e)
310
+ assert_block(failure_message) {false}
316
311
  else
317
312
  raise
318
313
  end
@@ -398,12 +393,12 @@ EOT
398
393
  # Passes if the block throws +expected_object+
399
394
  #
400
395
  # Example:
401
- # assert_throws :done do
402
- # throw :done
396
+ # assert_throw(:done) do
397
+ # throw(:done)
403
398
  # end
404
399
 
405
400
  public
406
- def assert_throws(expected_object, message="", &proc)
401
+ def assert_throw(expected_object, message="", &proc)
407
402
  _wrap_assertion do
408
403
  begin
409
404
  catch([]) {}
@@ -411,7 +406,7 @@ EOT
411
406
  assert_instance_of(Symbol, expected_object,
412
407
  "assert_throws expects the symbol that should be thrown for its first argument")
413
408
  end
414
- assert_block("Should have passed a block to assert_throws.") do
409
+ assert_block("Should have passed a block to assert_throw.") do
415
410
  block_given?
416
411
  end
417
412
  caught = true
@@ -437,6 +432,14 @@ EOT
437
432
  end
438
433
  end
439
434
 
435
+ ##
436
+ # Alias of assert_throw.
437
+ #
438
+ # Will be deprecated in 1.9, and removed in 2.0.
439
+ def assert_throws(*args, &block)
440
+ assert_throw(*args, &block)
441
+ end
442
+
440
443
  ##
441
444
  # Passes if block does not throw anything.
442
445
  #
@@ -559,6 +562,136 @@ EOT
559
562
  end
560
563
  end
561
564
 
565
+ ##
566
+ # Passes if expression "+expected+ +operator+
567
+ # +actual+" is true.
568
+ #
569
+ # Example:
570
+ # assert_compare(1, "<", 10) # -> pass
571
+ # assert_compare(1, ">=", 10) # -> fail
572
+ def assert_compare(expected, operator, actual, message=nil)
573
+ _wrap_assertion do
574
+ assert_send([["<", "<=", ">", ">="], :include?, operator.to_s])
575
+ case operator.to_s
576
+ when "<"
577
+ operator_description = "less than"
578
+ when "<="
579
+ operator_description = "less than or equal to"
580
+ when ">"
581
+ operator_description = "greater than"
582
+ when ">="
583
+ operator_description = "greater than or equal to"
584
+ end
585
+ template = <<-EOT
586
+ <?> #{operator} <?> should be true
587
+ <?> expected #{operator_description}
588
+ <?>.
589
+ EOT
590
+ full_message = build_message(message, template,
591
+ expected, actual,
592
+ expected, actual)
593
+ assert_block(full_message) do
594
+ expected.send(operator, actual)
595
+ end
596
+ end
597
+ end
598
+
599
+ ##
600
+ # Passes if assertion is failed in block.
601
+ #
602
+ # Example:
603
+ # assert_fail_assertion {assert_equal("A", "B")} # -> pass
604
+ # assert_fail_assertion {assert_equal("A", "A")} # -> fail
605
+ def assert_fail_assertion(message=nil)
606
+ _wrap_assertion do
607
+ full_message = build_message(message,
608
+ "Failed assertion was expected.")
609
+ assert_block(full_message) do
610
+ begin
611
+ yield
612
+ false
613
+ rescue AssertionFailedError
614
+ true
615
+ end
616
+ end
617
+ end
618
+ end
619
+
620
+ ##
621
+ # Passes if an exception is raised in block and its
622
+ # message is +expected+.
623
+ #
624
+ # Example:
625
+ # assert_raise_message("exception") {raise "exception"} # -> pass
626
+ # assert_raise_message(/exc/i) {raise "exception"} # -> pass
627
+ # assert_raise_message("exception") {raise "EXCEPTION"} # -> fail
628
+ # assert_raise_message("exception") {} # -> fail
629
+ def assert_raise_message(expected, message=nil)
630
+ _wrap_assertion do
631
+ full_message = build_message(message,
632
+ "<?> exception message expected " +
633
+ "but none was thrown.",
634
+ expected)
635
+ exception = nil
636
+ assert_block(full_message) do
637
+ begin
638
+ yield
639
+ false
640
+ rescue Exception => exception
641
+ true
642
+ end
643
+ end
644
+
645
+ actual = exception.message
646
+ diff = AssertionMessage.delayed_diff(expected, actual)
647
+ full_message =
648
+ build_message(message,
649
+ "<?> exception message expected but was\n" +
650
+ "<?>.?", expected, actual, diff)
651
+ assert_block(full_message) do
652
+ if expected.is_a?(Regexp)
653
+ expected =~ actual
654
+ else
655
+ expected == actual
656
+ end
657
+ end
658
+ end
659
+ end
660
+
661
+ ##
662
+ # Passes if +object+.const_defined?(+constant_name+)
663
+ #
664
+ # Example:
665
+ # assert_const_defined(Test, :Unit) # -> pass
666
+ # assert_const_defined(Object, :Nonexistent) # -> fail
667
+ def assert_const_defined(object, constant_name, message=nil)
668
+ _wrap_assertion do
669
+ full_message = build_message(message,
670
+ "<?>.const_defined\\?(<?>) expected.",
671
+ object, constant_name)
672
+ assert_block(full_message) do
673
+ object.const_defined?(constant_name)
674
+ end
675
+ end
676
+ end
677
+
678
+ ##
679
+ # Passes if !+object+.const_defined?(+constant_name+)
680
+ #
681
+ # Example:
682
+ # assert_not_const_defined(Object, :Nonexistent) # -> pass
683
+ # assert_not_const_defined(Test, :Unit) # -> fail
684
+ def assert_not_const_defined(object, constant_name, message=nil)
685
+ _wrap_assertion do
686
+ full_message = build_message(message,
687
+ "!<?>.const_defined\\?(<?>) expected.",
688
+ object, constant_name)
689
+ assert_block(full_message) do
690
+ !object.const_defined?(constant_name)
691
+ end
692
+ end
693
+ end
694
+
562
695
  ##
563
696
  # Builds a failure message. +head+ is added before the +template+ and
564
697
  # +arguments+ replaces the '?'s positionally in the template.
@@ -601,8 +734,37 @@ EOT
601
734
  def self.use_pp=(value)
602
735
  AssertionMessage.use_pp = value
603
736
  end
604
-
737
+
605
738
  # :stopdoc:
739
+ private
740
+ def _assert_raise(assert_expected_exception, *args, &block)
741
+ _wrap_assertion do
742
+ if args.last.is_a?(String)
743
+ message = args.pop
744
+ else
745
+ message = ""
746
+ end
747
+
748
+ assert_exception_helper = AssertExceptionHelper.new(self, args)
749
+ expected = assert_exception_helper.expected_exceptions
750
+ actual_exception = nil
751
+ full_message = build_message(message,
752
+ "<?> exception expected " +
753
+ "but none was thrown.",
754
+ expected)
755
+ assert_block(full_message) do
756
+ begin
757
+ yield
758
+ false
759
+ rescue Exception => actual_exception
760
+ true
761
+ end
762
+ end
763
+ assert_expected_exception.call(message, assert_exception_helper,
764
+ actual_exception)
765
+ actual_exception
766
+ end
767
+ end
606
768
 
607
769
  class AssertionMessage
608
770
  @use_pp = true
@@ -617,6 +779,31 @@ EOT
617
779
  DelayedLiteral.new(block)
618
780
  end
619
781
 
782
+ def delayed_diff(from, to)
783
+ delayed_literal do
784
+ if !from.is_a?(String) or !to.is_a?(String)
785
+ from = convert(from)
786
+ to = convert(to)
787
+ end
788
+
789
+ diff = Diff.readable(from, to)
790
+ if /^[-+]/ !~ diff
791
+ diff = ""
792
+ elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff
793
+ diff = "\n\ndiff:\n#{diff}"
794
+ else
795
+ diff = ""
796
+ end
797
+
798
+ if Diff.need_fold?(diff)
799
+ folded_diff = Diff.folded_readable(from, to)
800
+ diff << "\n\nfolded diff:\n#{folded_diff}"
801
+ end
802
+
803
+ diff
804
+ end
805
+ end
806
+
620
807
  def convert(object)
621
808
  case object
622
809
  when Exception
@@ -715,8 +902,105 @@ EOM
715
902
  end
716
903
  end
717
904
 
718
- # :startdoc:
905
+ class AssertExceptionHelper
906
+ class WrappedException
907
+ def initialize(exception)
908
+ @exception = exception
909
+ end
910
+
911
+ def inspect
912
+ inspect_method = @exception.method(:inspect)
913
+ if inspect_method.respond_to?(:owner) and
914
+ inspect_method.owner == Exception
915
+ "#{@exception.class.inspect}(#{@exception.message.inspect})"
916
+ else
917
+ @exception.inspect
918
+ end
919
+ end
920
+
921
+ def method_missing(name, *args, &block)
922
+ @exception.send(name, *args, &block)
923
+ end
924
+ end
925
+
926
+ def initialize(test_case, expected_exceptions)
927
+ @test_case = test_case
928
+ @expected_exceptions = expected_exceptions
929
+ @expected_classes, @expected_modules, @expected_objects =
930
+ split_expected_exceptions(expected_exceptions)
931
+ end
932
+
933
+ def expected_exceptions
934
+ exceptions = @expected_exceptions.collect do |exception|
935
+ if exception.is_a?(Exception)
936
+ WrappedException.new(exception)
937
+ else
938
+ exception
939
+ end
940
+ end
941
+ if exceptions.size == 1
942
+ exceptions[0]
943
+ else
944
+ exceptions
945
+ end
946
+ end
947
+
948
+ def expected?(actual_exception, equality=nil)
949
+ equality ||= :instance_of?
950
+ expected_class?(actual_exception, equality) or
951
+ expected_module?(actual_exception) or
952
+ expected_object?(actual_exception)
953
+ end
954
+
955
+ private
956
+ def split_expected_exceptions(expected_exceptions)
957
+ exception_modules = []
958
+ exception_objects = []
959
+ exception_classes = []
960
+ expected_exceptions.each do |exception_type|
961
+ if exception_type.instance_of?(Module)
962
+ exception_modules << exception_type
963
+ elsif exception_type.is_a?(Exception)
964
+ exception_objects << exception_type
965
+ else
966
+ @test_case.send(:assert,
967
+ Exception >= exception_type,
968
+ "Should expect a class of exception, " +
969
+ "#{exception_type}")
970
+ exception_classes << exception_type
971
+ end
972
+ end
973
+ [exception_classes, exception_modules, exception_objects]
974
+ end
975
+
976
+ def expected_class?(actual_exception, equality)
977
+ @expected_classes.any? do |expected_class|
978
+ actual_exception.send(equality, expected_class)
979
+ end
980
+ end
719
981
 
982
+ def expected_module?(actual_exception)
983
+ @expected_modules.any? do |expected_module|
984
+ actual_exception.is_a?(expected_module)
985
+ end
986
+ end
987
+
988
+ def expected_object?(actual_exception)
989
+ @expected_objects.any? do |expected_object|
990
+ equal_method = expected_object.method(:==)
991
+ if equal_method.respond_to?(:owner) and
992
+ (equal_method.owner == Kernel or
993
+ equal_method.owner == Exception)
994
+ expected_object.class == actual_exception.class and
995
+ expected_object.message == actual_exception.message
996
+ else
997
+ expected_object == actual_exception
998
+ end
999
+ end
1000
+ end
1001
+ end
1002
+
1003
+ # :startdoc:
720
1004
  end
721
1005
  end
722
1006
  end