rspec-rails 3.5.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/Capybara.md +6 -55
  4. data/Changelog.md +321 -62
  5. data/README.md +265 -493
  6. data/lib/generators/rspec/channel/channel_generator.rb +12 -0
  7. data/lib/generators/rspec/{observer/templates/observer_spec.rb → channel/templates/channel_spec.rb.erb} +1 -1
  8. data/lib/generators/rspec/controller/controller_generator.rb +21 -4
  9. data/lib/generators/rspec/controller/templates/request_spec.rb +14 -0
  10. data/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
  11. data/lib/generators/rspec/feature/feature_generator.rb +4 -4
  12. data/lib/generators/rspec/generator/generator_generator.rb +24 -0
  13. data/lib/generators/rspec/generator/templates/generator_spec.rb +6 -0
  14. data/lib/generators/rspec/helper/helper_generator.rb +1 -1
  15. data/lib/generators/rspec/install/install_generator.rb +4 -4
  16. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +27 -14
  17. data/lib/generators/rspec/integration/integration_generator.rb +4 -4
  18. data/lib/generators/rspec/integration/templates/request_spec.rb +1 -1
  19. data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  20. data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  21. data/lib/generators/rspec/mailer/mailer_generator.rb +2 -1
  22. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -2
  23. data/lib/generators/rspec/mailer/templates/preview.rb +1 -1
  24. data/lib/generators/rspec/model/model_generator.rb +6 -5
  25. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  26. data/lib/generators/rspec/request/request_generator.rb +1 -1
  27. data/lib/generators/rspec/scaffold/scaffold_generator.rb +52 -86
  28. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +129 -0
  29. data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  30. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +40 -74
  31. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +5 -1
  32. data/lib/generators/rspec/scaffold/templates/index_spec.rb +2 -2
  33. data/lib/generators/rspec/scaffold/templates/new_spec.rb +5 -1
  34. data/lib/generators/rspec/scaffold/templates/request_spec.rb +133 -0
  35. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +13 -12
  36. data/lib/generators/rspec/scaffold/templates/show_spec.rb +1 -1
  37. data/lib/generators/rspec/system/system_generator.rb +26 -0
  38. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  39. data/lib/generators/rspec/view/view_generator.rb +2 -2
  40. data/lib/generators/rspec.rb +0 -6
  41. data/lib/rspec/rails/active_record.rb +1 -1
  42. data/lib/rspec/rails/adapters.rb +11 -76
  43. data/lib/rspec/rails/configuration.rb +47 -31
  44. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  45. data/lib/rspec/rails/example/controller_example_group.rb +4 -4
  46. data/lib/rspec/rails/example/feature_example_group.rb +6 -26
  47. data/lib/rspec/rails/example/helper_example_group.rb +2 -9
  48. data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  49. data/lib/rspec/rails/example/mailer_example_group.rb +1 -1
  50. data/lib/rspec/rails/example/rails_example_group.rb +1 -2
  51. data/lib/rspec/rails/example/request_example_group.rb +1 -3
  52. data/lib/rspec/rails/example/system_example_group.rb +124 -0
  53. data/lib/rspec/rails/example/view_example_group.rb +47 -28
  54. data/lib/rspec/rails/example.rb +3 -0
  55. data/lib/rspec/rails/extensions/active_record/proxy.rb +1 -9
  56. data/lib/rspec/rails/feature_check.rb +12 -29
  57. data/lib/rspec/rails/fixture_file_upload_support.rb +40 -0
  58. data/lib/rspec/rails/fixture_support.rb +37 -31
  59. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
  60. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  61. data/lib/rspec/rails/matchers/action_cable.rb +65 -0
  62. data/lib/rspec/rails/matchers/action_mailbox.rb +64 -0
  63. data/lib/rspec/rails/matchers/active_job.rb +208 -18
  64. data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  65. data/lib/rspec/rails/matchers/be_a_new.rb +8 -7
  66. data/lib/rspec/rails/matchers/be_new_record.rb +3 -3
  67. data/lib/rspec/rails/matchers/be_valid.rb +1 -1
  68. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +198 -0
  69. data/lib/rspec/rails/matchers/have_http_status.rb +34 -13
  70. data/lib/rspec/rails/matchers/have_rendered.rb +2 -1
  71. data/lib/rspec/rails/matchers/redirect_to.rb +1 -1
  72. data/lib/rspec/rails/matchers/routing_matchers.rb +14 -14
  73. data/lib/rspec/rails/matchers.rb +11 -0
  74. data/lib/rspec/rails/tasks/rspec.rake +7 -17
  75. data/lib/rspec/rails/vendor/capybara.rb +12 -13
  76. data/lib/rspec/rails/version.rb +1 -1
  77. data/lib/rspec/rails/view_path_builder.rb +2 -2
  78. data/lib/rspec/rails/view_rendering.rb +18 -5
  79. data/lib/rspec/rails.rb +1 -0
  80. data/lib/rspec-rails.rb +17 -11
  81. data.tar.gz.sig +0 -0
  82. metadata +57 -33
  83. metadata.gz.sig +0 -0
  84. data/lib/generators/rspec/observer/observer_generator.rb +0 -13
