/* CODIFICANDO */

Relatos de um programador em contínua aprendizagem.

Archive for Janeiro 23rd, 2009

How to test file uploads with Cucumber

com 5 comentários

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.

Escrito por cassiomarques

Janeiro 23, 2009 em 5:22 am

Publicado em rails, testes

Como testar upload de arquivos com o Cucumber

com 5 comentários

Em um artigo anterior eu mostrei como utilizar o Cucumber para criar testes funcionais para sua aplicação web. Hoje vou mostrar como utilizar o Cucumber para testar uploads de arquivos. Vou usar como exemplo uma aplicação Rails, mas de forma geral as técnicas descritas aqui poderiam ser utilizadas para testar upload de arquivos em qualquer aplicação web.

Vamos considerar um controller ProductsController com uma action create-from_csv_file cujo propósito é receber um arquivo texto com valores separados por vírgulas e gravar os dados de cada linha como um novo objeto da classe Product persistido no banco de dados. Qual seria o comportamento esperado para uma action como essa? Vamos descrever esse comportamento em uma feature escrita com o Cucumber:

  
  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
  
  

Temos dois cenários básicos listados, um para um arquivo correto e outro para um arquivo defeituoso. Ainda não temos código nenhum implementado para os passos que o Cucumber deve executar durantes os testes, logo essa é a próxima etapa. Vou mostrar apenas como poderiam ser escritos os passos que realizam o upload dos arquivos.

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

A idéia aqui é criar dois arquivos, um correto e outro inválido, e colocá-los em algum diretório da sua aplicação. Eu coloquei dentro de features/upload-files, poderia ser colocado em qualquer outro lugar que você prefira. O método attach_file recebe um symbol com o nome do campo onde será informado o arquivo a enviar e o caminho para um arquivo em disco. Depois de associar o campo com o caminho para um arquivo, basta “clicar” no botão e fazer o submit do formulário.

Só por curiosidade, aqui está o código da action que escrevi:

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

Com essa solução você pode testar upload de qualquer tipo de arquivo. Um bom exemplo seria criar restrições para tipos de arquivos que podem ser recebidos, restrições para dimensões de imagens que podem ser enviadas, etc.

Escrito por cassiomarques

Janeiro 23, 2009 em 4:53 am

Publicado em rails, testes

Etiquetado com , ,