omghax-test_rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ === 1.0.0 / 2009-03-12
2
+
3
+ * 1 major enhancement:
4
+
5
+ * Extracted test-rails from ZenTest 3.11.1 into a separate gem.
data/Manifest.txt ADDED
@@ -0,0 +1,21 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/test/rails.rb
6
+ lib/test/rails/controller_test_case.rb
7
+ lib/test/rails/functional_test_case.rb
8
+ lib/test/rails/helper_test_case.rb
9
+ lib/test/rails/ivar_proxy.rb
10
+ lib/test/rails/pp_html_document.rb
11
+ lib/test/rails/rake_tasks.rb
12
+ lib/test/rails/render_tree.rb
13
+ lib/test/rails/test_case.rb
14
+ lib/test/rails/version.rb
15
+ lib/test/rails/view_test_case.rb
16
+ lib/test/zentest_assertions.rb
17
+ test/test_help.rb
18
+ test/test_rails_controller_test_case.rb
19
+ test/test_rails_helper_test_case.rb
20
+ test/test_rails_view_test_case.rb
21
+ test/test_zentest_assertions.rb
data/README.txt ADDED
@@ -0,0 +1,110 @@
1
+ = ZenTest
2
+
3
+ * http://www.zenspider.com/ZSS/Products/ZenTest/
4
+ * http://rubyforge.org/projects/zentest/
5
+ * mailto:ryand-ruby@zenspider.com
6
+
7
+ == DESCRIPTION
8
+
9
+ ZenTest provides 4 different tools and 1 library: zentest, unit_diff,
10
+ autotest, multiruby, and Test::Rails.
11
+
12
+ ZenTest scans your target and unit-test code and writes your missing
13
+ code based on simple naming rules, enabling XP at a much quicker
14
+ pace. ZenTest only works with Ruby and Test::Unit.
15
+
16
+ unit_diff is a command-line filter to diff expected results from
17
+ actual results and allow you to quickly see exactly what is wrong.
18
+
19
+ autotest is a continous testing facility meant to be used during
20
+ development. As soon as you save a file, autotest will run the
21
+ corresponding dependent tests.
22
+
23
+ multiruby runs anything you want on multiple versions of ruby. Great
24
+ for compatibility checking! Use multiruby_setup to manage your
25
+ installed versions.
26
+
27
+ Test::Rails helps you build industrial-strength Rails code.
28
+
29
+ == STRATEGERY
30
+
31
+ There are two strategeries intended for ZenTest: test conformance
32
+ auditing and rapid XP.
33
+
34
+ For auditing, ZenTest provides an excellent means of finding methods
35
+ that have slipped through the testing process. I've run it against my
36
+ own software and found I missed a lot in a well tested
37
+ package. Writing those tests found 4 bugs I had no idea existed.
38
+
39
+ ZenTest can also be used to evaluate generated code and execute your
40
+ tests, allowing for very rapid development of both tests and
41
+ implementation.
42
+
43
+ == FEATURES
44
+
45
+ * Scans your ruby code and tests and generates missing methods for you.
46
+ * Includes a very helpful filter for Test::Unit output called unit_diff.
47
+ * Continually and intelligently test only those files you change with autotest.
48
+ * Test against multiple versions with multiruby.
49
+ * Enhance and automatically audit your rails tests using Test::Rails.
50
+ * Includes a LinuxJournal article on testing with ZenTest written by Pat Eyler.
51
+ * See also: http://blog.zenspider.com/archives/zentest/
52
+ * See also: http://blog.segment7.net/articles/category/zentest
53
+
54
+ == SYNOPSYS
55
+
56
+ ZenTest MyProject.rb TestMyProject.rb > missing.rb
57
+
58
+ ./TestMyProject.rb | unit_diff
59
+
60
+ autotest
61
+
62
+ multiruby_setup mri:svn:current
63
+ multiruby ./TestMyProject.rb
64
+
65
+ (and other stuff for Test::Rails)
66
+
67
+ == REQUIREMENTS
68
+
69
+ * Ruby 1.6+, JRuby 1.1.2+, or rubinius
70
+ * Test::Unit or miniunit
71
+ * Hoe
72
+ * rubygems
73
+ * diff.exe on windoze. Try http://gnuwin32.sourceforge.net/packages.html
74
+
75
+ == INSTALL
76
+
77
+ Using Rubygems:
78
+
79
+ * sudo gem install ZenTest
80
+
81
+ Using Rake:
82
+
83
+ * rake test
84
+ * sudo rake install
85
+
86
+ == LICENSE
87
+
88
+ (The MIT License)
89
+
90
+ Copyright (c) 2001-2006 Ryan Davis, Eric Hodel, Zen Spider Software
91
+
92
+ Permission is hereby granted, free of charge, to any person obtaining
93
+ a copy of this software and associated documentation files (the
94
+ "Software"), to deal in the Software without restriction, including
95
+ without limitation the rights to use, copy, modify, merge, publish,
96
+ distribute, sublicense, and/or sell copies of the Software, and to
97
+ permit persons to whom the Software is furnished to do so, subject to
98
+ the following conditions:
99
+
100
+ The above copyright notice and this permission notice shall be
101
+ included in all copies or substantial portions of the Software.
102
+
103
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
104
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
105
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
106
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
107
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
108
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
109
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
110
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/test/rails/version.rb'
6
+
7
+ Hoe.new('test_rails', Test::Rails::VERSION::STRING) do |test_rails|
8
+ test_rails.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
9
+ test_rails.developer('Eric Hodel', 'drbrain@segment7.net')
10
+ test_rails.developer('Dray Lacy', 'dray@izea.com')
11
+ end
12
+
13
+ # vim: syntax=Ruby
@@ -0,0 +1,382 @@
1
+ ##
2
+ # ControllerTestCase allows controllers to be tested independent of their
3
+ # views.
4
+ #
5
+ # = Features
6
+ #
7
+ # * ActionMailer is already set up for you.
8
+ # * The session and flash accessors work on both sides of get/post/etc.
9
+ # * Optional automatic auditing for missing assert_assigns. See
10
+ # util_audit_assert_assigned
11
+ #
12
+ # = Naming
13
+ #
14
+ # The test class must be named after your controller class name, so if
15
+ # you're testing actions for the +RouteController+ you would name your
16
+ # test case +RouteControllerTest+.
17
+ #
18
+ # The test names should be in the form of +test_action_edgecase+ where
19
+ # 'action' corresponds to the name of the controller action, and
20
+ # 'edgecase' describes the scenario you are testing.
21
+ #
22
+ # If you are testing an action named 'show' your test should be named
23
+ # +test_show+. If your action behaves differently depending upon its
24
+ # arguments then you can make the test name descriptive like
25
+ # +test_show_photos+ and +test_show_no_photos+.
26
+ #
27
+ # = Examples
28
+ #
29
+ # == Typical Controller Test
30
+ #
31
+ # class RouteControllerTest < Test::Rails::ControllerTestCase
32
+ #
33
+ # fixtures :users, :routes, :points, :photos
34
+ #
35
+ # def test_delete
36
+ # # Store current count
37
+ # count = Route.count
38
+ # # Set up our environment
39
+ # session[:username] = users(:herbert).username
40
+ #
41
+ # # perform the delete action
42
+ # get :delete, :id => routes(:work).id
43
+ #
44
+ # # Assert we got a 200
45
+ # assert_response :success
46
+ # # Assert controller deleted route
47
+ # assert_equal count-1, Route.count
48
+ # # Ensure that @action_title is set properly
49
+ # assert_assigned :action_title, "Deleting \"#{routes(:work).name}\""
50
+ # # Ensure that @route is set properly
51
+ # assert_assigned :route, routes(:work)
52
+ # end
53
+ #
54
+ # end
55
+ #
56
+ # == ActionMailer Test
57
+ #
58
+ # class ApplicationController < ActionController::Base
59
+ #
60
+ # ##
61
+ # # Send an email when we get an unhandled exception.
62
+ #
63
+ # def log_error(exception)
64
+ # case exception
65
+ # when ::ActionController::RoutingError,
66
+ # ::ActionController::UnknownAction,
67
+ # ::ActiveRecord::RecordNotFound then
68
+ # # ignore
69
+ # else
70
+ # unless RAILS_ENV == 'development' then
71
+ # Email.deliver_error exception, params, session, @request.env
72
+ # end
73
+ # end
74
+ # end
75
+ #
76
+ # end
77
+ #
78
+ # ##
79
+ # # Dummy Controller just for testing.
80
+ #
81
+ # class DummyController < ApplicationController
82
+ #
83
+ # def error
84
+ # # Simulate a bug in our application
85
+ # raise RuntimeError
86
+ # end
87
+ #
88
+ # end
89
+ #
90
+ # class DummyControllerTest < Test::Rails::ControllerTestCase
91
+ #
92
+ # def test_error_email
93
+ # # The rescue_action added by ControllerTestCase needs to be removed so
94
+ # # that exceptions fall through to the real error handler
95
+ # @controller.class.send :remove_method, :rescue_action
96
+ #
97
+ # # Fire off a request
98
+ # get :error
99
+ #
100
+ # # We should get a 500
101
+ # assert_response 500
102
+ #
103
+ # # And one delivered email
104
+ # assert_equal 1, @deliveries.length, 'error email sent'
105
+ # end
106
+ #
107
+ # end
108
+ #
109
+ #--
110
+ # TODO: Ensure that assert_tag doesn't work
111
+ # TODO: Cookie input.
112
+
113
+ class Test::Rails::ControllerTestCase < Test::Rails::FunctionalTestCase
114
+
115
+ self.use_transactional_fixtures = true
116
+ self.use_instantiated_fixtures = false
117
+
118
+ NOTHING = Object.new # :nodoc:
119
+
120
+ DEFAULT_ASSIGNS = %w[
121
+ _cookies _flash _headers _params _request _response _session
122
+
123
+ cookies flash headers params request response session
124
+
125
+ action_name
126
+ before_filter_chain_aborted
127
+ db_rt_after_render
128
+ db_rt_before_render
129
+ ignore_missing_templates
130
+ loggedin_user
131
+ logger
132
+ rendering_runtime
133
+ request_origin
134
+ template
135
+ template_class
136
+ template_root
137
+ url
138
+ user
139
+ variables_added
140
+ ]
141
+
142
+ def setup
143
+ return if self.class == Test::Rails::ControllerTestCase
144
+
145
+ @controller_class_name ||= self.class.name.sub 'Test', ''
146
+
147
+ super
148
+
149
+ @controller_class.send(:define_method, :rescue_action) { |e| raise e }
150
+
151
+ @deliveries = []
152
+ ActionMailer::Base.deliveries = @deliveries
153
+
154
+ # used by util_audit_assert_assigns
155
+ @assigns_asserted = []
156
+ @assigns_ignored ||= [] # untested assigns to ignore
157
+ end
158
+
159
+ ##
160
+ # Excutes the request +action+ with +params+.
161
+ #
162
+ # See also: get, post, put, delete, head, xml_http_request
163
+
164
+ def process(action, parameters = nil)
165
+ parameters ||= {}
166
+
167
+ @request.recycle!
168
+ @request.env['REQUEST_METHOD'] ||= 'GET'
169
+ @request.action = action.to_s
170
+
171
+ @request.assign_parameters @controller_class.controller_path, action.to_s,
172
+ parameters
173
+
174
+ build_request_uri action, parameters
175
+
176
+ @controller.process @request, @response
177
+ end
178
+
179
+ ##
180
+ # Performs a GET request on +action+ with +params+.
181
+
182
+ def get(action, parameters = nil)
183
+ @request.env['REQUEST_METHOD'] = 'GET'
184
+ process action, parameters
185
+ end
186
+
187
+ ##
188
+ # Performs a HEAD request on +action+ with +params+.
189
+
190
+ def head(action, parameters = nil)
191
+ @request.env['REQUEST_METHOD'] = 'HEAD'
192
+ process action, parameters
193
+ end
194
+
195
+ ##
196
+ # Performs a POST request on +action+ with +params+.
197
+
198
+ def post(action, parameters = nil)
199
+ @request.env['REQUEST_METHOD'] = 'POST'
200
+ process action, parameters
201
+ end
202
+
203
+ ##
204
+ # Performs a PUT request on +action+ with +params+.
205
+
206
+ def put(action, parameters = nil)
207
+ @request.env['REQUEST_METHOD'] = 'PUT'
208
+ process action, parameters
209
+ end
210
+
211
+ ##
212
+ # Performs a DELETE request on +action+ with +params+.
213
+
214
+ def delete(action, parameters = nil)
215
+ @request.env['REQUEST_METHOD'] = 'DELETE'
216
+ process action, parameters
217
+ end
218
+
219
+ ##
220
+ # Performs a XMLHttpRequest request using +request_method+ on +action+ with
221
+ # +params+.
222
+
223
+ def xml_http_request(request_method, action, parameters = nil)
224
+ @request.env['REQUEST_METHOD'] = request_method.to_s
225
+
226
+ @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
227
+ @request.env['HTTP_ACCEPT'] = 'text/javascript, text/html, application/xml, text/xml, */*'
228
+
229
+ result = process action, parameters
230
+
231
+ @request.env.delete 'HTTP_X_REQUESTED_WITH'
232
+ @request.env.delete 'HTTP_ACCEPT'
233
+
234
+ return result
235
+ end
236
+
237
+ ##
238
+ # Friendly alias for xml_http_request
239
+
240
+ alias xhr xml_http_request
241
+
242
+ ##
243
+ # Asserts that the assigns variable +ivar+ is assigned to +value+. If
244
+ # +value+ is omitted, asserts that assigns variable +ivar+ exists.
245
+
246
+ def assert_assigned(ivar, value = NOTHING)
247
+ ivar = ivar.to_s
248
+ @assigns_asserted << ivar
249
+ assert_includes assigns, ivar, "#{ivar.inspect} missing from assigns"
250
+ unless value.equal? NOTHING then
251
+ assert_equal value, assigns[ivar],
252
+ "assert_assigned #{ivar.intern.inspect}"
253
+ end
254
+ end
255
+
256
+ ##
257
+ # Asserts the response content type matches +type+.
258
+
259
+ def assert_content_type(type, message = nil)
260
+ assert_equal type, @response.headers['Content-Type'], message
261
+ end
262
+
263
+ ##
264
+ # Asserts that +key+ of flash has +content+. If +content+ is a Regexp, then
265
+ # the assertion will fail if the Regexp does not match.
266
+ #
267
+ # controller:
268
+ # flash[:notice] = 'Please log in'
269
+ #
270
+ # test:
271
+ # assert_flash :notice, 'Please log in'
272
+
273
+ def assert_flash(key, content)
274
+ assert flash.include?(key),
275
+ "#{key.inspect} missing from flash, has #{flash.keys.inspect}"
276
+
277
+ case content
278
+ when Regexp then
279
+ assert_match content, flash[key],
280
+ "Content of flash[#{key.inspect}] did not match"
281
+ else
282
+ assert_equal content, flash[key],
283
+ "Incorrect content in flash[#{key.inspect}]"
284
+ end
285
+ end
286
+
287
+ ##
288
+ # Asserts that the assigns variable +ivar+ is not set.
289
+
290
+ def deny_assigned(ivar)
291
+ ivar = ivar.to_s
292
+ deny_includes assigns, ivar
293
+ end
294
+
295
+ ##
296
+ # Checks your assert_assigned tests against the instance variables in
297
+ # assigns. Fails if the two don't match.
298
+ #
299
+ # Add util_audit_assert_assigned to your teardown. If you have instance
300
+ # variables that you don't need to set (for example, were set in a
301
+ # before_filter in ApplicationController) then add them to the
302
+ # @assigns_ignored instance variable in your setup.
303
+ #
304
+ # = Example
305
+ #
306
+ # == Controller method
307
+ #
308
+ # class UserController < ApplicationController
309
+ # def new
310
+ # # ...
311
+ #
312
+ # @login_form = false
313
+ # end
314
+ # end
315
+ #
316
+ # == Test setup:
317
+ #
318
+ # class UserControllerTest < Test::Rails::ControllerTestCase
319
+ #
320
+ # def teardown
321
+ # super
322
+ # util_audit_assert_assigned
323
+ # end
324
+ #
325
+ # def test_new
326
+ # get :new
327
+ #
328
+ # assert_response :success
329
+ # # no assert_assigns for @login_form
330
+ # end
331
+ #
332
+ # end
333
+ #
334
+ # == Output
335
+ # 1) Failure:
336
+ # test_new(UserControllerTest)
337
+ # [[...]/controller_test_case.rb:331:in `util_audit_assert_assigned'
338
+ # [...]/user_controller_test.rb:14:in `teardown_without_fixtures'
339
+ # [...]fixtures.rb:555:in `teardown']:
340
+ # You are missing these assert_assigned assertions:
341
+ # assert_assigned :login_form #, some_value
342
+ # .
343
+
344
+ def util_audit_assert_assigned
345
+ return unless @test_passed
346
+ return unless @controller.send :performed?
347
+ all_assigns = assigns.keys.sort
348
+
349
+ assigns_ignored = DEFAULT_ASSIGNS | @assigns_ignored
350
+ assigns_ignored = assigns_ignored.map { |a| a.to_s }
351
+
352
+ assigns_created = all_assigns - assigns_ignored
353
+ assigns_asserted = @assigns_asserted - assigns_ignored
354
+
355
+ assigns_missing = assigns_created - assigns_asserted
356
+
357
+ return if assigns_missing.empty?
358
+
359
+ message = []
360
+ message << "You are missing these assert_assigned assertions:"
361
+ assigns_missing.sort.each do |ivar|
362
+ message << " assert_assigned #{ivar.intern.inspect} #, :some_value"
363
+ end
364
+ message << nil # stupid '.'
365
+
366
+ flunk message.join("\n")
367
+ end
368
+
369
+ private
370
+
371
+ def build_request_uri(action, parameters)
372
+ return if @request.env['REQUEST_URI']
373
+
374
+ options = @controller.send :rewrite_options, parameters
375
+ options.update :only_path => true, :action => action
376
+
377
+ url = ActionController::UrlRewriter.new @request, parameters
378
+ @request.set_REQUEST_URI url.rewrite(options)
379
+ end
380
+
381
+ end
382
+
@@ -0,0 +1,79 @@
1
+ $TESTING_RTC = defined?($TESTING_RTC) && $TESTING_RTC
2
+
3
+ ##
4
+ # FunctionalTestCase is an abstract class that sets up a controller instance
5
+ # for its subclasses.
6
+
7
+ class Test::Rails::FunctionalTestCase < Test::Rails::TestCase
8
+
9
+ self.use_transactional_fixtures = true
10
+ self.use_instantiated_fixtures = false
11
+
12
+ ##
13
+ # Sets up instance variables to allow tests depending on a controller work.
14
+ #
15
+ # setup uses the instance variable @controller_class_name to determine which
16
+ # controller class to instantiate.
17
+ #
18
+ # setup also instantiates a new @request and @response object.
19
+ #
20
+ # If you need to perform extra setup actions, define #setup_extra and
21
+ # FunctionalTestCase will call it after performing the rest of its setup
22
+ # actions.
23
+
24
+ def setup
25
+ return if self.class.name =~ /TestCase$/ and not $TESTING_RTC
26
+ super
27
+
28
+ @controller_class = Object.path2class @controller_class_name
29
+ raise "Can't determine controller class for #{self.class}" if @controller_class.nil?
30
+
31
+ @controller = @controller_class.new
32
+
33
+ @session = ActionController::TestSession.new
34
+
35
+ @flash = ActionController::Flash::FlashHash.new
36
+ @session['flash'] = @flash
37
+
38
+ @request = ActionController::TestRequest.new
39
+ @request.session = @session
40
+
41
+ # HACK There's probably an official way to do this
42
+ @controller.instance_variable_set :@_session, @request.session
43
+
44
+ @response = ActionController::TestResponse.new
45
+
46
+ setup_extra if respond_to? :setup_extra
47
+ end
48
+
49
+ ##
50
+ # Flash accessor. The flash can be assigned to before calling process or
51
+ # render and it will Just Work (yay!)
52
+ #
53
+ # view:
54
+ # <div class="error"><%= flash[:error] %></div>
55
+ #
56
+ # test:
57
+ # flash[:error] = 'You did a bad thing.'
58
+ # render
59
+ # assert_tag :tag => 'div', :attributes => { :class => 'error' },
60
+ # :content => 'You did a bad thing.'
61
+
62
+ attr_reader :flash
63
+
64
+ ##
65
+ # Session accessor. The session can be assigned to before calling process
66
+ # or render and it will Just Work (yay!)
67
+ #
68
+ # test:
69
+ #
70
+ # def test_logout
71
+ # session[:user] = users(:herbert)
72
+ # post :logout
73
+ # assert_equal nil, session[:user]
74
+ # end
75
+
76
+ attr_reader :session
77
+
78
+ end
79
+
@@ -0,0 +1,64 @@
1
+ ##
2
+ # Stub controller for testing helpers.
3
+
4
+ class HelperTestCaseController < ApplicationController
5
+
6
+ attr_accessor :request
7
+
8
+ attr_accessor :url
9
+
10
+ ##
11
+ # Re-raise errors
12
+
13
+ def rescue_action(e)
14
+ raise e
15
+ end
16
+
17
+ end
18
+
19
+ ##
20
+ # HelperTestCase allows helpers to be easily tested.
21
+ #
22
+ # Original concept by Ryan Davis, original implementation by Geoff Grosenbach.
23
+
24
+ class Test::Rails::HelperTestCase < Test::Rails::FunctionalTestCase
25
+
26
+ self.use_transactional_fixtures = true
27
+ self.use_instantiated_fixtures = false
28
+
29
+ # Are other helpers needed?
30
+
31
+ include ActionView::Helpers::ActiveRecordHelper
32
+ include ActionView::Helpers::TagHelper
33
+ include ActionView::Helpers::FormTagHelper
34
+ include ActionView::Helpers::FormOptionsHelper
35
+ include ActionView::Helpers::FormHelper
36
+ include ActionView::Helpers::UrlHelper
37
+ include ActionView::Helpers::AssetTagHelper
38
+ include ActionView::Helpers::PrototypeHelper rescue nil # Rails 1.0 only
39
+ include ActionView::Helpers::TextHelper
40
+
41
+ ##
42
+ # Automatically includes the helper module into the test sublcass.
43
+
44
+ def self.inherited(helper_testcase)
45
+ super
46
+ helper_name = helper_testcase.name.sub 'Test', ''
47
+ helper_module = Object.path2class helper_name
48
+ helper_testcase.send :include, helper_module
49
+ rescue NameError
50
+ raise "Unable to find helper #{helper_name}"
51
+ end
52
+
53
+ def setup
54
+ return if self.class.name =~ /TestCase$/
55
+ @controller_class_name = 'HelperTestCaseController'
56
+ super
57
+ @controller.request = @request
58
+ @controller.url = ActionController::UrlRewriter.new @request, {} # url_for
59
+
60
+ ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
61
+ end
62
+
63
+ end
64
+
@@ -0,0 +1,31 @@
1
+ require 'test/rails'
2
+
3
+ ##
4
+ # A wrapper that allows instance variables to be manipulated using +[]+ and
5
+ # +[]=+
6
+
7
+ class Test::Rails::IvarProxy
8
+
9
+ ##
10
+ # Wraps +object+ allowing its instance variables to be manipulated.
11
+
12
+ def initialize(object)
13
+ @object = object
14
+ end
15
+
16
+ ##
17
+ # Retrieves +ivar+ from the wrapped object.
18
+
19
+ def [](ivar)
20
+ @object.instance_variable_get "@#{ivar}"
21
+ end
22
+
23
+ ##
24
+ # Sets +ivar+ to +val+ on the wrapped object.
25
+
26
+ def []=(ivar, val)
27
+ @object.instance_variable_set "@#{ivar}", val
28
+ end
29
+
30
+ end
31
+