test-unit 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,26 @@
1
+ === 2.3.0 / 2011-04-17
2
+
3
+ * 13 enhancements
4
+ * improve Hash key sorting for diff.
5
+ * [#28928] support any characters in declarative style description.
6
+ [Daniel Berger]
7
+ * add Error#location and make #backtrace deprecated.
8
+ * make TestCase#passed? public.
9
+ * add result finished and pass assertion notifications.
10
+ * add TestSuite#passed? public.
11
+ * add XML test runner.
12
+ * add --output-file-descriptor option.
13
+ * measure elapsed time for each test.
14
+ * add --collector option.
15
+ * support test driven test.
16
+ [Haruka Yoshihara]
17
+ * add cleanup hook it runs between after test and before teardown.
18
+ * support recursive collection sort for diff.
19
+
20
+ * Thanks
21
+ * Daniel Berger
22
+ * Haruka Yoshihara
23
+
1
24
  === 2.2.0 / 2011-02-14
2
25
 
3
26
  * 22 enhancements
@@ -6,7 +29,7 @@
6
29
  * [test-unit-users-en:00035] make GC-able finished tests.
7
30
  [Daniel Berger]
8
31
  * use also COLUMNS environment variable to guess terminal width.
9
- * make delta for assert_in_delta optiona.
32
+ * make delta for assert_in_delta optional.
10
33
  [Nobuyoshi Nakada]
11
34
  * add assert_not_respond_to.
12
35
  [Nobuyoshi Nakada]
@@ -15,6 +15,7 @@ html/famfamfam-logo.png
15
15
  html/favicon.ico
16
16
  html/favicon.png
17
17
  html/favicon.svg
18
+ html/github-logo.png
18
19
  html/heading-mark.png
19
20
  html/heading-mark.svg
20
21
  html/index.html
@@ -44,8 +45,10 @@ lib/test/unit/collector/descendant.rb
44
45
  lib/test/unit/collector/dir.rb
45
46
  lib/test/unit/collector/load.rb
46
47
  lib/test/unit/collector/objectspace.rb
48
+ lib/test/unit/collector/xml.rb
47
49
  lib/test/unit/color-scheme.rb
48
50
  lib/test/unit/color.rb
51
+ lib/test/unit/data.rb
49
52
  lib/test/unit/diff.rb
50
53
  lib/test/unit/error.rb
51
54
  lib/test/unit/exceptionhandler.rb
@@ -58,9 +61,11 @@ lib/test/unit/priority.rb
58
61
  lib/test/unit/runner/console.rb
59
62
  lib/test/unit/runner/emacs.rb
60
63
  lib/test/unit/runner/tap.rb
64
+ lib/test/unit/runner/xml.rb
61
65
  lib/test/unit/testcase.rb
62
66
  lib/test/unit/testresult.rb
63
67
  lib/test/unit/testsuite.rb
68
+ lib/test/unit/testsuitecreator.rb
64
69
  lib/test/unit/ui/console/outputlevel.rb
65
70
  lib/test/unit/ui/console/testrunner.rb
66
71
  lib/test/unit/ui/emacs/testrunner.rb
@@ -68,6 +73,7 @@ lib/test/unit/ui/tap/testrunner.rb
68
73
  lib/test/unit/ui/testrunner.rb
69
74
  lib/test/unit/ui/testrunnermediator.rb
70
75
  lib/test/unit/ui/testrunnerutilities.rb
76
+ lib/test/unit/ui/xml/testrunner.rb
71
77
  lib/test/unit/util/backtracefilter.rb
72
78
  lib/test/unit/util/method-owner-finder.rb
73
79
  lib/test/unit/util/observable.rb
@@ -83,11 +89,13 @@ test/collector/test-descendant.rb
83
89
  test/collector/test-load.rb
84
90
  test/collector/test_dir.rb
85
91
  test/collector/test_objectspace.rb
92
+ test/fixtures/plus.csv
86
93
  test/run-test.rb
87
94
  test/test-assertions.rb
88
95
  test/test-attribute.rb
89
96
  test/test-color-scheme.rb
90
97
  test/test-color.rb
98
+ test/test-data.rb
91
99
  test/test-diff.rb
92
100
  test/test-emacs-runner.rb
93
101
  test/test-fixture.rb
data/README.txt CHANGED
@@ -50,6 +50,7 @@ Ruby license and PSF license.
50
50
  === Active
51
51
 
52
52
  * Kouhei Sutou: The current maintainer
53
+ * Haruka Yoshihara: Data driven test supports.
53
54
 
54
55
  === Inactive
55
56
 
data/Rakefile CHANGED
@@ -46,8 +46,7 @@ end
46
46
  desc "Tag the current revision."
47
47
  task :tag do
48
48
  message = "Released Test::Unit #{version}!"
49
- base = "svn+ssh://#{ENV['USER']}@rubyforge.org/var/svn/test-unit/"
50
- sh 'svn', 'copy', '-m', message, "#{base}trunk", "#{base}tags/#{version}"
49
+ sh 'git', 'tag', '-a', version, '-m', message
51
50
  end
52
51
 
53
52
  # vim: syntax=Ruby
Binary file
@@ -78,13 +78,18 @@ require "test/unit"</pre>
78
78
  </p>
79
79
  <h3 id="test-unit-latest">test-unit: The latest release</h3>
80
80
  <p>
81
- 2.2.0 is the latest release. It had been released at 2011-02-14.
81
+ 2.3.0 is the latest release. It had been released at 2011-04-17.
82
82
  </p>
83
83
  <h3 id="test-unit-install">test-unit: Install</h3>
84
84
  <p>
85
85
  Install:
86
86
  <pre class="command">% sudo gem install test-unit</pre>
87
87
  </p>
88
+ <p>
89
+ Usage:
90
+ <pre class="code">gem "test-unit"
91
+ require "test/unit"</pre>
92
+ </p>
88
93
 
89
94
  <h2 id="test-unit-full">test-unit-full</h2>
90
95
  <p>
@@ -125,7 +130,7 @@ require "test/unit"</pre>
125
130
  </p>
126
131
  <h3 id="test-unit-notify-latest">test-unit-notify: The latest release</h3>
127
132
  <p>
128
- 0.2.1 is the latest release. It had been released at 2011-02-10.
133
+ 0.3.0 is the latest release. It had been released at 2011-04-15.
129
134
  </p>
130
135
  <h3 id="test-unit-notify-install">test-unit-notify: Install</h3>
131
136
  <p>
@@ -228,23 +233,24 @@ require "test/unit"</pre>
228
233
 
229
234
  <h3 id="repository">Repositories</h3>
230
235
  <p>
231
- Test::Unit uses Subverseion repository on RubyForge. Here are a list to checkout each package.
232
- </p>
233
- <dl>
234
- <dt>test-unit</dt>
235
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/trunk test-unit</pre></dd>
236
- <dt>test-unit-full</dt>
237
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-full/trunk test-unit-full</pre></dd>
238
- <dt>test-unit-notify</dt>
239
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-notify/trunk test-unit-notify</pre></dd>
240
- <dt>test-unit-rr</dt>
241
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-rr/trunk test-unit-rr</pre></dd>
242
- <dt>test-unit-runner-gtk2</dt>
243
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-runner-gtk2/trunk test-unit-runner-gtk2</pre></dd>
244
- <dt>test-unit-runner-tk</dt>
245
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-runner-tk/trunk test-unit-runner-tk</pre></dd>
246
- <dt>test-unit-runner-fox</dt>
247
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-runner-fox/trunk test-unit-runner-fox</pre></dd>
236
+ Test::Unit uses <a href="https://github.com/test-unit/">git repository on GitHub</a>. Here is a list to get each source code.
237
+ </p>
238
+ <dt><a href="https://github.com/test-unit/test-unit/">test-unit</a></dt>
239
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit.git</pre></dd>
240
+ <dt><a href="https://github.com/test-unit/test-unit-full/">test-unit-full</a></dt>
241
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-full.git</pre></dd>
242
+ <dt><a href="https://github.com/test-unit/test-unit-notify/">test-unit-notify</a></dt>
243
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-notify.git</pre></dd>
244
+ <dt><a href="https://github.com/test-unit/test-unit-rr/">test-unit-rr</a></dt>
245
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-rr.git</pre></dd>
246
+ <dt><a href="https://github.com/test-unit/test-unit-capybara/">test-unit-capybara</a></dt>
247
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-capybara.git</pre></dd>
248
+ <dt><a href="https://github.com/test-unit/test-unit-runner-gtk2/">test-unit-runner-gtk2</a></dt>
249
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-runner-gtk2.git</pre></dd>
250
+ <dt><a href="https://github.com/test-unit/test-unit-runner-tk/">test-unit-runner-tk</a></dt>
251
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-runner-tk.git</pre></dd>
252
+ <dt><a href="https://github.com/test-unit/test-unit-runner-fox/">test-unit-runner-fox</a></dt>
253
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-runner-fox.git</pre></dd>
248
254
  </dl>
249
255
  </div>
250
256
 
@@ -265,6 +271,11 @@ require "test/unit"</pre>
265
271
  <img src="rubyforge.png" width="120" height="24" border="0" alt="Test::Unit is hosted on RubyForge.org." />
266
272
  </a>
267
273
  </p>
274
+ <p id="sponsor-github">
275
+ <a href="https://github.com/test-unit/">
276
+ <img src="github-logo.png" width="100" height="45" border="0" alt="GitHub's git repositories are used." />
277
+ </a>
278
+ </p>
268
279
  <p id="sponsor-tango">
269
280
  <a href="http://tango.freedesktop.org/">
270
281
  <img width="120" height="53" border="0" alt="Tango Desktop Project's icons are used." src="tango-logo.png" />
@@ -91,13 +91,18 @@ require "test/unit"</pre>
91
91
  </p>
92
92
  <h3 id="test-unit-latest">test-unit最新リリース</h3>
93
93
  <p>
94
- 2011-02-14にリリースされた2.2.0が最新リリースです。
94
+ 2011-04-17にリリースされた2.3.0が最新リリースです。
95
95
  </p>
96
96
  <h3 id="test-unit-install">test-unitのインストール</h3>
97
97
  <p>
98
98
  インストール:
99
99
  <pre class="command">% sudo gem install test-unit</pre>
100
100
  </p>
101
+ <p>
102
+ 使い方:
103
+ <pre class="code">gem "test-unit"
104
+ require "test/unit"</pre>
105
+ </p>
101
106
 
102
107
  <h2 id="test-unit-full">test-unit-full</h2>
103
108
  <p>
@@ -137,7 +142,7 @@ require "test/unit"</pre>
137
142
  </p>
138
143
  <h3 id="test-unit-notify-latest">test-unit-notify最新リリース</h3>
139
144
  <p>
140
- 2011-02-10にリリースされた0.2.1が最新リリースです。
145
+ 2011-04-15にリリースされた0.3.0が最新リリースです。
141
146
  </p>
142
147
  <h3 id="test-unit-notify-install">test-unit-notifyのインストール</h3>
143
148
  <p>
@@ -242,23 +247,25 @@ require "test/unit"</pre>
242
247
 
243
248
  <h3 id="repository">リポジトリ</h3>
244
249
  <p>
245
- RubyForge上のSubversionリポジトリを利用しています。チェックアウト方法は以下の通りです。
250
+ <a href="https://github.com/test-unit/">GitHub上のgitリポジトリ</a>を利用しています。ソースコードは以下のように取得できます。
246
251
  </p>
247
252
  <dl>
248
- <dt>test-unit</dt>
249
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/trunk test-unit</pre></dd>
250
- <dt>test-unit-full</dt>
251
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-full/trunk test-unit-full</pre></dd>
252
- <dt>test-unit-notify</dt>
253
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-notify/trunk test-unit-notify</pre></dd>
254
- <dt>test-unit-rr</dt>
255
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-rr/trunk test-unit-rr</pre></dd>
256
- <dt>test-unit-runner-gtk2</dt>
257
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-runner-gtk2/trunk test-unit-runner-gtk2</pre></dd>
258
- <dt>test-unit-runner-tk</dt>
259
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-runner-tk/trunk test-unit-runner-tk</pre></dd>
260
- <dt>test-unit-runner-fox</dt>
261
- <dd><pre class="command">% svn co http://test-unit.rubyforge.org/svn/extensions/test-unit-runner-fox/trunk test-unit-runner-fox</pre></dd>
253
+ <dt><a href="https://github.com/test-unit/test-unit/">test-unit</a></dt>
254
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit.git</pre></dd>
255
+ <dt><a href="https://github.com/test-unit/test-unit-full/">test-unit-full</a></dt>
256
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-full.git</pre></dd>
257
+ <dt><a href="https://github.com/test-unit/test-unit-notify/">test-unit-notify</a></dt>
258
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-notify.git</pre></dd>
259
+ <dt><a href="https://github.com/test-unit/test-unit-rr/">test-unit-rr</a></dt>
260
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-rr.git</pre></dd>
261
+ <dt><a href="https://github.com/test-unit/test-unit-capybara/">test-unit-capybara</a></dt>
262
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-capybara.git</pre></dd>
263
+ <dt><a href="https://github.com/test-unit/test-unit-runner-gtk2/">test-unit-runner-gtk2</a></dt>
264
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-runner-gtk2.git</pre></dd>
265
+ <dt><a href="https://github.com/test-unit/test-unit-runner-tk/">test-unit-runner-tk</a></dt>
266
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-runner-tk.git</pre></dd>
267
+ <dt><a href="https://github.com/test-unit/test-unit-runner-fox/">test-unit-runner-fox</a></dt>
268
+ <dd><pre class="command">% git clone https://github.com/test-unit/test-unit-runner-fox.git</pre></dd>
262
269
  </dl>
263
270
  </div>
264
271
 
@@ -279,6 +286,11 @@ require "test/unit"</pre>
279
286
  <img src="rubyforge.png" width="120" height="24" border="0" alt="ラングバプロジェクトはRubyForge.orgにホスティングしてもらっています。" />
280
287
  </a>
281
288
  </p>
289
+ <p id="sponsor-github">
290
+ <a href="https://github.com/milter-manager/">
291
+ <img src="github-logo.png" width="100" height="45" border="0" alt="GitHubの提供するgitリポジトリを利用しています。" />
292
+ </a>
293
+ </p>
282
294
  <p id="sponsor-tango">
283
295
  <a href="http://tango.freedesktop.org/">
284
296
  <img width="120" height="53" border="0" alt="Tango Desktop Projectのアイコンを利用しています。" src="tango-logo.png" />
@@ -244,17 +244,24 @@ div.sponsors p#sponsor-rubyforge
244
244
  right: 50px;
245
245
  }
