RSpec vs. Cucumber

So far, I’ve been using RSpec for testing my Rails apps simply because that’s what railstutorial.org emphasizes.

However, I am in the process of trying out Cucumber. I like the fact that it’s in plain English, and this is an asset for communicating with clients or other people who aren’t Rubyists. Migrating to Cucumber sounds like a good idea.

I’m curious about what you prefer. Do any of you know Cucumber well, yet still prefer RSpec? If so, why?

Jason, I highly recommend picking up The RSpec Book, published by Pragmatic Programmers [1]. It discusses both RSpec and Cucumber: when and how to use both of them. They actually work well together, and complement each other in many ways.

For me, RSpec is the way I like to perform unit and functional testing, while Cucumber, with the Gherkin language, seems ideal for describing and testing the larger elements of the application, and are quite well suited to documenting stories as one does in Agile development, and implementing them to provide acceptance tests for features and releases. Cucumber is useful also to drive external testing of web applications via Capybara or Watir, and also for driving command line tools via Aruba.

So, for me, it's not really one *or* the other, it's both, and deciding what level of testing is needed and how easy it will be to implement that test. It is possible, I suppose, to use only one of them, but the level of detail expressible in RSpec seems to me to be ideal at the lowest level, and the large scale expressibility with Gherkin makes Cucumber more relevant to higher levels of abstraction that can be written and read by non-technical people fairly easily.

[1] Search

My rule of thumb : Cucumber for integration testing ( output = documentation of features ) and RSpec for unit testing ( output = documentation of code )

I know a lot people may disagree, but I believe that using Cucumber is counterproductive as writing plain English text and then parsing it with regular expressions is somewhat overkill and error prone. I think anyone should use Cucumber only if they have a strong reason to. And some well known Rails developers such as Michael Hartl (Ruby on Rails Tutorial) and Aaron Sumner (Everyday Rails Testing with RSpec) are rather agree on that.

Agreed! I usually do my acceptance-level tests in straight Ruby. (Though with the aid of gems like Capybara and so on for page content access, click simulation, form filling, etc.) The Cucumber (tempted to just say Cucu!) way would be to write:

  When I build a new large, blue, left-handed veeblefetzer, with a belt in the back

Then I'd have to create a step definition that has to parse the size, color, handedness, and/or belting (or lack thereof) of a new veeblefetzer, with those various things all being optional (else I'd have to specify them when I don't care), and look at whether I said "create" or "build" to tell which it should do. Alternately, a BUNCH of step defs so they're not optional but key off the regex being satisfied. By skipping Cucumber altogether, I can just write a normal Ruby function call:

  when_i_make_a_veeblefetzer(size: :large,                              belt: :in_the_back,                              save: false)

This is close enough to plain English that any non-geek should be able to understand it just fine. I could even make the capitalization "normal" if they want. Anyway, then I make a normal Ruby function like "def when_i_make_a_veeblefetzer(options)" and have it parse them as a plain old hash, getting anything unspecified from a hash of defaults (such as how this one's color and handedness don't matter). No need to futz around with complex regexes. Usually I can pass most of the options-hash straight to either FactoryGirl or the class's .new method, other than filtering out "save" to determine whether to call build or create.

My tests may have 99 problems, but maintaining hairy regexes ain't one.

-Dave

Rspec is a popular framework for unit testing and Cucumber is used for integration testing and behavior driven development

Unit tests with rspec confirm that small, discrete portion continue working as developers add features.

Integration tests built with cucumber determine wether the application’s features work as expected,testing the application from user point of view.

Thanks

Rspec is a popular framework for unit testing and Cucumber is used for integration testing and behavior driven development

It's pretty strange to hear since RSpec description is "BDD for Ruby". More than that, recent versions of RSpec for Rails (v2.12.0 or greater) support feature specs for integration testing whose syntax is very similar to Cucumber features. For more information see: http://www.andylindeman.com/2012/11/11/rspec-rails-and-capybara-2.0-what-you-need-to-know.html

I’m a big fan of RSpec, and I use it all the time. But I think Cucumber wins hands down in generating readable test outputs which can be important in many scenarios. Let me explain one such scenario which I faced in one of my projects.

I was working on a Rails API app which would serve as the backend for a JS/native client running on platforms unknown to me. The API client was developed by a remote team separately. The remote developers would write client code to consume the APIs looking at an API documentation which would ideally describe the requests and all the possible responses from the APIs along with examples. The documentation would reflect the latest changes and it should be possible to obtain the documentation for every commit. The documentation would also ideally show the health of the APIs, so the client developers would know, for any given commit, which of the APIs work as expected ( mainly because I didn’t want to answer questions like “Does the user listing API work, because I’m always getting a 403 status?” ) , If the API doc is green, it means it should work for a correct request. I used Cucumber to write integration tests and also for all the above requirements, and it worked well for me.

Here’s an example of the documentation cucumber would create for my user sign up API:

Feature: Sign Up

Background:

Given I send and accept JSON

Scenario: Passwords do not match

When I send a POST request to “/api/users” with the following:

“”"

{

“user” : {

“first_name”: “Kobe”,

“last_name”: “Bryant”,

“email”: “kobe@gmail.com”,

“password”: “kobe1234”,

“password_confirmation”: “kobe12345”

}

}

“”"

Then the response status should be “422”

And the JSON response should be:

“”"

{“errors” : [“Password confirmation doesn’t match Password”]}

“”"

RSpec can test this scenario alright, and it would be very much readable for any Ruby programmer. But I can’t imagine a way to produce such a readable output with RSpec which could be read by a non Ruby developer, in my case a client side dev who may not be too interested in opening a ruby file to understand the API. But with cucumber, you are forced to think of a scenario as a sequence of steps, which really helped me in my case. My only problem with cucumber was writing regexes. But that’s a small threshold to cross (I created some vim snippets to help me with the common regex templates) and it’s not going to be one of your 99 problems.

Cucumber worked amazingly well for me, but I may not use it all the time. I can’t think of a reason why I shouldn’t use it for every project, though. Laziness probably.

My personal experience, of course, but the only time I’ll ever write Cucumber features is if plain-english acceptance tests are a requirement. Otherwise (95% of the time), I’m quite happy with the RSpec/Capybara combo. The overhead of having to wire together plain-english to regular expressions just doesn’t pay off in the end for normal acceptance testing.

Hi Emil,

Can you show me that example in cucumber but written in Rspec I been trying to solve that problem and dont seem to be able to send the parameters in json to the page using rspec + capybara.

all the best,

Andre

Andre, what you need is Rack::Test, not capybara.

Not sure what you mean here. Capy uses Rack::Test by default: https://github.com/jnicklas/capybara#selecting-the-driver

I meant to say simply use Rack::Test to make the requests while testing, Capybara isn’t useful for interacting with an API directly.