More articles about Ruby on Rails
File Upload Form Testing Fixtures
By
Recently, I needed to write my first set of functional tests for a form that is used to upload image assets into our Content Management System. I wanted to find something as easy as fixtures for testing this part of our program.
Whether you are using Rick Olson’s excellent attachment_fu (see Mike Clark’s nice tutorial), Sebastian Kanthak and Jonas Nicklas’ upload_column, or your own code that works with file uploads, you should test this workflow just like any other code path. At first, I thought this was going to be a painful task and require messing around with some custom File I/O or other marshaling trickery. Most of the documentation for 3rd party file upload implementations tended to have little or no information on testing.
Then, while reading through the code a bit more, I stumbled upon fixture_file_upload. This convenience function is tucked away in ActionController’s TestProcess module and is shorthand for instantiating the underlying ActionController::TestUploadedFile class. TestUploadedFile itself is a mock object that simulates the target file that my user would upload in a form or other interface via a MIME multipart/form-data POST.
To use this handy method, I simply put test files in a convenient directory within my fixtures directory, say “files”. Then in a test for upload_column, I write:
def test_should_create_asset
old_count = Asset.count
post :create, :asset => { :title => "test", :file => fixture_file_upload('/files/testpicture1.jpg', 'image/jpeg') }
assert_equal old_count+1, Asset.count
assert_redirected_to asset_path(assigns(:asset))
end
Here, the :file attribute for my asset model is expecting an uploaded file from my form, so I feed it one from my fixtures/files directory.
If I use attachment_fu, I may write a create test:
def test_should_create_asset
old_count = Asset.count
post :create, :asset => { :name => 'railslogo', :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') },
:html => {:multipart => true }
assert_equal old_count+1, Asset.count
end
or an update test:
def test_should_update_asset
put :update, {:id => assets(:one).id, :asset => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') }}
assert_redirected_to asset_path(assigns(:asset))
end
The TestUploadedFile class is not limited to image data. It can channel any type I may wish into the request. Its default content type assumes text/plain.
Now I can proceed to write a suite of tests for my file upload use cases and let Action Controller and the fixture_file_upload helper do the heavy lifting.
Other Resources
Reader comments on this article
Join our List
And we'll let you know when we post major new site updates.
We’ll never share your email address with anyone else.
Related Content
from around the Web
Other Articles
- Understanding Ruby blocks, Procs and methods
- Skinny Controller, Fat Model
- Ruby on Rails routing demystified
- Ruby on Rails Caching Tutorial
- 19 Tricks Most Rails Coders Don't Know
- iPhone on Rails - Creating an iPhone optimised version of your Rails site using iUI and Rails 2
Screencasts
- Railscasts - Free Ruby on Rails Screencasts
- PeepCode
- Rails from Scratch Part II
- Test-First Development for Rails
- rSpec Mocks and Models
- rSpec Controllers and Tools
Documentation
- Textile Reference
- RubyBrain.com: Javascript enhanced Ruby API docs
- GotAPI
- RailsBrain: Javascript-Enhanced Rails API Documentation
- Ruby on Rails API
- Ruby Standard Library Documentation
This article is licensed under a Creative Commons Attribution-NoDerivs 3.0 License

From: Ziemek Date: 04/29/08 08:08 AM
Subject: Nice Article
short sweet and to the point. Well done!