data/README.md CHANGED
@@ -1,597 +1,369 @@
1
- # rspec-rails [![Build Status](https://secure.travis-ci.org/rspec/rspec-rails.svg?branch=master)](http://travis-ci.org/rspec/rspec-rails) [![Code Climate](https://img.shields.io/codeclimate/github/rspec/rspec-rails.svg)](https://codeclimate.com/github/rspec/rspec-rails)
2
- **rspec-rails** is a testing framework for Rails 3.x and 4.x.
1
+ # rspec-rails [![Build Status][]][travis-ci] [![Code Climate][]][code-climate] [![Gem Version][]](gem-version)
3
2
 
4
- Use **[rspec-rails 1.x](http://github.com/dchelimsky/rspec-rails)** for Rails
5
- 2.x.
3
+ `rspec-rails` brings the [RSpec][] testing framework to [Ruby on Rails][]
4
+ as a drop-in alternative to its default testing framework, Minitest.
6
5
 
7
- ## Installation
8
-
9
- Add `rspec-rails` to **both** the `:development` and `:test` groups in the
10
- `Gemfile`:
11
-
12
- ```ruby
13
- group :development, :test do
14
- gem 'rspec-rails', '~> 3.4'
15
- end
16
- ```
17
-
18
- Want to run against the `master` branch? You'll need to include the dependent
19
- RSpec repos as well. Add the following to your `Gemfile`:
20
-
21
- ```ruby
22
- %w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
23
- gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'master'
24
- end
25
- ```
6
+ In RSpec, tests are not just scripts that verify your application code.
7
+ They’re also specifications (or _specs,_ for short):
8
+ detailed explanations of how the application is supposed to behave,
9
+ expressed in plain English.
26
10
 
27
- Download and install by running:
11
+ Use **[`rspec-rails` 1.x][]** for Rails 2.x.
28
12
 
29
- ```
30
- bundle install
31
- ```
13
+ [Build Status]: https://secure.travis-ci.org/rspec/rspec-rails.svg?branch=master
14
+ [travis-ci]: https://travis-ci.org/rspec/rspec-rails
15
+ [Code Climate]: https://codeclimate.com/github/rspec/rspec-rails.svg
16
+ [code-climate]: https://codeclimate.com/github/rspec/rspec-rails
17
+ [Gem Version]: https://badge.fury.io/rb/rspec-rails.svg
18
+ [gem-version]: https://badge.fury.io/rb/rspec-rails
19
+ [RSpec]: https://rspec.info/
20
+ [Ruby on Rails]: https://rubyonrails.org/
21
+ [`rspec-rails` 1.x]: https://github.com/dchelimsky/rspec-rails
32
22
 
33
- Initialize the `spec/` directory (where specs will reside) with:
23
+ ## Installation
34
24
 
35
- ```
36
- rails generate rspec:install
37
- ```
25
+ 1. Add `rspec-rails` to **both** the `:development` and `:test` groups
26
+ of your app’s `Gemfile`:
38
27
 
39
- This adds the following files which are used for configuration:
28
+ ```ruby
29
+ # Run against the latest stable release
30
+ group :development, :test do
31
+ gem 'rspec-rails', '~> 4.0'
32
+ end
40
33
 
41
- - `.rspec`
42
- - `spec/spec_helper.rb`
43
- - `spec/rails_helper.rb`
34
+ # Or, run against the master branch
35
+ # (requires master-branch versions of all related RSpec libraries)
36
+ group :development, :test do
37
+ %w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
38
+ gem lib, git: "https://github.com/rspec/#{lib}.git", branch: 'master'
39
+ end
40
+ end
41
+ ```
44
42
 
45
- Check the comments in each file for more information.
43
+ (Adding it to the `:development` group is not strictly necessary,
44
+ but without it, generators and rake tasks must be preceded by `RAILS_ENV=test`.)
46
45
 
47
- Use the `rspec` command to run your specs:
46
+ 2. Then, in your project directory:
48
47
 
49
- ```
50
- bundle exec rspec
51
- ```
48
+ ```sh
49
+ # Download and install
50
+ $ bundle install
52
51
 
53
- By default the above will run all `_spec.rb` files in the `spec` directory. For
54
- more details about this see the [RSpec spec file
55
- docs](https://www.relishapp.com/rspec/rspec-core/docs/spec-files).
52
+ # Generate boilerplate configuration files
53
+ # (check the comments in each generated file for more information)
54
+ $ rails generate rspec:install
55
+ create .rspec
56
+ create spec
57
+ create spec/spec_helper.rb
58
+ create spec/rails_helper.rb
59
+ ```
56
60
 
57
- To run only a subset of these specs use the following command:
61
+ ## Upgrading
58
62
 
59
- ```
60
- # Run only model specs
61
- bundle exec rspec spec/models
63
+ If your project is already using an older version of `rspec-rails`,
64
+ upgrade to the latest version with:
62
65
 
63
- # Run only specs for AccountsController
64
- bundle exec rspec spec/controllers/accounts_controller_spec.rb
66
+ ```sh
67
+ $ bundle update rspec-rails
65
68
  ```
66
69
 
67
- Specs can also be run via `rake spec`, though this command may be slower to
68
- start than the `rspec` command.
69
-
70
- In Rails 4, you may want to create a binstub for the `rspec` command so it can
71
- be run via `bin/rspec`:
72
-
73
- ```
74
- bundle binstubs rspec-core
75
- ```
76
-
77
- ### Upgrade Note
78
-
79
- For detailed information on the general RSpec 3.x upgrade process see the
80
- [RSpec Upgrade docs](https://relishapp.com/rspec/docs/upgrade).
81
-
82
- There are three particular `rspec-rails` specific changes to be aware of:
83
-
84
- 1. [The default helper files created in RSpec 3.x have changed](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#default-helper-files)
85
- 2. [File-type inference disabled by default](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled)
86
- 3. [Rails 4.x `ActiveRecord::Migration` pending migration checks](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks)
87
- 4. Extraction of `stub_model` and `mock_model` to
88
- [`rspec-activemodel-mocks`](https://github.com/rspec/rspec-activemodel-mocks)
89
-
90
- Please see the [RSpec Rails Upgrade
91
- docs](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade) for full
92
- details.
93
-
94
- **NOTE:** Generators run in RSpec 3.x will now require `rails_helper` instead
95
- of `spec_helper`.
96
-
97
- ### Generators
98
-
99
- Once installed, RSpec will generate spec files instead of Test::Unit test files
100
- when commands like `rails generate model` and `rails generate controller` are
101
- used.
102
-
103
- You may also invoke RSpec generators independently. For instance,
104
- running `rails generate rspec:model` will generate a model spec. For more
105
- information, see [list of all
106
- generators](https://www.relishapp.com/rspec/rspec-rails/docs/generators).
107
-
108
- ## Contributing
109
-
110
- Once you've set up the environment, you'll need to cd into the working
111
- directory of whichever repo you want to work in. From there you can run the
112
- specs and cucumber features, and make patches.
113
-
114
- NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You
115
- can treat each RSpec repo as an independent project.
116
- Please see the following files:
117
-
118
- For `rspec-rails`-specific development information, see
119
-
120
- - [Build details](BUILD_DETAIL.md)
121
- - [Code of Conduct](CODE_OF_CONDUCT.md)
122
- - [Detailed contributing guide](CONTRIBUTING.md)
123
- - [Development setup guide](DEVELOPMENT.md)
124
-
70
+ RSpec follows [semantic versioning](https://semver.org/),
71
+ which means that “major version” upgrades (_e.g.,_ 2.x → 3.x)
72
+ come with **breaking changes**.
73
+ If you’re upgrading from version 2.x or below,
74
+ read the [`rspec-rails` upgrade notes][] to find out what to watch out for.
125
75
 
126
- ## Model Specs
76
+ Be sure to check the general [RSpec upgrade notes][] as well.
127
77
 
128
- Use model specs to describe behavior of models (usually ActiveRecord-based) in
129
- the application.
78
+ [`rspec-rails` upgrade notes]: https://www.relishapp.com/rspec/rspec-rails/docs/upgrade
79
+ [RSpec upgrade notes]: https://relishapp.com/rspec/docs/upgrade
130
80
 
131
- Model specs default to residing in the `spec/models` folder. Tagging any
132
- context with the metadata `:type => :model` treats its examples as model
133
- specs.
81
+ ## Usage
134
82
 
135
- For example:
83
+ ### Creating boilerplate specs with `rails generate`
136
84
 
137
- ```ruby
138
- require "rails_helper"
85
+ ```sh
86
+ # RSpec hooks into built-in generators
87
+ $ rails generate model user
88
+ invoke active_record
89
+ create db/migrate/20181017040312_create_users.rb
90
+ create app/models/user.rb
91
+ invoke rspec
92
+ create spec/models/user_spec.rb
139
93
 
140
- RSpec.describe User, :type => :model do
141
- it "orders by last name" do
142
- lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
143
- chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")
94
+ # RSpec also provides its own spec file generators
95
+ $ rails generate rspec:model user
96
+ create spec/models/user_spec.rb
144
97
 
145
- expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
146
- end
147
- end
98
+ # List all RSpec generators
99
+ $ rails generate --help | grep rspec
148
100
  ```
149
101
 
150
- For more information, see [cucumber scenarios for model
151
- specs](https://www.relishapp.com/rspec/rspec-rails/docs/model-specs).
152
-
153
- ## Controller Specs
154
-
155
- Use controller specs to describe behavior of Rails controllers.
102
+ ### Running specs
156
103
 
157
- Controller specs default to residing in the `spec/controllers` folder. Tagging
158
- any context with the metadata `:type => :controller` treats its examples as
159
- controller specs.
104
+ ```sh
105
+ # Default: Run all spec files (i.e., those matching spec/**/*_spec.rb)
106
+ $ bundle exec rspec
160
107
 
161
- For example:
162
-
163
- ```ruby
164
- require "rails_helper"
165
-
166
- RSpec.describe PostsController, :type => :controller do
167
- describe "GET #index" do
168
- it "responds successfully with an HTTP 200 status code" do
169
- get :index
170
- expect(response).to be_success
171
- expect(response).to have_http_status(200)
172
- end
108
+ # Run all spec files in a single directory (recursively)
109
+ $ bundle exec rspec spec/models
173
110
 
174
- it "renders the index template" do
175
- get :index
176
- expect(response).to render_template("index")
177
- end
111
+ # Run a single spec file
112
+ $ bundle exec rspec spec/controllers/accounts_controller_spec.rb
178
113
 
179
- it "loads all of the posts into @posts" do
180
- post1, post2 = Post.create!, Post.create!
181
- get :index
114
+ # Run a single example from a spec file (by line number)
115
+ $ bundle exec rspec spec/controllers/accounts_controller_spec.rb:8
182
116
 
183
- expect(assigns(:posts)).to match_array([post1, post2])
184
- end
185
- end
186
- end
117
+ # See all options for running specs
118
+ $ bundle exec rspec --help
187
119
  ```
188
120
 
189
- For more information, see [cucumber scenarios for controller
190
- specs](https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs).
121
+ **Optional:** If `bundle exec rspec` is too verbose for you,
122
+ you can generate a binstub at `bin/rspec` and use that instead:
191
123
 
192
- **Note:** To encourage more isolated testing, views are not rendered by default
193
- in controller specs. If you are verifying discrete view logic, use a [view
194
- spec](#view-specs). If you are verifying the behaviour of a controller and view
195
- together, consider a [request spec](#request-specs). You can use
196
- [render\_views](https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs/render-views)
197
- if you must verify the rendered view contents within a controller spec, but
198
- this is not recommended.
124
+ ```sh
125
+ $ bundle binstubs rspec-core
126
+ ```
199
127
 
200
- ## Request Specs
128
+ ## RSpec DSL Basics (or, how do I write a spec?)
201
129
 
202
- Use request specs to specify one or more request/response cycles from end to
203
- end using a black box approach.
204
-
205
- Request specs default to residing in the `spec/requests`, `spec/api`, and
206
- `spec/integration` directories. Tagging any context with the metadata `:type =>
207
- :request` treats its examples as request specs.
208
-
209
- Request specs mix in behavior from
210
- [ActionDispatch::Integration::Runner](http://api.rubyonrails.org/classes/ActionDispatch/Integration/Runner.html),
211
- which is the basis for [Rails' integration
212
- tests](http://guides.rubyonrails.org/testing.html#integration-testing).
130
+ In RSpec, application behavior is described
131
+ **first in (almost) plain English, then again in test code**, like so:
213
132
 
214
133
  ```ruby
215
- require 'rails_helper'
216
-
217
- RSpec.describe "home page", :type => :request do
218
- it "displays the user's username after successful login" do
219
- user = User.create!(:username => "jdoe", :password => "secret")
220
- get "/login"
221
- assert_select "form.login" do
222
- assert_select "input[name=?]", "username"
223
- assert_select "input[name=?]", "password"
224
- assert_select "input[type=?]", "submit"
134
+ RSpec.describe 'Post' do #
135
+ context 'before publication' do # (almost) plain English
136
+ it 'cannot have comments' do #
137
+ expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid) # test code
225
138
  end
226
-
227
- post "/login", :username => "jdoe", :password => "secret"
228
- assert_select ".header .username", :text => "jdoe"
229
139
  end
230
140
  end
231
141
  ```
232
142
 
233
- The above example uses only standard Rails and RSpec APIs, but many
234
- RSpec/Rails users like to use extension libraries like
235
- [FactoryGirl](https://github.com/thoughtbot/factory_girl) and
236
- [Capybara](https://github.com/jnicklas/capybara):
237
-
238
- ```ruby
239
- require 'rails_helper'
143
+ Running `rspec` will execute this test code,
144
+ and then use the plain-English descriptions
145
+ to generate a report of where the application
146
+ conforms to (or fails to meet) the spec:
240
147
 
241
- RSpec.describe "home page", :type => :request do
242
- it "displays the user's username after successful login" do
243
- user = FactoryGirl.create(:user, :username => "jdoe", :password => "secret")
244
- visit "/login"
245
- fill_in "Username", :with => "jdoe"
246
- fill_in "Password", :with => "secret"
247
- click_button "Log in"
248
-
249
- expect(page).to have_selector(".header .username", :text => "jdoe")
250
- end
251
- end
252
148
  ```
149
+ $ rspec --format documentation spec/models/post_spec.rb
253
150
 
254
- FactoryGirl decouples this example from changes to validation requirements,
255
- which can be encoded into the underlying factory definition without requiring
256
- changes to this example.
257
-
258
- Among other benefits, Capybara binds the form post to the generated HTML, which
259
- means we don't need to specify them separately. Note that Capybara's DSL as
260
- shown is, by default, only available in specs in the spec/features directory.
261
- For more information, see the [Capybara integration
262
- docs](http://rubydoc.info/gems/rspec-rails/file/Capybara.md).
263
-
264
- There are several other Ruby libs that implement the factory pattern or provide
265
- a DSL for request specs (a.k.a. acceptance or integration specs), but
266
- FactoryGirl and Capybara seem to be the most widely used. Whether you choose
267
- these or other libs, we strongly recommend using something for each of these
268
- roles.
151
+ Post
152
+ before publication
153
+ cannot have comments
269
154
 
270
- ## Feature Specs
155
+ Failures:
271
156
 
272
- Feature specs test your application from the outside by simulating a browser.
273
- [`capybara`](https://github.com/jnicklas/capybara) is used to manage the
274
- simulated browser.
275
-
276
- Feature specs default to residing in the `spec/features` folder. Tagging any
277
- context with the metadata `:type => :feature` treats its examples as feature
278
- specs.
279
-
280
- Feature specs mix in functionality from the capybara gem, thus they require
281
- `capybara` to use. To use feature specs, add `capybara` to the `Gemfile`:
282
-
283
- ```ruby
284
- gem "capybara"
285
- ```
157
+ 1) Post before publication cannot have comments
158
+ Failure/Error: expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid)
159
+ expected ActiveRecord::RecordInvalid but nothing was raised
160
+ # ./spec/models/post.rb:4:in `block (3 levels) in <top (required)>'
286
161
 
287
- For more information, see the [cucumber scenarios for feature
288
- specs](https://www.relishapp.com/rspec/rspec-rails/v/3-4/docs/feature-specs/feature-spec).
162
+ Finished in 0.00527 seconds (files took 0.29657 seconds to load)
163
+ 1 example, 1 failure
289
164
 
290
- ## Mailer specs
165
+ Failed examples:
291
166
 
292
- By default Mailer specs reside in the `spec/mailers` folder. Adding the metadata
293
- `:type => :mailer` to any context makes its examples be treated as mailer specs.
294
-
295
- `ActionMailer::TestCase::Behavior` is mixed into your mailer specs.
296
-
297
- ```ruby
298
- require "rails_helper"
299
-
300
- RSpec.describe Notifications, :type => :mailer do
301
- describe "notify" do
302
- let(:mail) { Notifications.signup }
303
-
304
- it "renders the headers" do
305
- expect(mail.subject).to eq("Signup")
306
- expect(mail.to).to eq(["to@example.org"])
307
- expect(mail.from).to eq(["from@example.com"])
308
- end
309
-
310
- it "renders the body" do
311
- expect(mail.body.encoded).to match("Hi")
312
- end
313
- end
314
- end
167
+ rspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments
315
168
  ```
316
169
 
317
- For more information, see the [cucumber scenarios for mailer specs
318
- ](https://relishapp.com/rspec/rspec-rails/v/3-4/docs/mailer-specs).
319
-
320
- ## View specs
321
-
322
- View specs default to residing in the `spec/views` folder. Tagging any context
323
- with the metadata `:type => :view` treats its examples as view specs.
324
-
325
- View specs mix in `ActionView::TestCase::Behavior`.
326
-
327
- ```ruby
328
- require 'rails_helper'
170
+ For an in-depth look at the RSpec DSL, including lots of examples,
171
+ read the official Cucumber documentation for [RSpec Core][].
329
172
 
330
- RSpec.describe "events/index", :type => :view do
331
- it "renders _event partial for each event" do
332
- assign(:events, [double(Event), double(Event)])
333
- render
334
- expect(view).to render_template(:partial => "_event", :count => 2)
335
- end
336
- end
173
+ [RSpec Core]: https://relishapp.com/rspec/rspec-core/docs
337
174
 
338
- RSpec.describe "events/show", :type => :view do
339
- it "displays the event location" do
340
- assign(:event, Event.new(:location => "Chicago"))
341
- render
342
- expect(rendered).to include("Chicago")
343
- end
344
- end
345
- ```
175
+ ### Helpful Rails Matchers
346
176
 
347
- View specs infer the controller name and path from the path to the view
348
- template. e.g. if the template is `events/index.html.erb` then:
177
+ In RSpec, assertions are called _expectations,_
178
+ and every expectation is built around a _matcher._
179
+ When you `expect(a).to eq(b)`, you’re using the `eq` matcher.
349
180
 
350
- ```ruby
351
- controller.controller_path == "events"
352
- controller.request.path_parameters[:controller] == "events"
353
- ```
181
+ In addition to [the matchers that come standard in RSpec][],
182
+ here are some extras that make it easier
183
+ to test the various parts of a Rails system:
354
184
 
355
- This means that most of the time you don't need to set these values. When
356
- spec'ing a partial that is included across different controllers, you _may_
357
- need to override these values before rendering the view.
185
+ | RSpec matcher | Delegates to | Available in | Notes |
186
+ | ------------------------ | ----------------- | ------------------------------- | -------------------------------------------------------- |
187
+ | [`be_a_new`][] | | all | primarily intended for controller specs |
188
+ | [`render_template`][] | `assert_template` | request / controller / view | use with `expect(response).to` |
189
+ | [`redirect_to`][] | `assert_redirect` | request / controller | use with `expect(response).to` |
190
+ | [`route_to`] | `assert_routing` | routing / controller | replaces `route_for` from version 1.x |
191
+ | [`be_routable`] | | routing / controller | usu. for `expect(...).not_to be_routable` |
192
+ | [`have_http_status`][] | | request / controller / feature | |
193
+ | [`match_array`][] | | all | for comparing arrays of ActiveRecord objects |
194
+ | [`have_been_enqueued`][] | | all | requires config: `ActiveJob::Base.queue_adapter = :test` |
195
+ | [`have_enqueued_job`][] | | all | requires config: `ActiveJob::Base.queue_adapter = :test` |
358
196
 
359
- To provide a layout for the render, you'll need to specify _both_ the template
360
- and the layout explicitly. For example:
197
+ Follow the links above for examples of how each matcher is used.
361
198
 
362
- ```ruby
363
- render :template => "events/show", :layout => "layouts/application"
364
- ```
199
+ [the matchers that come standard in RSpec]: https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
200
+ [`be_a_new`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/be-a-new-matcher
201
+ [`render_template`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/render-template-matcher
202
+ [`redirect_to`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/redirect-to-matcher
203
+ [`route_to`]: https://relishapp.com/rspec/rspec-rails/docs/routing-specs/route-to-matcher
204
+ [`be_routable`]: https://relishapp.com/rspec/rspec-rails/docs/routing-specs/be-routable-matcher
205
+ [`have_http_status`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-http-status-matcher
206
+ [`match_array`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/activerecord-relation-match-array
207
+ [`have_been_enqueued`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-been-enqueued-matcher
208
+ [`have_enqueued_job`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-enqueued-job-matcher
365
209
 
366
- ### `assign(key, val)`
210
+ ### What else does RSpec Rails add?
367
211
 
368
- Use this to assign values to instance variables in the view:
212
+ For a comprehensive look at RSpec Rails’ features,
213
+ read the [official Cucumber documentation][].
369
214
 
370
- ```ruby
371
- assign(:widget, Widget.new)
372
- render
373
- ```
215
+ [official Cucumber documentation]: https://relishapp.com/rspec/rspec-rails/docs
374
216
 
375
- The code above assigns `Widget.new` to the `@widget` variable in the view, and
376
- then renders the view.
217
+ ## What tests should I write?
377
218
 
378
- Note that because view specs mix in `ActionView::TestCase` behavior, any
379
- instance variables you set will be transparently propagated into your views
380
- (similar to how instance variables you set in controller actions are made
381
- available in views). For example:
219
+ RSpec Rails defines ten different _types_ of specs
220
+ for testing different parts of a typical Rails application.
221
+ Each one inherits from one of Rails’ built-in `TestCase` classes,
222
+ meaning the helper methods provided by default in Rails tests
223
+ are available in RSpec, as well.
382
224
 
383
- ```ruby
384
- @widget = Widget.new
385
- render # @widget is available inside the view
386
- ```
225
+ | Spec type | Corresponding Rails test class |
226
+ | -------------- | -------------------------------- |
227
+ | [model][] | |
228
+ | [controller][] | [`ActionController::TestCase`][] |
229
+ | [mailer][] | `ActionMailer::TestCase` |
230
+ | [job][] | |
231
+ | [view][] | `ActionView::TestCase` |
232
+ | [routing][] | |
233
+ | [helper][] | `ActionView::TestCase` |
234
+ | [request][] | [`ActionDispatch::IntegrationTest`][] |
235
+ | [feature][] | |
236
+ | [system][] | [`ActionDispatch::SystemTestCase`][] |
387
237
 
388
- RSpec doesn't officially support this pattern, which only works as a
389
- side-effect of the inclusion of `ActionView::TestCase`. Be aware that it may be
390
- made unavailable in the future.
238
+ Follow the links above to see examples of each spec type,
239
+ or for official Rails API documentation on the given `TestCase` class.
391
240
 
392
- #### Upgrade note
241
+ > **Note: This is not a checklist.**
242
+ >
243
+ > Ask a hundred developers how to test an application,
244
+ > and you’ll get a hundred different answers.
245
+ >
246
+ > RSpec Rails provides thoughtfully selected features
247
+ > to encourage good testing practices, but there’s no “right” way to do it.
248
+ > Ultimately, it’s up to you to decide how your test suite will be composed.
249
+
250
+ When creating a spec file,
251
+ assign it a type in the top-level `describe` block, like so:
393
252
 
394
253
  ```ruby
395
- # rspec-rails-1.x
396
- assigns[key] = value
254
+ # spec/models/user_spec.rb
397
255
 
398
- # rspec-rails-2.x+
399
- assign(key, value)
256
+ RSpec.describe User, type: :model do
257
+ ...
400
258
  ```
401
259
 
402
- ### `rendered`
260
+ [request]: https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec
261
+ [feature]: https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec
262
+ [system]: https://relishapp.com/rspec/rspec-rails/docs/system-specs/system-spec
263
+ [model]: https://www.relishapp.com/rspec/rspec-rails/docs/model-specs
264
+ [controller]: https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs
265
+ [mailer]: https://relishapp.com/rspec/rspec-rails/docs/mailer-specs
266
+ [job]: https://relishapp.com/rspec/rspec-rails/docs/job-specs/job-spec
267
+ [view]: https://www.relishapp.com/rspec/rspec-rails/docs/view-specs/view-spec
268
+ [routing]: https://www.relishapp.com/rspec/rspec-rails/docs/routing-specs
269
+ [helper]: https://www.relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
270
+ [`ActionDispatch::IntegrationTest`]: https://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html
271
+ [`ActionDispatch::SystemTestCase`]: https://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html
272
+ [`ActionController::TestCase`]: https://api.rubyonrails.org/classes/ActionController/TestCase.html
273
+ [in the appropriate folder]: https://relishapp.com/rspec/rspec-rails/docs/directory-structure
403
274
 
404
- This represents the rendered view.
275
+ ### System specs, feature specs, request specs–what’s the difference?
405
276
 
406
- ```ruby
407
- render
408
- expect(rendered).to match /Some text expected to appear on the page/
409
- ```
410
-
411
- #### Upgrade note
277
+ RSpec Rails provides some end-to-end (entire application) testing capability
278
+ to specify the interaction with the client.
412
279
 
413
- ```ruby
414
- # rspec-rails-1.x
415
- render
416
- response.should xxx
280
+ #### System specs
417
281
 
418
- # rspec-rails-2.x+
419
- render
420
- rendered.should xxx
421
-
422
- # rspec-rails-2.x+ with expect syntax
423
- render
424
- expect(rendered).to xxx
425
- ```
282
+ Also called **acceptance tests**, **browser tests**, or **end-to-end tests**,
283
+ system specs test the application from the perspective of a _human client._
284
+ The test code walks through a user’s browser interactions,
426
285
 
427
- ## Routing specs
286
+ * `visit '/login'`
287
+ * `fill_in 'Name', with: 'jdoe'`
428
288
 
429
- Routing specs default to residing in the `spec/routing` folder. Tagging any
430
- context with the metadata `:type => :routing` treats its examples as routing
431
- specs.
289
+ and the expectations revolve around page content.
432
290
 
433
- ```ruby
434
- require 'rails_helper'
435
-
436
- RSpec.describe "routing to profiles", :type => :routing do
437
- it "routes /profile/:username to profile#show for username" do
438
- expect(:get => "/profiles/jsmith").to route_to(
439
- :controller => "profiles",
440
- :action => "show",
441
- :username => "jsmith"
442
- )
443
- end
291
+ * `expect(page).to have_text('Welcome')`
444
292
 
445
- it "does not expose a list of profiles" do
446
- expect(:get => "/profiles").not_to be_routable
447
- end
448
- end
449
- ```
293
+ Because system specs are a wrapper around Rails’ built-in `SystemTestCase`,
294
+ they’re only available on Rails 5.1+.
295
+ (Feature specs serve the same purpose, but without this dependency.)
450
296
 
451
- ### Upgrade note
297
+ #### Feature specs
452
298
 
453
- `route_for` from rspec-rails-1.x is gone. Use `route_to` and `be_routable`
454
- instead.
299
+ Before Rails introduced system testing facilities,
300
+ feature specs were the only spec type for end-to-end testing.
301
+ While the RSpec team now [officially recommends system specs][] instead,
302
+ feature specs are still fully supported, look basically identical,
303
+ and work on older versions of Rails.
455
304
 
456
- ## Helper specs
305
+ On the other hand, feature specs require non-trivial configuration
306
+ to get some important features working,
307
+ like JavaScript testing or making sure each test runs with a fresh DB state.
308
+ With system specs, this configuration is provided out-of-the-box.
457
309
 
458
- Helper specs default to residing in the `spec/helpers` folder. Tagging any
459
- context with the metadata `:type => :helper` treats its examples as helper
460
- specs.
461
-
462
- Helper specs mix in ActionView::TestCase::Behavior. A `helper` object is
463
- provided which mixes in the helper module being spec'd, along with
464
- `ApplicationHelper` (if present).
310
+ Like system specs, feature specs require the [Capybara][] gem.
311
+ Rails 5.1+ includes it by default as part of system tests,
312
+ but if you don’t have the luxury of upgrading,
313
+ be sure to add it to the `:test` group of your `Gemfile` first:
465
314
 
466
315
  ```ruby
467
- require 'rails_helper'
468
-
469
- RSpec.describe EventsHelper, :type => :helper do
470
- describe "#link_to_event" do
471
- it "displays the title, and formatted date" do
472
- event = Event.new("Ruby Kaigi", Date.new(2010, 8, 27))
473
- # helper is an instance of ActionView::Base configured with the
474
- # EventsHelper and all of Rails' built-in helpers
475
- expect(helper.link_to_event).to match /Ruby Kaigi, 27 Aug, 2010/
476
- end
477
- end
316
+ group :test do
317
+ gem "capybara"
478
318
  end
479
319
  ```
480
320
 
481
- ## Matchers
482
-
483
- Several domain-specific matchers are provided to each of the example group
484
- types. Most simply delegate to their equivalent Rails' assertions.
485
-
486
- ### `be_a_new`
487
-
488
- - Available in all specs
489
- - Primarily intended for controller specs
490
-
491
- ```ruby
492
- expect(object).to be_a_new(Widget)
493
- ```
494
-
495
- Passes if the object is a `Widget` and returns true for `new_record?`
496
-
497
- ### `render_template`
498
-
499
- - Delegates to Rails' `assert_template`
500
- - Available in request, controller, and view specs
501
-
502
- In request and controller specs, apply to the `response` object:
503
-
504
- ```ruby
505
- expect(response).to render_template("new")
506
- ```
507
-
508
- In view specs, apply to the `view` object:
509
-
510
- ```ruby
511
- expect(view).to render_template(:partial => "_form", :locals => { :widget => widget } )
512
- ```
513
-
514
- ### `redirect_to`
515
-
516
- - Delegates to `assert_redirect`
517
- - Available in request and controller specs
518
-
519
- ```ruby
520
- expect(response).to redirect_to(widgets_path)
521
- ```
321
+ [officially recommends system specs]: https://rspec.info/blog/2017/10/rspec-3-7-has-been-released/#rails-actiondispatchsystemtest-integration-system-specs
322
+ [Capybara]: https://github.com/teamcapybara/capybara
522
323
 
523
- ### `route_to`
324
+ #### Request specs
524
325
 
525
- - Delegates to Rails' `assert_routing`
526
- - Available in routing and controller specs
326
+ Request specs are for testing the application
327
+ from the perspective of a _machine client._
328
+ They begin with an HTTP request and end with the HTTP response,
329
+ so they’re faster than feature specs,
330
+ but do not examine your app’s UI or JavaScript.
527
331
 
528
- ```ruby
529
- expect(:get => "/widgets").to route_to(:controller => "widgets", :action => "index")
530
- ```
332
+ Request specs provide a high-level alternative to controller specs.
333
+ In fact, as of RSpec 3.5, both the Rails and RSpec teams
334
+ [discourage directly testing controllers][]
335
+ in favor of functional tests like request specs.
531
336
 
532
- ### `be_routable`
337
+ When writing them, try to answer the question,
338
+ “For a given HTTP request (verb + path + parameters),
339
+ what HTTP response should the application return?”
533
340
 
534
- Passes if the path is recognized by Rails' routing. This is primarily intended
535
- to be used with `not_to` to specify standard CRUD routes which should not be
536
- routable.
341
+ [discourage directly testing controllers]: https://rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5
537
342
 
538
- ```ruby
539
- expect(:get => "/widgets/1/edit").not_to be_routable
540
- ```
541
-
542
- ### `have_http_status`
543
-
544
- - Passes if `response` has a matching HTTP status code
545
- - The following symbolic status codes are allowed:
546
- - `Rack::Utils::SYMBOL_TO_STATUS_CODE`
547
- - One of the defined `ActionDispatch::TestResponse` aliases:
548
- - `:error`
549
- - `:missing`
550
- - `:redirect`
551
- - `:success`
552
- - Available in controller, feature, and request specs.
553
-
554
- In controller and request specs, apply to the `response` object:
555
-
556
- ```ruby
557
- expect(response).to have_http_status(201)
558
- expect(response).not_to have_http_status(:created)
559
- ```
560
-
561
- In feature specs, apply to the `page` object:
562
-
563
- ```ruby
564
- expect(page).to have_http_status(:success)
565
- ```
566
-
567
- ## `rake` tasks
568
-
569
- Several rake tasks are provided as a convenience for working with RSpec. To run
570
- the entire spec suite use `rake spec`. To run a subset of specs use the
571
- associated type task, for example `rake spec:models`.
572
-
573
- A full list of the available rake tasks can be seen by running `rake -T | grep
574
- spec`.
343
+ ## Contributing
575
344
 
576
- ### Customizing `rake` tasks
345
+ - [Build details](BUILD_DETAIL.md)
346
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
347
+ - [Detailed contributing guide](CONTRIBUTING.md)
577
348
 
578
- If you want to customize the behavior of `rake spec`, you may [define your own
579
- task in the `Rakefile` for your
580
- project](https://www.relishapp.com/rspec/rspec-core/docs/command-line/rake-task).
581
- However, you must first clear the task that rspec-rails defined:
349
+ Once you’ve cloned the repo and [set up the environment](DEVELOPMENT.md),
350
+ you can run the specs and Cucumber features, or submit a pull request.
582
351
 
583
- ```ruby
584
- task("spec").clear
585
- ```
352
+ ## See Also
586
353
 
354
+ ### RSpec base libraries
587
355
 
588
- ## Also see
356
+ * <https://github.com/rspec/rspec>
357
+ * <https://github.com/rspec/rspec-core>
358
+ * <https://github.com/rspec/rspec-expectations>
359
+ * <https://github.com/rspec/rspec-mocks>
589
360
 
590
- * [https://github.com/rspec/rspec](https://github.com/rspec/rspec)
591
- * [https://github.com/rspec/rspec-core](https://github.com/rspec/rspec-core)
592
- * [https://github.com/rspec/rspec-expectations](https://github.com/rspec/rspec-expectations)
593
- * [https://github.com/rspec/rspec-mocks](https://github.com/rspec/rspec-mocks)
361
+ ### Recommended third-party extensions
594
362
 
595
- ## Feature Requests & Bugs
363
+ * [FactoryBot](https://github.com/thoughtbot/factory_bot)
364
+ * [Capybara](https://github.com/teamcapybara/capybara)
365
+ (Included by default in Rails 5.1+.
366
+ Note that [additional configuration is required][] to use the Capybara DSL
367
+ anywhere other than system specs and feature specs.)
596
368
 
597
- See <http://github.com/rspec/rspec-rails/issues>
369
+ [additional configuration is required]: https://rubydoc.info/gems/rspec-rails/file/Capybara.md