Turnip: A Tasty Cucumber Alternative?

Harlow Ward

''

We’ve used Cucumber heavily and successfully on client work, internal projects, and open source. We also love RSpec, so when we heard that Turnip would give the ability to run Gherkin based integration tests in our RSpec suite it was a no-brainer for us to try it out on a project.

Highlights of Turnip

  • Integrates directly into your RSpec test suite
  • Features and Step definitions live in the spec directory
  • No need to maintain two configuration files
  • Uses Ruby style symbols instead of regular expressions in step definitions
  • No need to write Given/When/Then in the step definitions file
  • Speed boost when running unit tests and integration tests together

We use Cucumber integration tests in thoughtbot’s clearance gem. In the example below I remove Cucumber and replace it with Turnip.

Steps used to change from Cucumber to Turnip

  • Set up your features directory inside the spec directory
  • Remove the Given/When/Then’s from the step definitions
  • Replace regular expressions in the step definitions with Ruby style symbols

Cucumber and Turnip use the same Gherkin syntax:

Scenario: Visitor signs up with valid data
When I sign up with "email@example.com" and "password"
Then I should be signed in

Change the step definitions from Cucumber to Turnip style:

# Cucumber step definition
When /^I sign up (?:with|as) "(.*)" and "(.*)"$/ do |email, password|
visit sign_up_path
page.should have_css("input[type='email']")
fill_in "Email", :with => email
fill_in "Password", :with => password
click_button "Sign up"
end

# Turnip step definition
step "I sign in with/as :email and :password" do |email, password|
visit sign_in_path
page.should have_css("input[type='email']")
fill_in "Email", :with => email
fill_in "Password", :with => password
click_button "Sign in"
end

Run the test suite

An advantage having everything running through RSpec is we get an immediate boost in speed when running the whole test suite. With Cucumber running Rake will run the RSpec and Cucumber tests (the Rails environment will be loaded twice). With Turnip all tests run through directly through RSpec (the Rails environment is only loaded once).

We save around 12 seconds when running the entire suite:

# Rake running RSpec and Cucumber
~/Development/clearance_cucumber(master) $ time rake
/Users/training/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -S rspec ./spec/controllers/pages_controller_spec.rb ./spec/helpers/application_helper_spec.rb

Finished in 0.10696 seconds
1 example, 0 failures
/Users/training/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -S bundle exec cucumber --profile default
Using the default profile...
.................................................

13 scenarios (13 passed)
49 steps (49 passed)
0m1.729s
rake 19.97s user 2.71s system 98% cpu 22.960 total

# RSpec with Turnip
~/Development/clearance_turnip(master?) $ time rspec
..............

Finished in 1.84 seconds
14 examples, 0 failures, 0 pending
rspec 8.85s user 1.06s system 95% cpu 10.362 total

Takeaways

  • Great light-weight solution for anyone already using RSpec
  • Step definitions easier to read than their Cucumber counterparts
  • Low barrier to entry for developers new to integration testing

End-to-end testing with RSpec integration tests and Capybara