ZenTest 3.11.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/test/rails.rb DELETED
@@ -1,295 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
- require 'rubygems/version'
4
- require 'test_help' # hopefully temporary, required for Test::Rails to work
5
- # until we get rid of test_help so Test::Unit::TestCase
6
- # is kept virgin.
7
- require 'rails/version' unless defined? Rails::VERSION
8
-
9
- $TESTING = true
10
-
11
- ##
12
- # = Introduction
13
- #
14
- # Test::Rails helps you build industrial-strength Rails code by:
15
- # * testing views separate from controllers
16
- # * enhancing the assertion vocabulary, and
17
- # * auditing your tests for consistency.
18
- #
19
- # = Details
20
- #
21
- # Test::Rails:
22
- # * splits Functional test into Controller and View tests.
23
- # * Splits view assertions away from controller assertions.
24
- # * Helps decouple views from controllers.
25
- # * Allows you to test AJAX actions in isolation.
26
- # * Allows you to test a single partial.
27
- # * Clearer failures when assert_tag fails.
28
- # * An auditing script analyzes missing assertions in your controllers and
29
- # views.
30
- # * Library of assertions for testing views.
31
- #
32
- # = How to Convert to Test::Rails
33
- #
34
- # You will need to make three small changes to test/test_helper.rb to set up
35
- # Test::Rails:
36
- #
37
- # First, add the following to 'test/test_helper.rb' before you require
38
- # +test_help+:
39
- #
40
- # require 'test/rails'
41
- #
42
- # Next, change the class from "Unit" to "Rails" right after you
43
- # require +test_help+.
44
- #
45
- # Your 'test/test_helper.rb' will end up looking like this:
46
- #
47
- # ENV["RAILS_ENV"] = "test"
48
- # require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
49
- # require 'test/rails'
50
- # require 'test_help'
51
- #
52
- # class Test::Rails::TestCase
53
- # ...
54
- #
55
- # Finally, you need to add the extra rake tasks Test::Rails provides.
56
- # Add the following line to your Rakefile after you require
57
- # 'tasks/rails':
58
- #
59
- # require 'test/rails/rake_tasks'
60
- #
61
- # *NOTE*:
62
- #
63
- # * get/post/etc. no longer have a session or flash argument. Use the session
64
- # and flash accessor instead.
65
- # * assert_tag will (eventually) not work in controller tests.
66
- #
67
- # == Writing View Tests
68
- #
69
- # View tests live in test/views. They are named after the controller that is
70
- # being tested. For exampe, RouteViewTest will live in the file
71
- # test/views/route_view_test.rb.
72
- #
73
- # === Example View Test Case
74
- #
75
- # require 'test/test_helper'
76
- #
77
- # # We are testing RouteController's views
78
- # class RouteViewTest < Test::Rails::ViewTestCase
79
- #
80
- # fixtures :users, :routes, :points, :photos
81
- #
82
- # # testing the view for the delete action of RouteController
83
- # def test_delete
84
- # # Instance variables necessary for this view
85
- # assigns[:loggedin_user] = users(:herbert)
86
- # assigns[:route] = routes(:work)
87
- #
88
- # # render this view
89
- # render
90
- #
91
- # # assert everything is as it should be
92
- # assert_links_to "/route/flickr_refresh/#{routes(:work).id}"
93
- #
94
- # form_url = '/route/destroy'
95
- # assert_post_form form_url
96
- # assert_input form_url, :hidden, :id
97
- # assert_submit form_url, 'Delete!'
98
- # assert_links_to "/route/show/#{routes(:work).id}", 'No, I do not!'
99
- # end
100
- #
101
- # # ...
102
- #
103
- # end
104
- #
105
- # All view tests are a subclass of Test::Rails::ViewTestCase. The name of the
106
- # subclass must match the controller this view depends upon. ViewTestCase
107
- # takes care of all the setup necessary for running the tests.
108
- #
109
- # The +test_delete+ method is named after the delete method in
110
- # RouteController. The ViewTestCase#render method looks at the name of the
111
- # test and tries to figure out which view file to use, so naming tests after
112
- # actions will save you headaches and typing.
113
- #
114
- # Use +assigns+ to set up the variables the view will use when it renders.
115
- #
116
- # The call to render is the equivalent to a functional tests' get/post
117
- # methods. It makes several assumptions, so be sure to read
118
- # ViewTestCase#render carefully.
119
- #
120
- # ViewTestCase has a vastly expanded assertion library to help you out with
121
- # testing. See ViewTestCase for all the helpful assertions you can use in
122
- # your view tests.
123
- #
124
- # == Writing Controller Tests
125
- #
126
- # Controller tests are essentially functional tests without the view assertions.
127
- #
128
- # They live in test/controllers, subclass ControllerTestCase, and are
129
- # named after the controller they are testing. For example,
130
- # RouteControllerTest will live in the file
131
- # test/controllers/route_controller_test.rb.
132
- #
133
- # === Example Controller Test Case
134
- #
135
- # require 'test/test_helper'
136
- #
137
- # # We are testing RouteController's actions
138
- # class RouteControllerTest < Test::Rails::ControllerTestCase
139
- #
140
- # fixtures :users, :routes, :points, :photos
141
- #
142
- # # Testing the delete method
143
- # def test_delete
144
- # # A session accessor is provided instead of passing a hash to get.
145
- # session[:username] = users(:herbert).username
146
- #
147
- # get :delete, :id => routes(:work).id
148
- #
149
- # # assert we got a 200
150
- # assert_success
151
- #
152
- # # assert that instance variables are correctly assigned
153
- # assert_assigned :action_title, "Deleting \"#{routes(:work).name}\""
154
- # assert_assigned :route, routes(:work)
155
- # end
156
- #
157
- # # ...
158
- #
159
- # end
160
- #
161
- # == Writing Abstract Test Cases
162
- #
163
- # Abstract test cases are a great way to refactor your tests and
164
- # ensure you do not violate the DRY principal and share code between
165
- # different test classes. If you have common setup code for your test
166
- # classes you can create your own subclass of ControllerTestCase or
167
- # ViewTestCase.
168
- #
169
- # === Example Abstract Test Case
170
- #
171
- # class RobotControllerTestCase < Test::Rails::ControllerTestCase
172
- #
173
- # fixtures :markets, :people
174
- #
175
- # def setup
176
- # super
177
- #
178
- # # We're running tests in this class so we don't need to do any more
179
- # # setup
180
- # return if self.class == RobotControllerTestCase
181
- #
182
- # # Set our current host
183
- # @host = 'www.test.robotcoop.com'
184
- # util_set_host @host
185
- # end
186
- #
187
- # ##
188
- # # Sets the hostname to +host+ for this request.
189
- #
190
- # def util_set_host(hoston)
191
- # @request.host = host
192
- # end
193
- #
194
- # end
195
- #
196
- # = How to Audit Your Tests
197
- #
198
- # <tt>bin/rails_test_audit</tt> ensures that your view tests'
199
- # +assign+s are compared against your controller tests'
200
- # assert_assigned, warning you when you've forgotten to test
201
- # something.
202
- #
203
- # Given:
204
- #
205
- # class RouteControllerTest < Test::Rails::ControllerTestCase
206
- # def test_flickr_refresh
207
- # get :flickr_refresh, :id => routes(:work).id
208
- # assert_success
209
- #
210
- # assert_assigned :tz_name, 'Pacific Time (US & Canada)'
211
- # end
212
- # end
213
- #
214
- # And:
215
- #
216
- # class RouteViewTest < Test::Rails::ViewTestCase
217
- # def test_flickr_refresh
218
- # assigns[:route] = routes(:work)
219
- # assigns[:tz_name] = 'Pacific Time (US & Canada)'
220
- #
221
- # render
222
- #
223
- # # ...
224
- # end
225
- # end
226
- #
227
- # +rails_test_audit+ will see that you don't have an +assert_assigned+
228
- # for +route+ and will output:
229
- #
230
- # require 'test/test_helper'
231
- #
232
- # class RouteControllerTest < Test::Rails::ControllerTestCase
233
- #
234
- # def test_flickr_refresh
235
- # assert_assigned :route, routes(:work)
236
- # end
237
- #
238
- # end
239
- #
240
- # = How 'rake test' Changed
241
- #
242
- # test:views and test:controllers targets get added so you can run just the
243
- # view or controller tests.
244
- #
245
- # The "test" target runs tests in the following order: units, controllers,
246
- # views, functionals, integration.
247
- #
248
- # The test target no longer runs all tests, it stops on the first
249
- # failure. This way a failure in a unit test doesn't fill your screen
250
- # with less important errors because the underlying failure also
251
- # affected your controllers and views.
252
- #
253
- # The stats target is updated to account for controller and view tests.
254
-
255
- module Test::Rails
256
-
257
- @rails_version = Gem::Version.new Rails::VERSION::STRING
258
- @v1_2 = Gem::Version.new '1.2'
259
-
260
- ##
261
- # The currently loaded rails version. Better than Rails::VERSION::STRING
262
- # since this one is comparable.
263
-
264
- def self.rails_version
265
- @rails_version
266
- end
267
-
268
- def self.v1_2 # :nodoc:
269
- @v1_2
270
- end
271
-
272
- end
273
-
274
- class Object # :nodoc:
275
- def self.path2class(klassname)
276
- klassname.split('::').inject(Object) { |k,n| k.const_get n }
277
- end
278
- end
279
-
280
- require 'test/zentest_assertions'
281
- require 'test/rails/test_case'
282
- require 'test/rails/functional_test_case'
283
- require 'test/rails/controller_test_case'
284
- require 'test/rails/helper_test_case'
285
- require 'test/rails/ivar_proxy'
286
- require 'test/rails/view_test_case'
287
-
288
- ##
289
- # Use sensible defaults.
290
-
291
- class Test::Unit::TestCase # :nodoc:
292
- self.use_transactional_fixtures = true
293
- self.use_instantiated_fixtures = false
294
- end
295
-
@@ -1,382 +0,0 @@
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
-