Skip to content

Commit 0449b2f

Browse files
committed
Amend per @JonRowe's review
1 parent b690f70 commit 0449b2f

File tree

3 files changed

+86
-114
lines changed

3 files changed

+86
-114
lines changed

README.md

Lines changed: 47 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ In RSpec, application behavior is described
119119
**first in (almost) plain English, then again in test code**, like so:
120120

121121
```ruby
122-
RSpec.describe Member do #
123-
context 'in death' do # (almost) plain English
124-
it 'has a name' do #
125-
expect(dead_member.name).to eq('Robert Paulson') # test code
122+
RSpec.describe 'Post' do #
123+
context 'before publication' do # (almost) plain English
124+
it 'cannot have comments' do #
125+
expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid) # test code
126126
end
127127
end
128128
end
@@ -134,29 +134,25 @@ to generate a report of where the application
134134
conforms to (or fails to meet) the spec:
135135

136136
```
137-
$ rspec --format documentation spec/models/member_spec.rb
137+
$ rspec --format documentation spec/models/post_spec.rb
138138
139-
Member
140-
in death
141-
has a name
139+
Post
140+
before publication
141+
cannot have comments
142142
143143
Failures:
144144
145-
1) Member in death has a name
146-
Failure/Error: expect(dead_member.name).to eq('Robert Paulson')
147-
148-
expected: "Robert Paulson"
149-
got: nil
150-
151-
(compared using ==)
152-
# ./spec/models/member.rb:4:in `block (3 levels) in <top (required)>'
145+
1) Post before publication cannot have comments
146+
Failure/Error: expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid)
147+
expected ActiveRecord::RecordInvalid but nothing was raised
148+
# ./spec/models/post.rb:4:in `block (3 levels) in <top (required)>'
153149
154150
Finished in 0.00527 seconds (files took 0.29657 seconds to load)
155151
1 example, 1 failure
156152
157153
Failed examples:
158154
159-
rspec ./spec/models/member_spec.rb:3 # Member in death has a name
155+
rspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments
160156
```
161157

162158
For an in-depth look at the RSpec DSL, including lots of examples,
@@ -208,40 +204,24 @@ read the [official Cucumber documentation][].
208204

209205
## What tests should I write?
210206

211-
At the risk of grossly oversimplifying,
212-
there are two kinds of tests you can write:
213-
those that verify
214-
**an individual component of your application** (unit tests),
215-
and those that verify
216-
**how multiple parts of your application work as a whole** (integration tests).
217-
218-
RSpec Rails defines ten different _types_ of specs (7 unit, 3 integration)
207+
RSpec Rails defines ten different _types_ of specs
219208
for testing different parts of a typical Rails application.
220-
Many inherit from one of Rails’ built-in `TestCase` classes,
209+
Each one inherits from one of Rails’ built-in `TestCase` classes,
221210
meaning the helper methods provided by default in Rails tests
222211
are available in RSpec, as well.
223212

224-
- **Unit**
225-
226-
| Spec type | Corresponding Rails test class |
227-
| ---------------- | ---------------------------------- |
228-
| [model][] | |
229-
| [controller][]\* | [`ActionController::TestCase`][] |
230-
| [mailer][] | `ActionMailer::TestCase` |
231-
| [job][] | |
232-
| [view][] | `ActionView::TestCase` |
233-
| [routing][] | |
234-
| [helper][] | `ActionView::TestCase` |
235-
236-
- **Integration**
237-
238-
| Spec type | Corresponding Rails test class |
239-
| --------------- | ------------------------------------- |
240-
| [request][] | [`ActionDispatch::IntegrationTest`][] |
241-
| [feature][]\* | |
242-
| [system][] | [`ActionDispatch::SystemTestCase`][] |
243-
244-
_\* discouraged in favor new alternatives_
213+
| Spec type | Corresponding Rails test class |
214+
| -------------- | -------------------------------- |
215+
| [model][] | |
216+
| [controller][] | [`ActionController::TestCase`][] |
217+
| [mailer][] | `ActionMailer::TestCase` |
218+
| [job][] | |
219+
| [view][] | `ActionView::TestCase` |
220+
| [routing][] | |
221+
| [helper][] | `ActionView::TestCase` |
222+
| [request][] | [`ActionDispatch::IntegrationTest`][] |
223+
| [feature][] | |
224+
| [system][] | [`ActionDispatch::SystemTestCase`][] |
245225

246226
Follow the links above to see examples of each spec type,
247227
or for official Rails API documentation on the given `TestCase` class.
@@ -250,9 +230,6 @@ or for official Rails API documentation on the given `TestCase` class.
250230
>
251231
> Ask a hundred developers how to test an application,
252232
> and you’ll get a hundred different answers.
253-
> Some may insist on exhaustively testing every single method on every model;
254-
> others may contend that since integration tests capture model behavior anyway,
255-
> much unit testing is redundant and burdensome.
256233
>
257234
> RSpec Rails provides thoughtfully selected features
258235
> to encourage good testing practices, but there’s no “right” way to do it.
@@ -270,19 +247,17 @@ or for official Rails API documentation on the given `TestCase` class.
270247
[view]: https://www.relishapp.com/rspec/rspec-rails/docs/view-specs/view-spec
271248
[routing]: https://www.relishapp.com/rspec/rspec-rails/docs/routing-specs
272249
[helper]: https://www.relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
273-
[`ActionDispatch::IntegrationTest`]: https://edgeapi.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html
274-
[`ActionDispatch::SystemTestCase`]: https://edgeapi.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html
275-
[`ActionController::TestCase`]: https://edgeapi.rubyonrails.org/classes/ActionController/TestCase.html
250+
[`ActionDispatch::IntegrationTest`]: https://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html
251+
[`ActionDispatch::SystemTestCase`]: https://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html
252+
[`ActionController::TestCase`]: https://api.rubyonrails.org/classes/ActionController/TestCase.html
276253

277254
### I’m writing a spec file from scratch. How do I assign it a type?
278255

279-
Assuming you haven’t [modified the default `rails_helper.rb` configuration][],
280-
simply place the spec in the appropriate folder
256+
Simply place the spec in the appropriate folder
281257
(_e.g.,_ `spec/models/` for model specs)
282258
and RSpec will set its type automatically.
283259

284-
If you _have_ modified the default config
285-
(or if you just want to be extra explicit),
260+
If you want to be extra explicit,
286261
you can set the `:type` option at the top of the file, like so:
287262

288263
```ruby
@@ -297,12 +272,11 @@ RSpec.describe User, type: :model do
297272
### System specs, feature specs, request specs–what’s the difference?
298273

