test-unit 1.2.3 → 2.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/History.txt +27 -0
- data/Manifest.txt +30 -8
- data/README.txt +9 -4
- data/Rakefile +16 -1
- data/bin/testrb +0 -0
- data/lib/test/unit/assertions.rb +148 -48
- data/lib/test/unit/attribute.rb +125 -0
- data/lib/test/unit/autorunner.rb +101 -71
- data/lib/test/unit/collector/descendant.rb +23 -0
- data/lib/test/unit/collector/dir.rb +1 -1
- data/lib/test/unit/collector/load.rb +135 -0
- data/lib/test/unit/color.rb +61 -0
- data/lib/test/unit/diff.rb +524 -0
- data/lib/test/unit/error.rb +70 -2
- data/lib/test/unit/exceptionhandler.rb +39 -0
- data/lib/test/unit/failure.rb +63 -4
- data/lib/test/unit/fixture.rb +185 -0
- data/lib/test/unit/notification.rb +125 -0
- data/lib/test/unit/omission.rb +143 -0
- data/lib/test/unit/pending.rb +146 -0
- data/lib/test/unit/priority.rb +146 -0
- data/lib/test/unit/runner/console.rb +46 -0
- data/lib/test/unit/runner/emacs.rb +8 -0
- data/lib/test/unit/testcase.rb +193 -76
- data/lib/test/unit/testresult.rb +37 -28
- data/lib/test/unit/testsuite.rb +35 -1
- data/lib/test/unit/ui/console/outputlevel.rb +14 -0
- data/lib/test/unit/ui/console/testrunner.rb +96 -28
- data/lib/test/unit/ui/emacs/testrunner.rb +49 -0
- data/lib/test/unit/ui/testrunner.rb +20 -0
- data/lib/test/unit/ui/testrunnermediator.rb +28 -19
- data/lib/test/unit/ui/testrunnerutilities.rb +2 -7
- data/lib/test/unit/util/backtracefilter.rb +2 -1
- data/lib/test/unit/version.rb +1 -1
- data/test/collector/test_descendant.rb +135 -0
- data/test/collector/test_load.rb +333 -0
- data/test/run-test.rb +13 -0
- data/test/test_assertions.rb +221 -56
- data/test/test_attribute.rb +86 -0
- data/test/test_color.rb +37 -0
- data/test/test_diff.rb +477 -0
- data/test/test_emacs_runner.rb +60 -0
- data/test/test_fixture.rb +275 -0
- data/test/test_notification.rb +33 -0
- data/test/test_omission.rb +81 -0
- data/test/test_pending.rb +70 -0
- data/test/test_priority.rb +89 -0
- data/test/test_testcase.rb +160 -5
- data/test/test_testresult.rb +61 -52
- data/test/testunit_test_util.rb +14 -0
- data/test/ui/test_testrunmediator.rb +20 -0
- metadata +53 -23
- data/lib/test/unit/ui/fox/testrunner.rb +0 -268
- data/lib/test/unit/ui/gtk/testrunner.rb +0 -416
- data/lib/test/unit/ui/gtk2/testrunner.rb +0 -465
- data/lib/test/unit/ui/tk/testrunner.rb +0 -260
- data/test/runit/test_assert.rb +0 -402
- data/test/runit/test_testcase.rb +0 -91
- data/test/runit/test_testresult.rb +0 -144
- data/test/runit/test_testsuite.rb +0 -49
data/History.txt
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
=== 2.0.0 / 2008-06-18
|
2
|
+
|
3
|
+
* 15 major enhancements
|
4
|
+
|
5
|
+
* support startup/shutdown. (test case level setup/teardown)
|
6
|
+
* support multiple setup/teardown.
|
7
|
+
* support pending.
|
8
|
+
* support omission.
|
9
|
+
* support notification.
|
10
|
+
* support colorize.
|
11
|
+
* support diff.
|
12
|
+
* support test attribute.
|
13
|
+
* add assert_boolean.
|
14
|
+
* add assert_true.
|
15
|
+
* add assert_false.
|
16
|
+
* add --priority-mode option.
|
17
|
+
* don't use ObjectSpace to collect test cases.
|
18
|
+
* make more customizable. (additional options, exception handling and so on)
|
19
|
+
* improve Emacs integration.
|
20
|
+
|
21
|
+
* 4 major changes
|
22
|
+
|
23
|
+
* remove GTK+1 support.
|
24
|
+
* split GTK+ runner as another gem.
|
25
|
+
* split FOX runner as another gem.
|
26
|
+
* split Tk runner as another gem.
|
27
|
+
|
1
28
|
=== 1.2.3 / 2008-02-25
|
2
29
|
|
3
30
|
* 1 major enhancement
|
data/Manifest.txt
CHANGED
@@ -6,22 +6,34 @@ bin/testrb
|
|
6
6
|
lib/test/unit.rb
|
7
7
|
lib/test/unit/assertionfailederror.rb
|
8
8
|
lib/test/unit/assertions.rb
|
9
|
+
lib/test/unit/attribute.rb
|
9
10
|
lib/test/unit/autorunner.rb
|
10
11
|
lib/test/unit/collector.rb
|
12
|
+
lib/test/unit/collector/descendant.rb
|
11
13
|
lib/test/unit/collector/dir.rb
|
14
|
+
lib/test/unit/collector/load.rb
|
12
15
|
lib/test/unit/collector/objectspace.rb
|
16
|
+
lib/test/unit/color.rb
|
17
|
+
lib/test/unit/diff.rb
|
13
18
|
lib/test/unit/error.rb
|
19
|
+
lib/test/unit/exceptionhandler.rb
|
14
20
|
lib/test/unit/failure.rb
|
21
|
+
lib/test/unit/fixture.rb
|
22
|
+
lib/test/unit/notification.rb
|
23
|
+
lib/test/unit/omission.rb
|
24
|
+
lib/test/unit/pending.rb
|
25
|
+
lib/test/unit/priority.rb
|
26
|
+
lib/test/unit/runner/console.rb
|
27
|
+
lib/test/unit/runner/emacs.rb
|
15
28
|
lib/test/unit/testcase.rb
|
16
29
|
lib/test/unit/testresult.rb
|
17
30
|
lib/test/unit/testsuite.rb
|
31
|
+
lib/test/unit/ui/console/outputlevel.rb
|
18
32
|
lib/test/unit/ui/console/testrunner.rb
|
19
|
-
lib/test/unit/ui/
|
20
|
-
lib/test/unit/ui/
|
21
|
-
lib/test/unit/ui/gtk2/testrunner.rb
|
33
|
+
lib/test/unit/ui/emacs/testrunner.rb
|
34
|
+
lib/test/unit/ui/testrunner.rb
|
22
35
|
lib/test/unit/ui/testrunnermediator.rb
|
23
36
|
lib/test/unit/ui/testrunnerutilities.rb
|
24
|
-
lib/test/unit/ui/tk/testrunner.rb
|
25
37
|
lib/test/unit/util/backtracefilter.rb
|
26
38
|
lib/test/unit/util/observable.rb
|
27
39
|
lib/test/unit/util/procwrapper.rb
|
@@ -31,18 +43,28 @@ sample/subtracter.rb
|
|
31
43
|
sample/tc_adder.rb
|
32
44
|
sample/tc_subtracter.rb
|
33
45
|
sample/ts_examples.rb
|
46
|
+
test/collector/test_descendant.rb
|
34
47
|
test/collector/test_dir.rb
|
48
|
+
test/collector/test_load.rb
|
35
49
|
test/collector/test_objectspace.rb
|
36
|
-
test/
|
37
|
-
test/runit/test_testcase.rb
|
38
|
-
test/runit/test_testresult.rb
|
39
|
-
test/runit/test_testsuite.rb
|
50
|
+
test/run-test.rb
|
40
51
|
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
|
41
56
|
test/test_error.rb
|
42
57
|
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
|
43
63
|
test/test_testcase.rb
|
44
64
|
test/test_testresult.rb
|
45
65
|
test/test_testsuite.rb
|
66
|
+
test/testunit_test_util.rb
|
67
|
+
test/ui/test_testrunmediator.rb
|
46
68
|
test/util/test_backtracefilter.rb
|
47
69
|
test/util/test_observable.rb
|
48
70
|
test/util/test_procwrapper.rb
|
data/README.txt
CHANGED
@@ -9,13 +9,18 @@ externalized from the ruby project as a gem (for tool developers).
|
|
9
9
|
|
10
10
|
== FEATURES/PROBLEMS:
|
11
11
|
|
12
|
-
*
|
13
|
-
distribution. It is being
|
14
|
-
builders to use it as a
|
15
|
-
|
12
|
+
* Test::Unit 1.2.3 is the original Test::Unit, taken
|
13
|
+
straight from the ruby distribution. It is being
|
14
|
+
distributed as a gem to allow tool builders to use it as a
|
15
|
+
stand-alone package. (The test framework in ruby is going
|
16
|
+
to radically change very soon).
|
17
|
+
|
16
18
|
* DO NOT INSTALL THIS GEM unless you're active state or some other
|
17
19
|
development tool provider! You don't need it.
|
18
20
|
|
21
|
+
* Test::Unit 2.0.0 or later are extended versions of the
|
22
|
+
original Test::Unit (== Tset::Unit 1.2.3).
|
23
|
+
|
19
24
|
== INSTALL:
|
20
25
|
|
21
26
|
* sudo gem install test-unit
|
data/Rakefile
CHANGED
@@ -4,7 +4,9 @@ require 'rubygems'
|
|
4
4
|
require 'hoe'
|
5
5
|
require './lib/test/unit/version.rb'
|
6
6
|
|
7
|
-
|
7
|
+
version = Test::Unit::VERSION
|
8
|
+
ENV["VERSION"] = version
|
9
|
+
Hoe.new('test-unit', version) do |p|
|
8
10
|
p.developer('Kouhei Sutou', 'kou@cozmixng.org')
|
9
11
|
p.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
|
10
12
|
|
@@ -12,4 +14,17 @@ Hoe.new('test-unit', Test::Unit::VERSION) do |p|
|
|
12
14
|
# p.developer('Nathaniel Talbott', 'nathaniel@talbott.ws')
|
13
15
|
end
|
14
16
|
|
17
|
+
task :check_manifest => :clean_test_result
|
18
|
+
|
19
|
+
task :clean_test_result do
|
20
|
+
test_results = Dir.glob("**/.test-result")
|
21
|
+
sh("rm", "-rf", *test_results) unless test_results.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
task :tag do
|
25
|
+
message = "Released Test::Unit #{version}!"
|
26
|
+
base = "svn+ssh://#{ENV['USER']}@rubyforge.org/var/svn/test-unit/"
|
27
|
+
sh 'svn', 'copy', '-m', message, "#{base}trunk", "#{base}tags/#{version}"
|
28
|
+
end
|
29
|
+
|
15
30
|
# vim: syntax=Ruby
|
data/bin/testrb
CHANGED
File without changes
|
data/lib/test/unit/assertions.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
require 'test/unit/assertionfailederror'
|
6
6
|
require 'test/unit/util/backtracefilter'
|
7
|
+
require 'test/unit/diff'
|
7
8
|
|
8
9
|
module Test
|
9
10
|
module Unit
|
@@ -76,9 +77,24 @@ module Test
|
|
76
77
|
|
77
78
|
public
|
78
79
|
def assert_equal(expected, actual, message=nil)
|
79
|
-
|
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
|
95
|
+
full_message = build_message(message, <<EOT, expected, actual, diff)
|
80
96
|
<?> expected but was
|
81
|
-
|
97
|
+
<?>.?
|
82
98
|
EOT
|
83
99
|
assert_block(full_message) { expected == actual }
|
84
100
|
end
|
@@ -169,7 +185,10 @@ EOT
|
|
169
185
|
|
170
186
|
public
|
171
187
|
def assert_nil(object, message="")
|
172
|
-
|
188
|
+
full_message = build_message(message, <<EOT, object)
|
189
|
+
<?> expected to be nil.
|
190
|
+
EOT
|
191
|
+
assert_block(full_message) { object.nil? }
|
173
192
|
end
|
174
193
|
|
175
194
|
##
|
@@ -369,11 +388,14 @@ EOT
|
|
369
388
|
end
|
370
389
|
end
|
371
390
|
|
372
|
-
UncaughtThrow = {
|
373
|
-
|
391
|
+
UncaughtThrow = {
|
392
|
+
NameError => /^uncaught throw \`(.+)\'$/,
|
393
|
+
ArgumentError => /^uncaught throw (.+)$/,
|
394
|
+
ThreadError => /^uncaught throw \`(.+)\' in thread /
|
395
|
+
} #`
|
374
396
|
|
375
397
|
##
|
376
|
-
# Passes if the block throws +
|
398
|
+
# Passes if the block throws +expected_object+
|
377
399
|
#
|
378
400
|
# Example:
|
379
401
|
# assert_throws :done do
|
@@ -381,23 +403,35 @@ EOT
|
|
381
403
|
# end
|
382
404
|
|
383
405
|
public
|
384
|
-
def assert_throws(
|
406
|
+
def assert_throws(expected_object, message="", &proc)
|
385
407
|
_wrap_assertion do
|
386
|
-
|
387
|
-
|
408
|
+
begin
|
409
|
+
catch([]) {}
|
410
|
+
rescue TypeError
|
411
|
+
assert_instance_of(Symbol, expected_object,
|
412
|
+
"assert_throws expects the symbol that should be thrown for its first argument")
|
413
|
+
end
|
414
|
+
assert_block("Should have passed a block to assert_throws.") do
|
415
|
+
block_given?
|
416
|
+
end
|
388
417
|
caught = true
|
389
418
|
begin
|
390
|
-
catch(
|
419
|
+
catch(expected_object) do
|
391
420
|
proc.call
|
392
421
|
caught = false
|
393
422
|
end
|
394
|
-
full_message = build_message(message,
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
423
|
+
full_message = build_message(message,
|
424
|
+
"<?> should have been thrown.",
|
425
|
+
expected_object)
|
426
|
+
assert_block(full_message) {caught}
|
427
|
+
rescue NameError, ArgumentError, ThreadError => error
|
428
|
+
raise unless UncaughtThrow[error.class] =~ error.message
|
429
|
+
tag = $1
|
430
|
+
tag = tag[1..-1].intern if tag[0, 1] == ":"
|
431
|
+
full_message = build_message(message,
|
432
|
+
"<?> expected to be thrown but\n" +
|
433
|
+
"<?> was thrown.",
|
434
|
+
expected_object, tag)
|
401
435
|
flunk(full_message)
|
402
436
|
end
|
403
437
|
end
|
@@ -417,11 +451,13 @@ EOT
|
|
417
451
|
assert(block_given?, "Should have passed a block to assert_nothing_thrown")
|
418
452
|
begin
|
419
453
|
proc.call
|
420
|
-
rescue NameError, ThreadError => error
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
full_message = build_message(message,
|
454
|
+
rescue NameError, ArgumentError, ThreadError => error
|
455
|
+
raise unless UncaughtThrow[error.class] =~ error.message
|
456
|
+
tag = $1
|
457
|
+
tag = tag[1..-1].intern if tag[0, 1] == ":"
|
458
|
+
full_message = build_message(message,
|
459
|
+
"<?> was thrown when nothing was expected",
|
460
|
+
tag)
|
425
461
|
flunk(full_message)
|
426
462
|
end
|
427
463
|
assert(true, "Expected nothing to be thrown")
|
@@ -475,6 +511,54 @@ EOT
|
|
475
511
|
end
|
476
512
|
end
|
477
513
|
|
514
|
+
##
|
515
|
+
# Passes if +actual+ is a boolean value.
|
516
|
+
#
|
517
|
+
# Example:
|
518
|
+
# assert_boolean(true) # -> pass
|
519
|
+
# assert_boolean(nil) # -> fail
|
520
|
+
def assert_boolean(actual, message=nil)
|
521
|
+
_wrap_assertion do
|
522
|
+
assert_block(build_message(message,
|
523
|
+
"<true> or <false> expected but was\n<?>",
|
524
|
+
actual)) do
|
525
|
+
[true, false].include?(actual)
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
##
|
531
|
+
# Passes if +actual+ is true.
|
532
|
+
#
|
533
|
+
# Example:
|
534
|
+
# assert_true(true) # -> pass
|
535
|
+
# assert_true(:true) # -> fail
|
536
|
+
def assert_true(actual, message=nil)
|
537
|
+
_wrap_assertion do
|
538
|
+
assert_block(build_message(message,
|
539
|
+
"<true> expected but was\n<?>",
|
540
|
+
actual)) do
|
541
|
+
actual == true
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
546
|
+
##
|
547
|
+
# Passes if +actual+ is false.
|
548
|
+
#
|
549
|
+
# Example:
|
550
|
+
# assert_false(false) # -> pass
|
551
|
+
# assert_false(nil) # -> fail
|
552
|
+
def assert_false(actual, message=nil)
|
553
|
+
_wrap_assertion do
|
554
|
+
assert_block(build_message(message,
|
555
|
+
"<false> expected but was\n<?>",
|
556
|
+
actual)) do
|
557
|
+
actual == false
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
478
562
|
##
|
479
563
|
# Builds a failure message. +head+ is added before the +template+ and
|
480
564
|
# +arguments+ replaces the '?'s positionally in the template.
|
@@ -524,6 +608,37 @@ EOT
|
|
524
608
|
@use_pp = true
|
525
609
|
class << self
|
526
610
|
attr_accessor :use_pp
|
611
|
+
|
612
|
+
def literal(value)
|
613
|
+
Literal.new(value)
|
614
|
+
end
|
615
|
+
|
616
|
+
def delayed_literal(&block)
|
617
|
+
DelayedLiteral.new(block)
|
618
|
+
end
|
619
|
+
|
620
|
+
def convert(object)
|
621
|
+
case object
|
622
|
+
when Exception
|
623
|
+
<<EOM.chop
|
624
|
+
Class: <#{convert(object.class)}>
|
625
|
+
Message: <#{convert(object.message)}>
|
626
|
+
---Backtrace---
|
627
|
+
#{Util::BacktraceFilter.filter_backtrace(object.backtrace).join("\n")}
|
628
|
+
---------------
|
629
|
+
EOM
|
630
|
+
else
|
631
|
+
if use_pp
|
632
|
+
begin
|
633
|
+
require 'pp' unless defined?(PP)
|
634
|
+
return PP.pp(object, '').chomp
|
635
|
+
rescue LoadError
|
636
|
+
self.use_pp = false
|
637
|
+
end
|
638
|
+
end
|
639
|
+
object.inspect
|
640
|
+
end
|
641
|
+
end
|
527
642
|
end
|
528
643
|
|
529
644
|
class Literal
|
@@ -536,6 +651,16 @@ EOT
|
|
536
651
|
end
|
537
652
|
end
|
538
653
|
|
654
|
+
class DelayedLiteral
|
655
|
+
def initialize(value)
|
656
|
+
@value = value
|
657
|
+
end
|
658
|
+
|
659
|
+
def inspect
|
660
|
+
@value.call.to_s
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
539
664
|
class Template
|
540
665
|
def self.create(string)
|
541
666
|
parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : [])
|
@@ -556,10 +681,6 @@ EOT
|
|
556
681
|
end
|
557
682
|
end
|
558
683
|
|
559
|
-
def self.literal(value)
|
560
|
-
Literal.new(value)
|
561
|
-
end
|
562
|
-
|
563
684
|
include Util::BacktraceFilter
|
564
685
|
|
565
686
|
def initialize(head, template_string, parameters)
|
@@ -569,28 +690,7 @@ EOT
|
|
569
690
|
end
|
570
691
|
|
571
692
|
def convert(object)
|
572
|
-
|
573
|
-
when Exception
|
574
|
-
<<EOM.chop
|
575
|
-
Class: <#{convert(object.class)}>
|
576
|
-
Message: <#{convert(object.message)}>
|
577
|
-
---Backtrace---
|
578
|
-
#{filter_backtrace(object.backtrace).join("\n")}
|
579
|
-
---------------
|
580
|
-
EOM
|
581
|
-
else
|
582
|
-
if(self.class.use_pp)
|
583
|
-
begin
|
584
|
-
require 'pp'
|
585
|
-
rescue LoadError
|
586
|
-
self.class.use_pp = false
|
587
|
-
return object.inspect
|
588
|
-
end unless(defined?(PP))
|
589
|
-
PP.pp(object, '').chomp
|
590
|
-
else
|
591
|
-
object.inspect
|
592
|
-
end
|
593
|
-
end
|
693
|
+
self.class.convert(object)
|
594
694
|
end
|
595
695
|
|
596
696
|
def template
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Test
|
2
|
+
module Unit
|
3
|
+
module Attribute
|
4
|
+
class << self
|
5
|
+
def included(base)
|
6
|
+
base.extend(BaseClassMethods)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module BaseClassMethods
|
12
|
+
def attributes_table
|
13
|
+
{}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def method_added(name)
|
19
|
+
super
|
20
|
+
return unless defined?(@current_attributes)
|
21
|
+
|
22
|
+
attributes = {}
|
23
|
+
kept_attributes = {}
|
24
|
+
@current_attributes.each do |attribute_name, attribute|
|
25
|
+
attributes[attribute_name] = attribute[:value]
|
26
|
+
kept_attributes[attribute_name] = attribute if attribute[:keep]
|
27
|
+
end
|
28
|
+
set_attributes(name, attributes)
|
29
|
+
@current_attributes = kept_attributes
|
30
|
+
end
|
31
|
+
|
32
|
+
def attribute(name, value, options={}, *method_names)
|
33
|
+
unless options.is_a?(Hash)
|
34
|
+
method_names << options
|
35
|
+
options = {}
|
36
|
+
end
|
37
|
+
@current_attributes ||= {}
|
38
|
+
if method_names.empty?
|
39
|
+
@current_attributes[name] = options.merge(:value => value)
|
40
|
+
else
|
41
|
+
method_names.each do |method_name|
|
42
|
+
set_attributes(method_name, {name => value})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def attributes_table
|
48
|
+
@attributes_table ||= {}
|
49
|
+
super.merge(@attributes_table)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_attributes(method_name, new_attributes)
|
53
|
+
return if new_attributes.empty?
|
54
|
+
method_name = normalize_method_name(method_name)
|
55
|
+
@attributes_table ||= {}
|
56
|
+
@attributes_table[method_name] ||= {}
|
57
|
+
current_attributes = @attributes_table[method_name]
|
58
|
+
new_attributes.each do |key, value|
|
59
|
+
key = normalize_attribute_name(key)
|
60
|
+
observers = attribute_observers(key) || []
|
61
|
+
observers.each do |observer|
|
62
|
+
observer.call(self,
|
63
|
+
key,
|
64
|
+
(attributes(method_name) || {})[key],
|
65
|
+
value,
|
66
|
+
method_name)
|
67
|
+
end
|
68
|
+
current_attributes[key] = value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def attributes(method_name)
|
73
|
+
method_name = normalize_method_name(method_name)
|
74
|
+
attributes = attributes_table[method_name]
|
75
|
+
ancestors[1..-1].each do |ancestor|
|
76
|
+
if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute
|
77
|
+
parent_attributes = ancestor.attributes(method_name)
|
78
|
+
if attributes
|
79
|
+
attributes = (parent_attributes || {}).merge(attributes)
|
80
|
+
else
|
81
|
+
attributes = parent_attributes
|
82
|
+
end
|
83
|
+
break
|
84
|
+
end
|
85
|
+
end
|
86
|
+
attributes
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_attribute(method_name, attribute_name)
|
90
|
+
attribute_name = normalize_attribute_name(attribute_name)
|
91
|
+
(attributes(method_name) || {})[attribute_name]
|
92
|
+
end
|
93
|
+
|
94
|
+
@@attribute_observers = {}
|
95
|
+
def register_attribute_observer(attribute_name, observer=Proc.new)
|
96
|
+
attribute_name = normalize_attribute_name(attribute_name)
|
97
|
+
@@attribute_observers[attribute_name] ||= []
|
98
|
+
@@attribute_observers[attribute_name] << observer
|
99
|
+
end
|
100
|
+
|
101
|
+
def attribute_observers(attribute_name)
|
102
|
+
attribute_name = normalize_attribute_name(attribute_name)
|
103
|
+
@@attribute_observers[attribute_name]
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def normalize_attribute_name(name)
|
108
|
+
name.to_s
|
109
|
+
end
|
110
|
+
|
111
|
+
def normalize_method_name(name)
|
112
|
+
name.to_s
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def attributes
|
117
|
+
self.class.attributes(@method_name) || {}
|
118
|
+
end
|
119
|
+
|
120
|
+
def [](name)
|
121
|
+
self.class.get_attribute(@method_name, name)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|