246
246
 
247
- div.sponsors p#sponsor-tango
247
+ div.sponsors p#sponsor-github
248
248
  {
249
249
  position: absolute;
250
250
  top: 50px;
251
251
  right: 50px;
252
252
  }
253
253
 
254
+ div.sponsors p#sponsor-tango
255
+ {
256
+ position: absolute;
257
+ top: 105px;
258
+ right: 50px;
259
+ }
260
+
254
261
  div.sponsors p#sponsor-famfamfam
255
262
  {
256
263
  position: absolute;
257
- top: 118px;
264
+ top: 168px;
258
265
  right: 50px;
259
266
  padding-bottom: 50px;
260
267
  }
@@ -1507,23 +1507,50 @@ Message: <#{convert(object.message)}>
1507
1507
  ---------------
1508
1508
  EOM
1509
1509
  else
1510
+ inspector = Inspector.new(object)
1510
1511
  if use_pp
1511
1512
  begin
1512
1513
  require 'pp' unless defined?(PP)
1513
- if HashInspector.target?(object)
1514
- pp_target = HashInspector.new(object)
1515
- else
1516
- pp_target = object
1517
- end
1518
1514
  begin
1519
- return PP.pp(pp_target, '').chomp
1515
+ return PP.pp(inspector, '').chomp
1520
1516
  rescue NameError
