Cucumber + Paperclip

96 views
Skip to first unread message

Jeremy Hageman

unread,
Jul 31, 2009, 3:09:09 AM7/31/09
to Cukes
I have recently become a student of Cucumber and have been working
through the Rspec book, but have hit a spot which I cannot find much
documentation about. Can you recommend some methods for testing the
filesystem using Cucumber? Specifically Paperclip. Below is my initial
scenario:

Scenario: User uploads first photo to profile
Given I am a logged user
And I am on the My Profile page
And I have no photos uploaded
When I follow "Upload a photo"
And I press "Browse"
And I press "Upload"
Then I should see "Your photo has bee uploaded"
And I should see my photo

I know I am missing some important parts.

nruth

unread,
Jul 31, 2009, 7:48:30 AM7/31/09
to Cukes
There is some test functionality provided with paperclip, but it is
for shoulda and I have not really pursued this direction yet.

Instead I have taken the following approach. I am using Machinist for
random test data. You could simplify this to use a single test image
if you prefer.

Put some images into spec/fixtures directory with a common name, e.g.
example1.jpg example2.gif example3.jpg and so on

My paperclip binding is called picture and it's on my service object.
This is in my service steps file:

def new_picture
@new_picture ||= Sham.image
end

When /^I provide an image file for "picture"$/ do
attach_file "service_picture", new_picture.path
end

And in my Sham.define block (in spec/blueprints.rb)

image do
images = []
dirpath = File.join Rails.root, 'spec', 'fixtures'
Dir.new(dirpath).each { |file| images << File.new(File.join
(dirpath, file)) if file =~ /^example\d/ }
images[rand(images.length)]
end

The gotcha is cleaning up the files afterwards, since we're not using
the database for a file store. I took this approach (which is hacky
but works, on unix) to put the paperclip test files into a different
directory and delete the directory afterwards.

features/support.env

#remove paperclip files
module Paperclip::Interpolations
alias_method :org_attachment, :attachment

def attachment(att, style)
"CUKE/" + org_attachment(att, style)
end
end

After do
`rm -rf #{"#{RAILS_ROOT}/public/system/CUKE"}`
end

#end remove paperclip files

Hope this helps. If it doesn't work I may have forgotten some code.

Regards

Nick

Jeremy Hageman

unread,
Jul 31, 2009, 8:07:06 PM7/31/09
to Cukes
Nick, thanks for the help. I was able to use your recommendations and
get the test images into the app and deleted via my cucumber story. My
scenario became:

Scenario: User uploads first photo to profile
Given I am a logged user
And I am on the My Profile page
And I have no photos uploaded
When I follow "Upload a photo"
And I provide an image file for "user_photo_avatar"
And I press "Upload"
Then I should see "Your photo has bee uploaded"
And I should see my photo

I've added the following to my user_steps.rb file:

def new_picture
@new_picture ||= Sham.image
end

When /^I provide an image file for "([^\"]*)"$/ do |field_name|
attach_file field_name, new_picture.path
end

Now I'm a little stuck on how to verify the last step in my scenario,
"And I should see my photo." So far I have this as the step, based on
page 311 of the Rspec book.

Then /^I should see my photo$/ do
response.should have_selector("img", :scr => "...")
end

I'm not sure what to reference for the 'scr' in order to verify that
the name of the image uploaded is the one being displayed. Any
recommendations?

nruth

unread,
Aug 1, 2009, 8:49:42 AM8/1/09
to Cukes
I opted for this fairly low-level approach, it works, but there may be
a better alternative.

response.body.should =~ /#{File.basename new_picture.path}/

I suppose you could try the contents of my pattern as your src, and
variations on that theme.

iirc the idea here was for it to look for the image's filename but you
might want to check what the basename and path methods do.

nruth

unread,
Aug 1, 2009, 9:57:53 AM8/1/09
to Cukes
I should mention that if you look at the image paths produced they
include Rails post cookie session secret thingy, so if you check for
the file path only the test will fail (in some situations I observed,
at least). So you should pattern match rather than use ==

With a selector you can use img[src*='#{the_file_path_here}'] rather
than src=, or perhaps ^= to assert the src begins with the path

I don't tend to use the :src => flags as I have had problems with css
selector abstraction in webrat/rspec/something in the case of tag1
tag2 vs tag1 > tag2, i.e. if anything is in between the two elements
your test will fail even though you want it to pass, e.g. a form
contains an input tag but there is a fieldset tag in-between, the
fieldset will cause the assertion to fail erroneously.

so for your example I would try this:

Then /^I should see my photo$/ do
response.should have_selector("img[src*=''#{File.basename
new_picture.path}])
end

Jeremy Hageman

unread,
Aug 2, 2009, 2:49:08 AM8/2/09
to Cukes
Going the pattern match route worked great. My scenario completely
passes now.

There was one out-of-place apostrophe for anyone following along.

Then /^I should see my photo$/ do
response.should have_selector("img[src*='#{File.basename
new_picture.path}']")
end

Thanks again for the help.
Reply all
Reply to author
Forward
0 new messages