bdd labs rspec testing

Getting “by” with rspec feature specs

If you find that you are making your rspec feature specs longer and longer to cram more coverage in or to prevent the setup costs for more, shorter tests, you will probably have found that it becomes very hard to figure out what’s going on. If you find yourself wanting to add comments to your specs to state what is happening, like so:

it "allows the user to manage her account" do
  #Login user
  visit "/login"
  fill_in "Username", :with => "jdoe"
  fill_in "Password", :with => "secret"
  click_button "Log in"

  expect(page).to have_selector(".username", :text => "jdoe")

  #Account management
  click_link "Account"
  expect(page).to have_content("User Profile")
  ...
end

Why not throw this code into your spec_helper.rb…

def by(message)
  if block_given?
    yield
  else
    pending message
  end
end

alias and_by by

… and replace the above section with this:

it "allows the user to manage her account" do
  by "logging in the user" do
    visit "/login"
    fill_in "Username", :with => "jdoe"
    fill_in "Password", :with => "secret"
    click_button "Log in"

    expect(page).to have_selector(".username", :text => "jdoe")
  end

  and_by "managing the account" do
    click_link "Account"
    expect(page).to have_content("User Profile")
  end
  ...
end

Instead of having comments, which I personally am trained to a) ignore and b) expect to be outdated, I now have a block which denotes that a part of the spec as doing something specific. I like to think that the benefit of the block over the comment is that

  • it has a start and an end (and thus adds programmatic structure),
  • it adds indentation (and thus visual structure),
  • it can have behavior (like the use of rspec’s pending).