1521
1517
  end
1522
1518
  rescue LoadError
1523
1519
  self.use_pp = false
1524
1520
  end
1525
1521
  end
1526
- object.inspect
1522
+ inspector.inspect
1523
+ end
1524
+ end
1525
+ end
1526
+
1527
+ class Inspector
1528
+ def initialize(object)
1529
+ @object = object
1530
+ @inspect_target = inspect_target
1531
+ end
1532
+
1533
+ alias_method :native_inspect, :inspect
1534
+ def inspect
1535
+ @inspect_target.inspect
1536
+ end
1537
+
1538
+ def pretty_print(q)
1539
+ @inspect_target.pretty_print(q)
1540
+ end
1541
+
1542
+ def pretty_print_cycle(q)
1543
+ @inspect_target.pretty_print_cycle(q)
1544
+ end
1545
+
1546
+ private
1547
+ def inspect_target
1548
+ if HashInspector.target?(@object)
1549
+ HashInspector.new(@object)
1550
+ elsif ArrayInspector.target?(@object)
1551
+ ArrayInspector.new(@object)
1552
+ else
1553
+ @object
1527
1554
  end
1528
1555
  end
1529
1556
  end
@@ -1533,14 +1560,6 @@ EOM
1533
1560
  def target?(object)
1534
1561
  object.is_a?(Hash) or object == ENV