299274
RSpec Rails provides three types of specs
300-
for integration testing the application as a whole—in other words,
301-
specifying what the client sees when interacting with it.
275+
that do not directly correspond to any Rails application component.
302276

303277
#### System specs
304278

305-
Sometimes called **acceptance tests** or **browser tests**,
279+
Also called **acceptance tests**, **browser tests**, or **end-to-end tests**,
306280
system specs test the application from the perspective of a _human client._
307281
The test code walks through a user’s browser interactions,
308282

@@ -323,16 +297,21 @@ but `SystemTestCase` solves some longstanding configuration issues they had,
323297
so the RSpec team [officially recommends system specs][] over feature specs.
324298

325299
If you don’t have the luxury of upgrading,
326-
you’ll be limited to writing feature specs for your browser tests.
327-
They require [Capybara][],
328-
so make sure it’s listed in the `:test` group of your `Gemfile`:
300+
there’s no problem with using feature specs instead.
301+
Be sure to add [Capybara][] to the `:test` group of your `Gemfile` first:
329302

330303
```ruby
331304
group :test do
332305
gem "capybara"
333306
end
334307
```
335308

309+
(It’s actually required for both feature and system specs,
310+
but Rails includes it by default in versions 5.1+.)
311+
312+
[officially recommends system specs]: http://rspec.info/blog/2017/10/rspec-3-7-has-been-released/#rails-actiondispatchsystemtest-integration-system-specs
313+
[Capybara]: https://github.com/teamcapybara/capybara
314+
336315
#### Request specs
337316

338317
Request specs are for testing the application
@@ -341,18 +320,16 @@ They begin with an HTTP request and end with the HTTP response,
341320
so they’re faster than feature specs,
342321
but do not examine your app’s UI or JavaScript.
343322

344-
Request specs provide a high-level alternative to unit testing controllers.
345-
In fact, as of RSpec 3.5,
346-
the RSpec team [discourages controller specs entirely][]
347-
in favor of request specs.
323+
Request specs provide a high-level alternative to controller specs.
324+
In fact, as of RSpec 3.5, both the Rails and RSpec teams
325+
[discourage directly testing controllers][]
326+
in favor of functional tests like request specs.
348327

349328
When writing them, try to answer the question,
350329
“For a given HTTP request (verb + path + parameters),
351330
what HTTP response should the application return?”
352331

353-
[officially recommends system specs]: http://rspec.info/blog/2017/10/rspec-3-7-has-been-released/#rails-actiondispatchsystemtest-integration-system-specs
354-
[Capybara]: https://github.com/teamcapybara/capybara
355-
[discourages controller specs entirely]: rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5
332+
[discourage directly testing controllers]: rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5
356333

357334
## Contributing
358335

@@ -381,7 +358,3 @@ you can run the specs and Cucumber features, or submit a pull request.
381358
anywhere other than system specs and feature specs.)
382359

383360
[additional configuration is required]: http://rubydoc.info/gems/rspec-rails/file/Capybara.md
384-
385-
### RSpec style guides
386-
387-
* [Better Specs](http://www.betterspecs.org/)

features/matchers/have_http_status_matcher.feature

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ Feature: `have_http_status` matcher
55

66
* numeric
77
* name (defined in `Rack::Utils::SYMBOL_TO_STATUS_CODE`)
8-
* type (`:success`, `:missing`, `:redirect`, or `:error`)
8+
* `ActionDispatch::TestResponse` alias (`:success`, `:missing`, `:redirect`, or `:error`)
99

1010
The matcher works on any `response` object. It is available for use in
1111
[controller specs](../controller-specs), [request specs](../request-specs), and [feature specs](../feature-specs).
1212

13-
Scenario: Checking a response code by number
13+
Scenario: Checking a numeric response code
1414
Given a file named "spec/controllers/application_controller_spec.rb" with:
1515
"""ruby
1616
require "rails_helper"
@@ -35,7 +35,7 @@ Feature: `have_http_status` matcher
3535
When I run `rspec spec`
3636
Then the examples should all pass
3737

38-
Scenario: Checking a response code by name
38+
Scenario: Checking a symbolic response code (by name)
3939
Given a file named "spec/controllers/application_controller_spec.rb" with:
4040
"""ruby
4141
require "rails_helper"
@@ -60,7 +60,7 @@ Feature: `have_http_status` matcher
6060
When I run `rspec spec`
6161
Then the examples should all pass
6262

63-
Scenario: Checking a response code by type
63+
Scenario: Checking a symbolic response code (by `ActionDispatch::TestRespose` alias)
6464
Given a file named "spec/controllers/application_controller_spec.rb" with:
6565
"""ruby
6666
require "rails_helper"

features/view_specs/view_spec.feature

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
Feature: view spec
22

3-
View specs should be placed in `spec/views`,
4-
and verify the content of view templates in isolation
5-
(that is, without invoking a controller).
6-
7-
Overview
8-
--------
3+
View specs are marked by `:type => :view`
4+
or if you have set `config.infer_spec_type_from_file_location!`
5+
by placing them in `spec/views`.
96

10-
View specs generally follow three steps:
7+
Use them to test the content of view templates in isolation
8+
(that is, without invoking a controller).
9+
They generally follow three steps:
1110

1211
```ruby
1312
assign(:widget, Widget.new) # sets @widget = Widget.new in the view template
@@ -18,38 +17,10 @@ Feature: view spec
1817
```
1918

2019
1. Use the `assign` method to set instance variables in the view.
21-
Technically, `@widget = Widget.new` would work too,
22-
but RSpec doesn't officially support this pattern.
23-
(It only works as a side effect of the fact that
24-
view specs include `ActionView::TestCase` behavior.
25-
Be aware that it may be made unavailable in the future.)
2620

2721
2. Use the `render` method to render the view.
2822

29-
3. Set expectations against the resulting `rendered` object.
30-
31-
Notes
32-
-----
33-
34-
* To apply a layout to the view template being rendered,
35-
be sure to specify both the template and layout explicitly:
36-
37-
```ruby
38-
render :template => "events/show", :layout => "layouts/application"
39-
```
40-
41-
* View specs expose a `controller` object,
42-
which can be used to set expectations about the route (path + parameters)
43-
to the view template being tested.
44-
Some attributes of this object are based on
45-
the name of the view itself—that is, in a spec for `events/index.html.erb`:
46-
47-
* `controller.controller_path == "events"`
48-
* `controller.request.path_parameters[:controller] == "events"`
49-
50-
Be careful of these automatically-inferred values
51-
when writing specs for partials
52-
(which may be shared across multiple controllers).
23+
3. Set expectations against the resulting rendered template.
5324

5425
Scenario: View specs render the described view file
5526
Given a file named "spec/views/widgets/index.html.erb_spec.rb" with:
@@ -122,6 +93,34 @@ Feature: view spec
12293
When I run `rspec spec/views`
12394
Then the examples should all pass
12495

96+
Scenario: View specs can render templates in layouts
97+
Given a file named "spec/views/widgets/widget.html.erb_spec.rb" with:
98+
"""ruby
99+
require "rails_helper"
100+
101+
RSpec.describe "rendering the widget template" do
102+
context "with the inventory layout" do
103+
it "displays the widget" do
104+
assign(:widget, Widget.create!(:name => "slicer"))
105+
106+
render :template => "widgets/widget.html.erb", :layout => "layouts/inventory"
107+
108+
expect(rendered).to match /slicer/
109+
end
110+
end
111+
end
112+
"""
113+
And a file named "app/views/widgets/widget.html.erb" with:
114+
"""
115+
<h2><%= @widget.name %></h2>
116+
"""
117+
And a file named "app/views/layouts/inventory.html.erb" with:
118+
"""
119+
<%= yield %>
120+
"""
121+
When I run `rspec spec/views`
122+
Then the examples should all pass
123+
125124
Scenario: View specs can have description that includes the format and handler
126125
Given a file named "spec/views/widgets/widget.xml.erb_spec.rb" with:
127126
"""ruby

0 commit comments

Comments
 (0)