Jeff Kreeftmeijer

Steak: because Cucumber is for vegetarians!

2010-05-03
Capybara has an RSpec DSL now, allowing you to steak-acceptance testing without Steak. Be sure to read Acceptance testing using Capybara’s new RSpec DSL too.

I’m not going to tell you why you should write acceptance (or integration) tests, but you should. I used Cucumber for a while now and I love it, but I think writing my tests in a business-readable domain-specific language and translating them into Ruby using step definitions is a bit too much sometimes. And I’m not a vegetarian.

Luckily, we have Steak by @cavalle:

“Steak is like Cucumber but in plain Ruby. No explicit givens, whens or thens. No steps, no English, just Ruby: RSpec and Steak. That’s all.”

Right now the stable version of Steak only works with Rails 2.x and RSpec 1.x, but there’s a Rails 3 branch where some work is being done to support Rails 3.x and RSpec 2.×. I’ve been using that one, but this article should also be fine for you when you’re on Rails 2.×.

Installation

OK, throw this into your Gemfile (I’m specifying the 0.4.0.a4 release here, that’s the most recent alpha release from the rails3 branch). Also, I’ll be using Capybara for this example:

group :test do
  gem 'steak', '0.4.0.a4'
  gem 'capybara'
end

And install your bundle:

$ bundle install

Or — if you’re using Rails 2.x — put this in config/environment.rb (Just using the stable Rails 2 release of Steak here):

config.gem 'steak'
config.gem 'capybara'

And run:

$ rake gems:install RAILS_ENV=test

Now you can use the Steak generators to set everything up. You have to specify which driver you’re using (Steak also has a generator for Webrat):

$ rails generate steak --capybara # or -- webrat

Please remember to use script/generate instead of rails generate when on Rails 2.×.

The generator created the spec/acceptance directory in your project, in which you can find acceptance_helper.rb and the support directory. The support directory holds paths.rb — which should be familiar if you’ve used Cucumber before — and helpers.rb.

Acceptance specs

Now, let’s write our first acceptance spec — no, we’re not calling it a “feature”. It’s a spec. — by using another generator (I’m creating an articles spec here):

$ rails generate acceptance_spec articles

Steak generated spec/acceptance/articles_spec.rb, which looks like this:

require File.dirname(__FILE__) + '/acceptance_helper'

feature "Feature name", %q{
  In order to ...
  As a ...
  I want to ...
} do

  scenario "Scenario name" do
    true.should == true
  end

end

If you’re a Cucumber user, the feature description should look familiar. I’ll try to describe what I’m doing like this:

feature "Articles", %q{
  In order to have an awesome blog
  As an author
  I want to create and manage articles
} do

Great. On to our first scenario. In the articles index we want to show all articles in a list.

scenario "Article index" do
  Article.create!(:title => 'One')
  Article.create!(:title => 'Two')
  visit article_index
  page.should have_content('One')
  page.should have_content('Two')
end

First, I create two articles called “One” and “Two” (please, use a tool like Machinist for that). Then I visit article_index and check if the article titles show up. Really simple.

The last thing to do to get this thing running is to create the path for article_index in spec/acceptance/support/paths.rb:

module NavigationHelpers
  def homepage
    "/"
  end

  def article_index
    "/articles"
  end
end

Simple, right? I’m not going to walk you through building and testing this application here right now, but I think you get the point.

Minimalist acceptance testing

Steak just provides some aliases (like scenario and feature) for RSpec’s methods “providing you with the language of acceptance testing”. Here’s a snippet from Steak’s library:

module Spec::Example::ExampleGroupMethods
  alias scenario example
  alias background before
end

module Spec::DSL::Main
  alias feature describe
end

So, if you know your RSpec, the only thing you’ll have to do is dive into Capybara (or Webrat) for a bit and you’ll be writing acceptance specs in no time.

Running your spec

You might have guessed, but running your acceptance specs is exactly the same as running any other spec. After all, it’s just a minimal layer on top of RSpec:

$ spec spec/acceptance/articles_spec.rb

Cucumber vs Steak?

Cucumber is highly focused on creating a business-readable DSL, and does so perfectly. I understand the thought behind making stakeholders able to read what’s going on in their projects, but I wonder how many people actually do this. Also, one might argue that — from a Ruby programmer’s perspective — Steak’s specs are in fact more readable than Cucumber’s.

Steak takes away the extra step of translating everything from English to Ruby and is incredibly easy to learn (especially when you have some RSpec experience). It’s completely incomparable to Cucumber though and which one to choose is simply a matter of taste. And I love me some Steak.