1535
1562
  end
1536
-
1537
- def normalize(object)
1538
- if target?(object)
1539
- new(object)
1540
- else
1541
- object
1542
- end
1543
- end
1544
1563
  end
1545
1564
 
1546
1565
  def initialize(hash)
@@ -1567,13 +1586,52 @@ EOM
1567
1586
  end
1568
1587
 
1569
1588
  def pretty_print_cycle(q)
1570
- q.text(@hash.empty? ? '{}' : '{...}')
1589
+ @hash.pretty_print_cycle(q)
1571
1590
  end
1572
1591
 
1573
1592
  def each_pair
1574
- @hash.keys.sort.each do |key|
1575
- yield(self.class.normalize(key),
1576
- self.class.normalize(@hash[key]))
1593
+ keys = @hash.keys
1594
+ begin
1595
+ keys = keys.sort # FIXME: more cleverly
1596
+ rescue ArgumentError
1597
+ end
1598
+ keys.each do |key|
1599
+ yield(Inspector.new(key),
1600
+ Inspector.new(@hash[key]))
1601
+ end
1602
+ end
1603
+ end
1604
+
1605
+ class ArrayInspector
1606
+ class << self
1607
+ def target?(object)
1608
+ object.is_a?(Array)
1609
+ end
1610
+ end
1611
+
1612
+ def initialize(array)
1613
+ @array = array
1614
+ end
1615
+
1616
+ def inspect
1617
+ @array.inspect
1618
+ end
1619
+
1620
+ def pretty_print(q)
1621
+ q.group(1, '[', ']') do
1622
+ q.seplist(self) do |v|
1623
+ q.pp(v)
1624
+ end
1625
+ end
1626
+ end
1627
+
1628
+ def pretty_print_cycle(q)
1629
+ @array.pretty_print_cycle(q)
1630
+ end
1631
+
1632
+ def each
1633
+ @array.each do |element|
1634
+ yield(Inspector.new(element))
1577
1635
  end
