More articles about Ruby on Rails

File Upload Form Testing Fixtures

By Christopher Haupt

Published February 5, 2008  |   comments

Related Topics

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


Add your comment on this article






Reader comments on this article

From: Joe       Date: 07/02/08 02:14 PM

Subject: Awesome!

I’ve been trying to figure out how to test file uploads for an hour now and I stumbled upon this. Great job!

From: Ziemek       Date: 04/29/08 08:08 AM

Subject: Nice Article

short sweet and to the point. Well done!

 

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

Screencasts


Creative Commons License

This article is licensed under a Creative Commons Attribution-NoDerivs 3.0 License