Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
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).

Comments
  1. Robbie Clutton says:

    You might also be interested in something similar, SimpleBDD

    https://github.com/robb1e/simple_bdd

  2. Jared Carroll says:

    Stephan,

    I often run across tests/specs with names that are out of date. The body of the test/spec was updated but the name of the test wasn’t.

    I could see #by blocks not getting updated and having the same issues that a comment has.
    Why do you think #by blocks are less likely to be out of date than comments? A #by block does have better syntax highlighting and indention to set it apart; giving it more importance in a codebase. I’m just not sold on adding code to my test suite that does nothing other than improve the documentation.

  3. Stephan Hagemann says:

    Robbie,

    Indeed these approaches are very similar. With SimpleBDD I structure my specs using methods instead of using blocks as I am doing.

    The reason I would rather not use methods for most of my structure is that I don’t want to encourage reuse. My intent is to cover every bit of the app with one happy path request spec. For this intention, introducing SimpleBDD seems a bit much.

  4. Stephan Hagemann says:

    Jared,

    I suggest this technique to _replace_ comments. While you are right that spec descriptions can fall victim to the same problems as comments, they are at least no worse. Similarly, these blocks are no worse then comments.

    That’s certainly not the best kind of answer, and I will post an update as soon as I have a better solution :)

  5. Robbie Clutton says:

    I wish I got email notifications on replies – sorry for the delayed response.

    I completely understand wanting a single happy path test and we’ve found that SimpleBDD can still assist this by giving a small, easily grokable, portion of the file describing the intent of the test with the implementation being ‘below the fold’ and out of the way.

  6. Stephan Hagemann says:

    A project that I have heard from recently extended the by and and_by idea further: they are using “it_also” as another alias.

    They are also following the convention of it_also’s for large blocks that would typically be their own “it”s. Additionally, they try to keep these it_alsos independent so that one can comment out one block without affecting the others.

    I think that’s pretty cool.

  7. Hunter Gillane says:

    Another benefit of using blocks instead of comments is code folding in your IDE. This is especially beneficial if you have a single larger happy path test.

  8. Rob Head says:

    Under what conditions would you move the block into a well-named helper method instead?

    As I see it, we gain separation, readability, and reusability without adding a new structural concept.

  9. Stephan Hagemann says:

    Hi Rob,

    I use this technique exclusively for feature specs, which I tend to make somewhat longer and happy path centered. In those situations I would split out only that into a helper method that needs to be repeated in several tests, e.g., a helper for clicking the link to the login page, entering username and password and submitting the form.

    If there were repetition between these happy path tests I would probably consider that test duplication and work on that rather than the extracting of a helper method. In that way I specifically am trying to avoid separation as it might encourage test duplication.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *