Veezus Kreist

Integration testing without cucumber

There are three main testing cliques at Hashrocket: the Fakirs, the Derivatives, and Team Zombie. Fakirs are so named because they stub and mock everything – making it all fake. Derivatives are the exact opposite, preferring to forego unit testing in most cases and just write integration tests that interact with the code through a browser. Team Zombie (the “decomposers”) had just the right mix for me: integration testing for core business value, unit testing individual methods, and stubbing them elsewhere. Personally, such a technique helped me with my data models: too many stubs means too complex a model.

Additionally, I’ve never been in love with cucumber; the regexes drive me crazy, and I’ve never had a client who wants the (admittedly very nice) story formatting that it gives. I’ve been working on a green-field app this week at Hashrocket for the first time in months and it’s given me an opportunity to try out a new integration testing methodology and has called into serious question my membership in Team Zombie. Tip of the hat to Sandro for turning me and Voxdolo on to this technique.

Here’s a quick and dirty implementation of integration testing with rspec and webrat on Vurl (source), using the techniques I picked up this week.

Configure your application

In config/environment.rb:

1
2
config.gem 'rspec-rails', :lib => false, :version => '1.2.7.1'
config.gem "webrat", :version => "0.5.3", :lib => false

In spec/spec_helper.rb:

1
2
3
4
5
6
7
8
9
10
11
require 'webrat'

Webrat.configure do |config|
    config.mode = :rails
end

Spec::Runner.configure do |config|
  ...
  config.include(Webrat::Matchers, :type => [:integration])
  ...
end

Create your spec

1
mkdir spec/integration

Here’s my spec/integration/create_vurl_spec.rb file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))

describe "Create Vurls" do
  it "redirects to the vurl show page" do
    submit_vurl 'http://google.com'
    current_url.should == vurl_url(Vurl.last)
  end 
  it "shows a success message" do
    submit_vurl 'http://google.com'
    response.body.should include('Vurl was successfully created')
  end 
  it "creates a vurl" do
    submit_vurl 'http://veez.us'
    Vurl.last.url.should == 'http://veez.us'
  end 
end

def submit_vurl url 
  visit root_path
  fill_in "vurl_url", :with => url 
  click_button 'Vurlify!'
end

Run your spec

Since your spec file ends in _spec.rb, it will run with the rest of your spec files. Just give your app a

1
rake spec

A note about rspec matchers

When running these rspec tests, we don’t have access to the rspec matchers. So things like

1
flash[:error].should_not be_nil

won’t work because the be_nil matcher isn’t loaded. You can always fall back to Test::Unit:

1
assert_not_nil flash[:error]

Or, better yet, test that your content is within the body:

1
response.body.should include('There was a problem creating your vurl')

This method of integration testing feels much lighter to me; the tests take less time than cucumber equivalents and we’re not writing and maintaining a separate set of regexes to go with the app.

  1. Evan David Light says:

    One feature of Cucumber that Joseph Wilk got me to appreciate is that it forces you to explain why you have implemented a set of features--the "In order to <accomplish one thing> As a <role>, I want to <do something>". Without it, I have occasionally found myself looking at some olders specs and wondering "Why did I write these?"''

    I absolutely agree, and vociferously spoke to several people about Cucumber adding yet *another* layer of abstraction with the "call-by-regexp" feature (to connect the plain text to the matching blocks).

    However, I'm also finding that my specs can get awfully deeply nested at times--a problem that could just as easily occur with any nested setup BDD framework (i.e., rspec, shoulda, context, micronaut, etc.). This has put me in some unusual spots the past. I'm working on an alternate solution using several Cucumber features but as an internal DSL instead.

  2. Sandro Turriate says:

    It seems strange that the rspec matchers aren't included when running integration tests. I imagine this is just an oversight, rspec-rails is all about re-opening Rails classes to include the rspec matchers... they must've forgotten about integration tests.

    Add this to your spec helper to get the regular rspec matchers working:
    class ActionController::Integration::Session; include Spec::Matchers end

  3. Jon Larkowski says:

    This looks like a good nuts and bolts solution for programmers who can't understand Cucumber. ;) Haha. Thanks for the post, man. I will have to check this out for serious.

  4. Matt Van Horn says:

    Nice post - I'm trying this out in my current project, because most of my controllers are inherited_resources style, and the magic therein doesn't play nice with rspec unit tests.

  5. Bypereirm says:

    Hello. Often the Internet can see links like [url=http://www.whitehutchinson.com/aboutus/]Buy cialis without prescription[/url] or [url=http://www.rc.umd.edu/bibliographies/]Buy cialis without prescription[/url]. Is it safe to buy in pharmacies such goods?

Post a comment


(lesstile enabled - surround code blocks with ---)