Simultaneous Capybara Sessions in Cucumber

There’s something very satisfying about watching your Cucumber test suite run (and pass), especially when the tests are running in your browser. I can’t help but think, “Man, I’m glad I don’t have to do all of this myself.” That’s especially true when your testing requires multiple sessions. The old me would fire up a couple different browsers and get to work. But that was the old me.

The New Me: Powered by Capybara

Capybara 1.0.0 added the ability to name your sessions. Prior to this, a session was only identified by its driver (before & after). It’s a small change with big benefit. For instance…

Testing Pub/Sub

If you’re not familiar with the latest Pub/Sub craze, check out Pusher and PubNub. They’re similar services enabling your app to push JSON to your user’s browser rather than the browser polling for updates. It’s all very cool. And for me, it was also tricky to test.

Imagine we’re developing a simple chat feature inside a Rails app. I’ll skip the specifics of integrating with Pusher or PubNub so we can focus on the tests. The challenge is to bring up two browser windows with separate sessions and test that they can chat with each other. Enter: named Capybara sessions. With a couple simple Cucumber steps, this is a breeze. Here’s our feature:

@javascript
Feature: Chat
  As a user
  I want to chat with other users
  So I feel like part of a community

  Scenario: Push for chat
    Given the following users exist:
      | Name  |
      | Steve |
      | Catie |
    When I am in Steve's browser
    And I am logged in as "Steve"
    And I go to the messages page
    Then I should not see "Hi, Steve!"

    When I am in Catie's browser
    And I am logged in as "Catie"
    And I go to the new message page
    And I fill in "Body" with "Hi, Steve!"
    And I press "Send"
    And I wait 2 seconds
    Then I should see "Hi, Steve!"

    When I am in Steve's browser
    Then I should see "Hi, Steve!"

Many of those steps come from Capybara’s web\_steps.rb, with some help from Factory Girl. The “logged in” steps are custom but I’ll leave them out here because they’re usually pretty application-specific. That leaves these custom steps:

When /^I am in (.*) browser$/ do |name|
  Capybara.session_name = name
end

When /^I wait (\d+) seconds?$/ do |seconds|
  sleep seconds.to_i
end

And that’s it. Cucumber and Capybara will remember the current state of each browser. It works well with the @javascript tag for Pub/Sub but can be used for any kind of concurrent user interactions.

One More Thing…

The browser switching step above is simple enough but I found myself wanting a more inline step as well. So here you go:

When /^(?!I am in)(.*(?= in)) in (.*) browser$/ do |step, name|
  When "I am in #{name} browser"
  And step
end

The regular expression is little crazy but what it does is simple. It matches any step that ends in in (.\*) browser and will run that step in the given browser. This lets us change the scenario above to:

Scenario: Push for chat
  Given the following users exist:
    | Name  |
    | Steve |
    | Catie |
  And I am logged in as "Steve" in Steve's browser
  And I am logged in as "Catie" in Catie's browser
  When I go to the new message page
  And I fill in "Body" with "Hi, Steve!"
  And I press "Send"
  And I wait 2 seconds
  Then I should see "Hi, Steve!"
  And I should see "Hi, Steve!" in Steve's browser

It’s really a matter of personal preference, but I like both styles depending on the situation.

See It In Action!

We put together a simple chat app (using Pusher) that uses this method of testing simultaneous sessions in Cucumber. The code lives on GitHub and we have a live version up on Heroku. Check it out and let us know what you think.

steve@collectiveidea.com

Comments

  1. September 06, 2011 at 4:12 AM

    I really like bbq when it comes to scenarios with multiple users/browsers interacting at the same time - https://github.com/drugpl/bbq . I wonder if anyone tried to use bbq with cucumber. I only know test::unit and rspec usages in the real world. [Disclaimer: I am one of the bbq maintainers]

  2. derevjaginti@gmail.com
    Artjom Juferov
    February 19, 2015 at 11:59 AM

    A you sure that session are swiched? I tried but nothing happend?