Skip to content
janeiro 23, 2009 / cassiomarques

How to test file uploads with Cucumber

In a previous article (in portuguese, but you can always use Google Translate to take a look at it) I showed how to use Cucumber to create functional tests for your web applications. Today I’ll show how to use Cucumber to test file uploads. I’ll use a Rails application as our example, but in general the concepts presented here could be applied to test file uploads in any web application.

Let’s consider a ProductsController controller with an get_csv_file action, which purpose is to receive a csv text file with and record the data in each line as a new instance of the Product class. What could be the expected behaviour of such action? Let’s describe it with a Cucumber feature:

  
  Feature: CSV file upload
    In order to create new products in the database
    As a user
    I want to be able to upload a CSV file with the products' data

    Scenario: Uploading a valid file with data for 3 new products
      Given I visit the file upload page
      When I upload a file with valid data for 3 new products
      Then the number of products should change to 3
      And I should be sent to the products index page

    Scenario: Uploading a malformed file
      Given I visit the file upload page
      When I upload a malformed file
      Then the number of products should not change
      And I should see the file upload page again
  
  

We have two basic scenarios, one for a correct file and another for a bad one. We don’t have any code yet for the steps Cucumber will execute when running the tests, so let’s do it. I’ll show just the steps for the file uploads.

When /^I upload a file with valid data for 3 new products$/ do
  attach_file(:csv_file, File.join(RAILS_ROOT, 'features', 'upload-files', 'products_csv_ok.csv'))
  click_button "Send file"
end

When /^I upload a malformed file$/ do
  attach_file(:csv_file, File.join(RAILS_ROOT, 'features', 'upload-files', 'products_csv_bad.csv'))
  click_button "Send file"
end

The idea here is to create two files, one good and one invalid, and put them somewhere inside your application. I put them inside features/upload-files, you can place them wherever you like. The attach_file method received a symbol with the name of the field used for the upload and the path for a file in your disc. After associating the field with the path for the file, all we’ll have to do is “to click” at the submit button.

Here’s the code of the action I wrote

def create_from_csv_file
  csv_data = params[:csv_file]
  if Product.create_from_csv(csv_data)
    flash[:notice] = "Products succesfully created"
    redirect_to products_url
  else
    flash[:error] = "Invalid file contents"
    render :action => "new_csv_file"
  end
end

With this solution you can test any kind of file uploads. A good example would be to create restrictions about the type of the files that can be uploaded, restrictions about the dimensions of uploaded images and so on.

7 Comentários

Deixe um comentário
  1. William Notowidagdo / abr 27 2009 7:25 am

    Thank you for sharing. I was looking for this

  2. Curt / maio 5 2009 12:31 am

    Thanks so much for this info. It really helped me! I found that I need to add the content-type as a third argument to get this to work correctly with cucumber and ActiveRecord validations. Do you know of any efficient methods to determine a file’s content-type so that it can be dynamically inserted in to the argument hash? Right now I have ‘image/jpeg’ hard-coded as the third argument to attach_file() until I find a solution. Thanks again!

  3. cassiomarques / maio 5 2009 3:31 am

    @Curt,

    I really didn’t test it with image uploads and/or testing with plugins such as attachment-fu or paperclip (which does validations against the files’ content type).
    However, I think that you could test the ‘acceptable’ content-types using Cucumber’s Scenario Outlines (http://wiki.github.com/aslakhellesoy/cucumber/scenario-outlines), somethink like this:

    Scenario Outline: Acceptable image formats
    ...
    When I upload a <format> image located at <path>...

    Examples:
    |format|path |
    |jpeg |files/image.jpeg |
    |gif |files/image.gif |
    |png |files/image.png |

    And then in the step definition

    When /^I upload a (.+) image located at (.+)$/ do |format, path|
    attach_file(:image, File.join(RAILS_ROOT, 'features', ṕath), "image/#{format}")
    end

    It’s an idea :)

  4. abhishek shukla / nov 28 2009 9:03 am

    Thank you you saved my life..

  5. Simon / abr 19 2011 4:04 pm

    What about javascript file uploads ? How can I test those..

Trackbacks

  1. InVisible Blog » links for 2009-11-10

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: