Skip to content

Instantly share code, notes, and snippets.

@ramontayag
Created November 13, 2012 05:58
Show Gist options
  • Save ramontayag/4064226 to your computer and use it in GitHub Desktop.
Save ramontayag/4064226 to your computer and use it in GitHub Desktop.
Capybara that is cucumber-like

From what I understood this morning, the concern Steve had was to be able to use the acceptance specs as a communication tool with the clients, whether directly (the clients read it) or indirectly (the clients do not read it).

The concern from me (at least) is the maintainability of the Cucumber steps. Here are some example:

  • Projects where there were so many cucumber steps that it became hard to figure out what each step did
  • Projects that tried to be too DRY with the steps the regexps became difficult to handle
  • Projects where a lot of set up was required, and the steps to create the users like became long and too descriptive (Given an active user exists that last logged in 2 years ago)
  • Projects whose Cuke steps shared World-wide variables (@project) that were used across steps

For me, using Capybara directly solves this. But, I must agree that only developers can read them. Why not have the best of both worlds?

Given this rspec file:

feature 'User can disable their own account' do

  background do
    given 'a user Bob exists' do
      @user = FactoryGirl.build_stubbed(:activated_user,
                                        username: 'Bob')
    end
  end

  scenario 'Disables own account' do
    given 'I am logged in as Bob' do
      sign_in_as @user
    end

    when 'I go to my account page' do
      visit account_path(@user)
    end

    when 'I click on the button to disable my account' do
      click_button 'Disable my account'
    end

    then 'I should see the message that I am logged out' do
      within '.flash-messages' do
        should_see 'You have been logged out. We will miss you.'
      end
    end
  end

end

The output would contain something like this:

Given I am logged in as Bob
When I go to my account page
And I click on the button to disable my account
Then I should see the message that I am logged out
  expected page to contain 'You have been logged out. We will miss you.' but
  it did not
@padi
Copy link

padi commented Nov 14, 2012

My two cents:

Aside from the global variables, what ultimately added complexity in Cucumber is the regex. When doing BDD (presumably with a client), I think the two indispensable components that we are looking for are:

  1. Connextra Format/Gherkin syntax - Gherkin is the part of cucumber that deals with the .feature files. Based from Steve's reasons for choosing Cucumber, I suspect that it's really Gherkin that we really want. Basically, we want business analysts (spec/product/domain guy) to articulate specs without dealing with the internals of the app they want us to create.
  2. Step Definitions - The code that will be driven by #1 (Capybara and party). In Cucumber's case, I don't like that fact sometimes regex step defs can be a pain to use. I don't want to debug some regex everytime I create a step definition with parameters to match. Frankly, they're not readable by humans.

I think it's overkill to use regex in step defs just for the sake of DRYness and being able to accept parameters. Like what Steve said, steps don't have to be as DRY as our codebase. The right way of describing the scenarios should be in declarative way anyway. Ergo, less regex needed.

Gladly, there are already a number of available alternatives to Cucumber that may address our specific needs. Here are my first impressions of each option based on their docs/description:

  1. Steak - basically this is RSpec + Capybara niceties. It throws away Gherkin. We might use this internally, but I'm pretty sure that for client-based work, we wouldn't.
  2. Turnip
    • it has Gherkin. +1!

    • step definitions are just in this format (easier than regex):

      module SomeSteps
      step "there is/are :user_count users" do |:user_count|
      # some ruby code here e.g. capybara
      end
      end

    • You control the scope of specific steps via RSpec.configure, since steps are defined in modules. At the very least, this can easily solve step conflicts.

  3. Spinach
    • it has Gherkin too!
    • Based on their blog post, the guys who made this basically had the same complaint we had for Cucumber: the way steps defs are implemented in Cucumber suck.
    • Step definitions for a Feature: Some Feature are either in that associated SomeFeature < Spinach::FeatureSteps class, or in the include-d modules. No surprises. Less chances for conflict.
    • Want to encapsulate/expose certain step defs/variables/methods? Do it the Ruby way: private-ize methods,include Modules. Whatever floats your boat.

Personally, I would like to try out Spinach first, simply because it was borne out of the same frustration we had for Cucumber (step definitions). This is the tool that satisfies our minimum requirements.

What do you think?

(This discussion is worthy of a tech talk, a blog post, and/or topic for the upcoming meetup.)

@padi
Copy link

padi commented Nov 14, 2012

Corrected Markdown format: https://gist.github.com/ec125767b0ac9ddb3093

Why can't we edit gist comments even for a few minutes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment