119

What is the conceptual difference between Rspec's feature specs and request specs?

From the feature spec docs:

Feature specs are high-level tests meant to exercise slices of functionality through an application. They should drive the application only via its external interface, usually web pages.

And for request specs:

Request specs provide a thin wrapper around Rails' integration tests, and are designed to drive behavior through the full stack, including routing (provided by Rails) and without stubbing (that's up to you). With request specs, you can:

  • specify a single request
  • specify multiple requests across multiple controllers
  • specify multiple requests across multiple sessions

I know that feature specs use Capybara and request specs do not. But that hardly merits different concepts.

gnoll110
  • 332
  • 1
  • 4
  • 11
harm
  • 10,045
  • 10
  • 36
  • 41

1 Answers1

153

The conceptual difference is that you're usually testing a user story, and all interaction should be driven via the user interface. That's where Capybara comes in. A request spec is still testing the behavior of your application and doesn't have the expectation of readability that an acceptance test would have. So, feature is there for the improved syntax for acceptance tests.

Technical differences include request specs wrap Rails integration tests, whereas feature specs don't. This means with request specs you can use methods get, post, put, delete and assert against response. With feature specs you should drive all interaction through the browser and use methods like visit and assert against the page.

I'd recommend reading the feature_spec.feature in the rspec-rails source code on github.

starball
  • 20,030
  • 7
  • 43
  • 238
Richard Jordan
  • 8,066
  • 3
  • 39
  • 45
  • 2
    So would you recommend using both feature and request specs, or is one or the other sufficient? (Being new to TDD...) – robertwbradford Mar 18 '14 at 18:12
  • 2
    I use both, @robertwbradford. I use feature specs to drive my outside in tests - testing the user experience and then building out the functionality using unit tests. I use request specs for testing responses - e.g. in a sessions_spec I may have a describe `"GET /login"` block with expectations in `it` blocks such as `expect(response.status).to eq(200)` and `expect(response).to render_template(:new)`, or in a `describe "POST /sessions"`, a `context "with valid credentials"` block, with `expect(response).to redirect_to(user)` and `follow_redirect!; expect(response.body).to include("Signed in")` – Richard Jordan Mar 18 '14 at 21:51
  • 5
    And do you use controller specs too? It seems there's a bit of duplication between what you test in request specs and what is normally tested in controller specs. – Ernesto Mar 25 '14 at 21:54
  • I find massive, unnecessary duplication between feature and request specs. For example, in Richard's comment above, a feature spec would already test for 200 status by making any assertion against the page. The new session request would be equally covered in a generic feature spec that clicks 'Sign in' and tests for response to include 'Signed in'. Sure, it might not test the redirect. So what? What if you want to replace the normal request/response with a single page application and use an angular router instead? Your feature specs still hold up. – Damien Roche May 14 '14 at 09:11
  • 6
    Saying that, the above linked post clearly describes the differences. Use request specs to test via API, use feature specs to test via frontend. – Damien Roche May 14 '14 at 09:18
  • 2
    @RichardJordan: A question: In feature specs, would you recommend to use Rails paths (i.e `visit users_path`) or hardcoded strings (`visit '/users'`)?. Personally, I prefer not to use any app internals in those kind of specs. – tokland Dec 03 '14 at 17:25
  • 1
    @tokland I agree with your instinct on this - I prefer not to test app internals for such things - visit the path as someone would put it in the browser, that should be the test IMHO – Richard Jordan Dec 05 '14 at 01:30
  • article link is broken. – Dobler Jan 25 '17 at 10:47
  • I agree with @DamienRoche. Use request spec for API. For example, test an endpoint that returns a json. Use feature spec for frontend test. For example, user fills an input and clicks buttons. – Gundam Meister Mar 20 '19 at 19:10