Cucumber speed tips


#1

As some of us have been using cucumber for quite a while now, I may not
be
the only one wishing his many steps ran a bit faster.

Let’s try to put together a quick FAQ for people looking to speed up
their
steps.

Here’s my ideas:

  1. Consolidate steps
    You only need to test login for each login case, not for each time you
    are
    testing some sort of logged in functionality.
    In most cases you can just post to sessions/create rather than filling
    in a
    login form.

1a) Don’t use GivenScenario
Instead, make one step that will quickly do what the scenario you want
to
start at the end of does. E.g. rather than fill in a form and post to a
controller to create an object, just create the object in its own step.

  1. Use the profiler format
    I’ve only tried this a few times, but the profile formatting appears to
    be
    useful.

Anybody else have any tips?

M


#2

On 12/27/08 1:08 AM, Mischa F. wrote:

are testing some sort of logged in functionality.
I’ve only tried this a few times, but the profile formatting appears
to be useful.

Anybody else have any tips?

  1. Seed your database in your support files. For static data that will
    be used over and over again you can save time by only inserting it once
    in your DB at the start of the run. For example in env.rb you could
    say:

unless ZipCode.count == 79851
puts “Loading all the zip code data…”

end


#3

On Sat, Dec 27, 2008 at 12:52 PM, Ben M. removed_email_address@domain.invalid wrote:

  1. Consolidate steps
  2. Use the profiler format
    I’ve only tried this a few times, but the profile formatting appears to be
    useful.

Anybody else have any tips?

  1. Seed your database in your support files. For static data that will be
    used over and over again you can save time by only inserting it once in your
    DB at the start of the run. For example in env.rb you could say:
  1. Distribute your scenarios across multiple processes using TestJour
    (http://github.com/brynary/testjour)


Josh K.
phone: 509-979-1593
email: removed_email_address@domain.invalid
web: http://joshknowles.com


#4

On Dec 28, 2008, at 11:30 AM, Josh K. wrote:

  1. Distribute your scenarios across multiple processes using TestJour
    (http://github.com/brynary/testjour)

To provide a little more info (Josh and I work with Bryan, who created
testjour): we have a cucumber suite currently consisting of 5835 steps
that takes a bit under 20 minutes to run without testjour.

Running it via testjour with 2 local slaves and 6 remote slaves (2 mac
minis and a Mac Pro), the run completes in about 4 minutes.

testjour is still a little raw, but I already would not want to work
on a large product without it.

Luke

Luke M.
removed_email_address@domain.invalid
http://www.lukemelia.com/


#5

On Dec 27, 2008, at 3:08 AM, Mischa F. wrote:

You only need to test login for each login case, not for each time
you are testing some sort of logged in functionality.
In most cases you can just post to sessions/create rather than
filling in a login form.

I also wanted to speed up the “Given I am a logged in user” type of
thing, as you suggested, but took a different, faster approach which
may also work for you. I set a cookie to auto-login the user on the
next request. Implementation as a gist http://gist.github.com/42973
and below. -Luke

features/steps/users_steps.rb:

Given “I’m a logged in member” do
@me = create_adult
logged_in_as @me
end

features/support/env.rb:

class Cucumber::Rails::World

def logged_in_as(user)
cookies[‘integration_test_user’] = user.id.to_s
end
,
end

app/controllers/application.rb

class ApplicationController < ActionController::Base

before_filter :login_integration_test_user, :if => lambda
{ Rails.env == ‘test’ }

def login_integration_test_user
return true if cookies[‘integration_test_user’].blank?
integration_test_user_id = cookies[‘integration_test_user’].to_i

 if integration_test_user_id != current_user.id
   reset_session
   self.current_user = User.find(integration_test_user_id)
 end

 cookies['integration_test_user'] = nil

end


Luke M.
removed_email_address@domain.invalid
http://www.lukemelia.com/


#6

On 1/3/09 6:41 PM, Luke M. wrote:

next request. Implementation as a gist http://gist.github.com/42973

class ApplicationController < ActionController::Base
self.current_user = User.find(integration_test_user_id)
end

cookies['integration_test_user'] = nil

end

The downside with this approach is that it only works with the rails
webrat adapter. One solution which I have been meaning to do is to
create a UsersSessionManager. The manager would be responsible for
logging in all the various roles you use in your app with different
webrat sessions (and then caching them.) You could then swap out which
session you would be using in your steps…

So you could then do something like:

logged_in_as ‘Admin’ do |session|
session.click_link ‘Foo’

end

Or…

Given /^I am logged in as an ‘(.+)’$/ |role|
login_as role
end

The ‘login_as’ would swap out the session that the World object uses so
the next steps would be using the appropriate session.

WDYT?

-Ben

-Ben


#7

On 1/3/09 8:36 PM, Luke M. wrote:

visit login_for_test_path(user)

end

where login_for_test_path is is a named route defined only for the
selenium environment that provides a “quick” login of a given user.

Would the solution you’re thinking of help with this? I’m not sure how
you would “cache” a selenium session.

I’m by no means a Selenium expert so I may be making some incorrect
assumptions. I thought that it was possible with Selenium to have
different sessions open concurrently for the same selenium server. (i.e.
have more than one SeleniumDriver/browser instance running against the
same server but with different session ids.) Is that not possible?

-Ben


#8

On Jan 3, 2009, at 9:12 PM, Ben M. wrote:

session.click_link ‘Foo’
so the next steps would be using the appropriate session.

WDYT?

In general I like the idea, Ben. At weplay, we use webrat to drive
rails and selenium, and logged_in_as method has the following
implementation in the Selenium world:

def logged_in_as(user)
visit login_for_test_path(user)
end

where login_for_test_path is is a named route defined only for the
selenium environment that provides a “quick” login of a given user.

Would the solution you’re thinking of help with this? I’m not sure how
you would “cache” a selenium session.


Luke M.
removed_email_address@domain.invalid
http://www.lukemelia.com/


#9

On Jan 4, 2009, at 7:08 PM, Ben M. wrote:

I’m by no means a Selenium expert so I may be making some incorrect
assumptions. I thought that it was possible with Selenium to have
different sessions open concurrently for the same selenium server.
(i.e. have more than one SeleniumDriver/browser instance running
against the same server but with different session ids.) Is that
not possible?

Not that I know of, but now that you mention it, seems like it would
be pretty cool. Anyone else on the list done this?

Luke M.
removed_email_address@domain.invalid
http://www.lukemelia.com/


#10

Josh, Ben & Luke –

This is great stuff, thanks a bunch. Over at CaptainU we are probably
going
to get into the thousands in the next few weeks or so, so speed is a
serious
issue. I’m going to work on a longer blog post about this, will let you
guys
know when finished.

Best,

M