1578
1636
  end
1579
1637
  end
@@ -1,6 +1,22 @@
1
1
  module Test
2
2
  module Unit
3
3
  module Attribute
4
+ class StringifyKeyHash < Hash
5
+ class << self
6
+ def stringify(object)
7
+ object.to_s
8
+ end
9
+ end
10
+
11
+ def [](key)
12
+ super(self.class.stringify(key))
13
+ end
14
+
15
+ def []=(key, value)
16
+ super(self.class.stringify(key), value)
17
+ end
18
+ end
19
+
4
20
  class << self
5
21
  def included(base)
6
22
  base.extend(BaseClassMethods)
@@ -34,9 +50,8 @@ module Test
34
50
  method_names << options
35
51
  options = {}
36
52
  end
37
- @current_attributes ||= {}
38
53
  if method_names.empty?
39
- @current_attributes[name] = options.merge(:value => value)
54
+ current_attributes[name] = options.merge(:value => value)
40
55
  else
41
56
  method_names.each do |method_name|
42
57
  set_attributes(method_name, {name => value})
@@ -44,23 +59,29 @@ module Test
44
59
  end
45
60
  end
46
61
 
62
+ def current_attributes
63
+ @current_attributes ||= StringifyKeyHash.new
64
+ end
65
+
66
+ def current_attribute(name)
67
+ current_attributes[name] || StringifyKeyHash.new
68
+ end
69
+
47
70
  def attributes_table
48
- @attributes_table ||= {}
71
+ @attributes_table ||= StringifyKeyHash.new
49
72
  super.merge(@attributes_table)
50
73
  end
51
74
 
52
75
  def set_attributes(method_name, new_attributes)
53
76
  return if new_attributes.empty?
54
- method_name = normalize_method_name(method_name)
55
- @attributes_table ||= {}
56
- @attributes_table[method_name] ||= {}
77
+ @attributes_table ||= StringifyKeyHash.new
78
+ @attributes_table[method_name] ||= StringifyKeyHash.new
57
79
  current_attributes = @attributes_table[method_name]
58
80
  new_attributes.each do |key, value|
59
- key = normalize_attribute_name(key)
60
81
  observers = attribute_observers(key) || []
61
82
  observers.each do |observer|
62
83
  observer.call(self,
63
- key,
84
+ StringifyKeyHash.stringify(key),
64
85
  (attributes(method_name) || {})[key],
65
86
  value,
66
87
  method_name)
@@ -70,7 +91,6 @@ module Test
70
91
  end
71
92
 
72
93
  def attributes(method_name)
73
- method_name = normalize_method_name(method_name)
74
94
  attributes = attributes_table[method_name]
75
95
  ancestors[1..-1].each do |ancestor|
76
96
  if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute
@@ -83,42 +103,26 @@ module Test
83
103
  break
84
104
  end
85
105
  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]
106
+ attributes || StringifyKeyHash.new
92
107
  end
93
108
 
94
- @@attribute_observers = {}
109
+ @@attribute_observers = StringifyKeyHash.new
95
110
  def register_attribute_observer(attribute_name, observer=Proc.new)
96
- attribute_name = normalize_attribute_name(attribute_name)
97
111
  @@attribute_observers[attribute_name] ||= []
98
112
  @@attribute_observers[attribute_name] << observer
99
113
  end
100
114
 
101
115
  def attribute_observers(attribute_name)
102
- attribute_name = normalize_attribute_name(attribute_name)
103
116
  @@attribute_observers[attribute_name]
104
117
  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
118
  end
115
119
 
116
120
  def attributes
117
- self.class.attributes(@method_name) || {}
121
+ self.class.attributes(@method_name) || StringifyKeyHash.new
118
122
  end
119
123
 
120
124
  def [](name)
121
- self.class.get_attribute(@method_name, name)
125
+ attributes[name]
122
126
  end
123
127
  end
124
128
  end