rspec-rails 2.14.2 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +4 -2
  5. data/Capybara.md +2 -4
  6. data/Changelog.md +592 -34
  7. data/{License.txt → LICENSE.md} +5 -2
  8. data/README.md +290 -369
  9. data/lib/generators/rspec/controller/controller_generator.rb +1 -0
  10. data/lib/generators/rspec/controller/templates/controller_spec.rb +5 -5
  11. data/lib/generators/rspec/controller/templates/view_spec.rb +2 -2
  12. data/lib/generators/rspec/feature/feature_generator.rb +29 -0
  13. data/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
  14. data/lib/generators/rspec/feature/templates/feature_spec.rb +5 -0
  15. data/lib/generators/rspec/generators/generator_generator.rb +24 -0
  16. data/lib/generators/rspec/generators/templates/generator_spec.rb +6 -0
  17. data/lib/generators/rspec/helper/helper_generator.rb +1 -0
  18. data/lib/generators/rspec/helper/templates/helper_spec.rb +2 -2
  19. data/lib/generators/rspec/install/install_generator.rb +44 -5
  20. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +78 -0
  21. data/lib/generators/rspec/integration/integration_generator.rb +8 -13
  22. data/lib/generators/rspec/integration/templates/request_spec.rb +4 -9
  23. data/lib/generators/rspec/job/job_generator.rb +12 -0
  24. data/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -0
  25. data/lib/generators/rspec/mailer/mailer_generator.rb +7 -0
  26. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +7 -7
  27. data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
  28. data/lib/generators/rspec/model/model_generator.rb +19 -5
  29. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  30. data/lib/generators/rspec/model/templates/model_spec.rb +2 -2
  31. data/lib/generators/rspec/observer/observer_generator.rb +1 -0
  32. data/lib/generators/rspec/observer/templates/observer_spec.rb +2 -2
  33. data/lib/generators/rspec/request/request_generator.rb +10 -0
  34. data/lib/generators/rspec/scaffold/scaffold_generator.rb +68 -138
  35. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +165 -0
  36. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +98 -73
  37. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +9 -13
  38. data/lib/generators/rspec/scaffold/templates/index_spec.rb +3 -10
  39. data/lib/generators/rspec/scaffold/templates/new_spec.rb +10 -14
  40. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +21 -12
  41. data/lib/generators/rspec/scaffold/templates/show_spec.rb +4 -11
  42. data/lib/generators/rspec/system/system_generator.rb +26 -0
  43. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  44. data/lib/generators/rspec/view/templates/view_spec.rb +2 -2
  45. data/lib/generators/rspec/view/view_generator.rb +1 -0
  46. data/lib/generators/rspec.rb +20 -6
  47. data/lib/rspec/rails/active_record.rb +25 -0
  48. data/lib/rspec/rails/adapters.rb +104 -37
  49. data/lib/rspec/rails/configuration.rb +148 -0
  50. data/lib/rspec/rails/example/controller_example_group.rb +188 -138
  51. data/lib/rspec/rails/example/feature_example_group.rb +63 -20
  52. data/lib/rspec/rails/example/helper_example_group.rb +35 -26
  53. data/lib/rspec/rails/example/job_example_group.rb +23 -0
  54. data/lib/rspec/rails/example/mailer_example_group.rb +30 -14
  55. data/lib/rspec/rails/example/model_example_group.rb +8 -7
  56. data/lib/rspec/rails/example/rails_example_group.rb +3 -1
  57. data/lib/rspec/rails/example/request_example_group.rb +23 -16
  58. data/lib/rspec/rails/example/routing_example_group.rb +49 -40
  59. data/lib/rspec/rails/example/system_example_group.rb +108 -0
  60. data/lib/rspec/rails/example/view_example_group.rb +168 -135
  61. data/lib/rspec/rails/example.rb +2 -33
  62. data/lib/rspec/rails/extensions/active_record/proxy.rb +0 -1
  63. data/lib/rspec/rails/extensions.rb +0 -1
  64. data/lib/rspec/rails/feature_check.rb +64 -0
  65. data/lib/rspec/rails/file_fixture_support.rb +17 -0
  66. data/lib/rspec/rails/fixture_file_upload_support.rb +40 -0
  67. data/lib/rspec/rails/fixture_support.rb +32 -13
  68. data/lib/rspec/rails/matchers/active_job.rb +317 -0
  69. data/lib/rspec/rails/matchers/base_matcher.rb +184 -0
  70. data/lib/rspec/rails/matchers/be_a_new.rb +69 -62
  71. data/lib/rspec/rails/matchers/be_new_record.rb +24 -21
  72. data/lib/rspec/rails/matchers/be_valid.rb +42 -33
  73. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +174 -0
  74. data/lib/rspec/rails/matchers/have_http_status.rb +381 -0
  75. data/lib/rspec/rails/matchers/have_rendered.rb +54 -31
  76. data/lib/rspec/rails/matchers/redirect_to.rb +30 -29
  77. data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
  78. data/lib/rspec/rails/matchers/routing_matchers.rb +107 -93
  79. data/lib/rspec/rails/matchers.rb +13 -14
  80. data/lib/rspec/rails/tasks/rspec.rake +1 -1
  81. data/lib/rspec/rails/vendor/capybara.rb +10 -4
  82. data/lib/rspec/rails/version.rb +3 -1
  83. data/lib/rspec/rails/view_assigns.rb +18 -18
  84. data/lib/rspec/rails/view_path_builder.rb +29 -0
  85. data/lib/rspec/rails/view_rendering.rb +89 -63
  86. data/lib/rspec/rails/view_spec_methods.rb +56 -0
  87. data/lib/rspec/rails.rb +10 -10
  88. data/lib/rspec-rails.rb +66 -1
  89. data.tar.gz.sig +0 -0
  90. metadata +92 -77
  91. metadata.gz.sig +0 -0
  92. data/lib/autotest/rails_rspec2.rb +0 -85
  93. data/lib/generators/rspec/install/templates/.rspec +0 -1
  94. data/lib/generators/rspec/install/templates/spec/spec_helper.rb.tt +0 -49
  95. data/lib/rspec/rails/extensions/active_record/base.rb +0 -58
  96. data/lib/rspec/rails/matchers/have_extension.rb +0 -36
  97. data/lib/rspec/rails/mocks.rb +0 -274
  98. data/lib/rspec/rails/module_inclusion.rb +0 -19
  99. data/lib/rspec/rails/vendor/webrat.rb +0 -33
data/README.md CHANGED
@@ -1,449 +1,370 @@
1
- # rspec-rails [![Build Status](https://secure.travis-ci.org/rspec/rspec-rails.png?branch=master)](http://travis-ci.org/rspec/rspec-rails) [![Code Climate](https://codeclimate.com/github/rspec/rspec-rails.png)](https://codeclimate.com/github/rspec/rspec-rails)
1
+ # rspec-rails [![Build Status][]][travis-ci] [![Code Climate][]][code-climate] [![Gem Version][]](gem-version)
2
2
 
3
- **rspec-rails** is a testing framework for Rails 3.x and 4.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.
4
5
 
5
- Use **[rspec-rails 1.x](http://github.com/dchelimsky/rspec-rails)** for Rails
6
- 2.x.
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.
7
10
 
8
- ## Installation
9
-
10
- Add `rspec-rails` to **both** the `:development` and `:test` groups in the
11
- `Gemfile`:
11
+ Use **[`rspec-rails` 1.x][]** for Rails 2.x.
12
12
 
13
- ```ruby
14
- group :development, :test do
15
- gem 'rspec-rails', '~> 2.0'
16
- end
17
- ```
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
18
22
 
19
- Download and install by running:
23
+ ## Installation
20
24
 
21
- ```
22
- bundle install
25
+ 1. Add `rspec-rails` to **both** the `:development` and `:test` groups
26
+ of your app’s `Gemfile`:
27
+
28
+ ```ruby
29
+ # Run against the latest stable release
30
+ group :development, :test do
31
+ gem 'rspec-rails', '~> 3.9'
32
+ end
33
+
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
+ ```
42
+
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`.)
45
+
46
+ 2. Then, in your project directory:
47
+
48
+ ```sh
49
+ # Download and install
50
+ $ bundle install
51
+
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
+ ```
60
+
61
+ ## Upgrading
62
+
63
+ If your project is already using an older version of `rspec-rails`,
64
+ upgrade to the latest version with:
65
+
66
+ ```sh
67
+ $ bundle update rspec-rails
23
68
  ```
24
69
 
25
- Initialize the `spec/` directory (where specs will reside) with:
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.
26
75
 
27
- ```
28
- rails generate rspec:install
29
- ```
30
-
31
- To run your specs, use the `rspec` command:
76
+ Be sure to check the general [RSpec upgrade notes][] as well.
32
77
 
33
- ```
34
- bundle exec rspec
78
+ [`rspec-rails` upgrade notes]: https://www.relishapp.com/rspec/rspec-rails/docs/upgrade
79
+ [RSpec upgrade notes]: https://relishapp.com/rspec/docs/upgrade
35
80
 
36
- # Run only model specs
37
- bundle exec rspec spec/models
81
+ ## Usage
38
82
 
39
- # Run only specs for AccountsController
40
- bundle exec rspec spec/controllers/accounts_controller_spec.rb
41
- ```
83
+ ### Creating boilerplate specs with `rails generate`
42
84
 
43
- Specs can also be run via `rake spec`, though this command may be slower to
44
- start than the `rspec` command.
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
45
93
 
46
- In Rails 4, you may want to create a binstub for the `rspec` command so it can
47
- be run via `bin/rspec`:
94
+ # RSpec also provides its own spec file generators
95
+ $ rails generate rspec:model user
96
+ create spec/models/user_spec.rb
48
97
 
98
+ # List all RSpec generators
99
+ $ rails generate --help | grep rspec
49
100
  ```
50
- bundle binstubs rspec-core
51
- ```
52
-
53
- ### Generators
54
101
 
55
- Once installed, RSpec will generate spec files instead of Test::Unit test files
56
- when commands like `rails generate model` and `rails generate controller` are
57
- used.
102
+ ### Running specs
58
103
 
59
- You may also invoke invoke RSpec generators independently. For instance,
60
- running `rails generate rspec:model` will generate a model spec. For more
61
- information, see [list of all
62
- generators](https://www.relishapp.com/rspec/rspec-rails/docs/generators).
104
+ ```sh
105
+ # Default: Run all spec files (i.e., those matching spec/**/*_spec.rb)
106
+ $ bundle exec rspec
63
107
 
64
- ## Model Specs
108
+ # Run all spec files in a single directory (recursively)
109
+ $ bundle exec rspec spec/models
65
110
 
66
- Model specs reside in the `spec/models` folder. Use model specs to describe
67
- behavior of models (usually ActiveRecord-based) in the application. For example:
111
+ # Run a single spec file
112
+ $ bundle exec rspec spec/controllers/accounts_controller_spec.rb
68
113
 
69
- ```ruby
70
- require "spec_helper"
114
+ # Run a single example from a spec file (by line number)
115
+ $ bundle exec rspec spec/controllers/accounts_controller_spec.rb:8
71
116
 
72
- describe User do
73
- it "orders by last name" do
74
- lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
75
- chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")
76
-
77
- expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
78
- end
79
- end
117
+ # See all options for running specs
118
+ $ bundle exec rspec --help
80
119
  ```
81
120
 
82
- For more information, see [cucumber scenarios for model
83
- specs](https://www.relishapp.com/rspec/rspec-rails/docs/model-specs).
84
-
85
- ## Controller Specs
86
-
87
- Controller specs reside in the `spec/controllers` folder. Use controller specs
88
- to describe behavior of Rails controllers. For example:
89
-
90
- ```ruby
91
- require "spec_helper"
92
-
93
- describe PostsController do
94
- describe "GET #index" do
95
- it "responds successfully with an HTTP 200 status code" do
96
- get :index
97
- expect(response).to be_success
98
- expect(response.status).to eq(200)
99
- end
100
-
101
- it "renders the index template" do
102
- get :index
103
- expect(response).to render_template("index")
104
- end
121
+ **Optional:** If `bundle exec rspec` is too verbose for you,
122
+ you can generate a binstub at `bin/rspec`
123
+ and use that instead (Rails 4+ only):
105
124
 
106
- it "loads all of the posts into @posts" do
107
- post1, post2 = Post.create!, Post.create!
108
- get :index
125
+ ```sh
126
+ $ bundle binstubs rspec-core
127
+ ```
109
128
 
110
- expect(assigns(:posts)).to match_array([post1, post2])
111
- end
112
- end
113
- end
114
- ```
129
+ ## RSpec DSL Basics (or, how do I write a spec?)
115
130
 
116
- For more information, see [cucumber scenarios for controller
117
- specs](https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs).
118
-
119
- **Note:** To encourage more isolated testing, views are not rendered by default
120
- in controller specs. If you wish to assert against the contents of the rendered
121
- view in a controller spec, enable
122
- [render\_views](https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs/render-views)
123
- or use a higher-level [request spec](#request-specs) or [feature
124
- spec](#feature-specs).
125
-
126
- ## <a id="request-spec"></a>Request Specs
127
-
128
- Request specs live in spec/requests, spec/api and
129
- spec/integration, and mix in behavior
130
- [ActionDispatch::Integration::Runner](http://api.rubyonrails.org/classes/ActionDispatch/Integration/Runner.html),
131
- which is the basis for [Rails' integration
132
- tests](http://guides.rubyonrails.org/testing.html#integration-testing). The
133
- intent is to specify one or more request/response cycles from end to end using
134
- a black box approach.
131
+ In RSpec, application behavior is described
132
+ **first in (almost) plain English, then again in test code**, like so:
135
133
 
136
134
  ```ruby
137
- require 'spec_helper'
138
- describe "home page" do
139
- it "displays the user's username after successful login" do
140
- user = User.create!(:username => "jdoe", :password => "secret")
141
- get "/login"
142
- assert_select "form.login" do
143
- assert_select "input[name=?]", "username"
144
- assert_select "input[name=?]", "password"
145
- assert_select "input[type=?]", "submit"
135
+ RSpec.describe 'Post' do #
136
+ context 'before publication' do # (almost) plain English
137
+ it 'cannot have comments' do #
138
+ expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid) # test code
146
139
  end
147
-
148
- post "/login", :username => "jdoe", :password => "secret"
149
- assert_select ".header .username", :text => "jdoe"
150
140
  end
151
141
  end
152
142
  ```
153
143
 
154
- This example uses only standard Rails and RSpec API's, but many RSpec/Rails
155
- users like to use extension libraries like
156
- [FactoryGirl](https://github.com/thoughtbot/factory_girl) and
157
- [Capybara](https://github.com/jnicklas/capybara):
144
+ Running `rspec` will execute this test code,
145
+ and then use the plain-English descriptions
146
+ to generate a report of where the application
147
+ conforms to (or fails to meet) the spec:
158
148
 
159
- ```ruby
160
- require 'spec_helper'
161
- describe "home page" do
162
- it "displays the user's username after successful login" do
163
- user = FactoryGirl.create(:user, :username => "jdoe", :password => "secret")
164
- visit "/login"
165
- fill_in "Username", :with => "jdoe"
166
- fill_in "Password", :with => "secret"
167
- click_button "Log in"
168
-
169
- expect(page).to have_selector(".header .username", :text => "jdoe")
170
- end
171
- end
172
149
  ```
150
+ $ rspec --format documentation spec/models/post_spec.rb
173
151
 
174
- FactoryGirl decouples this example from changes to validation requirements,
175
- which can be encoded into the underlying factory definition without requiring
176
- changes to this example.
152
+ Post
153
+ before publication
154
+ cannot have comments
177
155
 
178
- Among other benefits, Capybara binds the form post to the generated HTML, which
179
- means we don't need to specify them separately. Note that Capybara's DSL as
180
- shown is, by default, only available in specs in the spec/features directory.
181
- For more information, see the [Capybara integration
182
- docs](http://rubydoc.info/gems/rspec-rails/file/Capybara.md).
156
+ Failures:
183
157
 
184
- There are several other Ruby libs that implement the factory pattern or provide
185
- a DSL for request specs (a.k.a. acceptance or integration specs), but
186
- FactoryGirl and Capybara seem to be the most widely used. Whether you choose
187
- these or other libs, we strongly recommend using something for each of these
188
- roles.
158
+ 1) Post before publication cannot have comments
159
+ Failure/Error: expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid)
160
+ expected ActiveRecord::RecordInvalid but nothing was raised
161
+ # ./spec/models/post.rb:4:in `block (3 levels) in <top (required)>'
189
162
 
190
- # View specs
163
+ Finished in 0.00527 seconds (files took 0.29657 seconds to load)
164
+ 1 example, 1 failure
191
165
 
192
- View specs live in spec/views, and mix in ActionView::TestCase::Behavior.
166
+ Failed examples:
193
167
 
194
- ```ruby
195
- require 'spec_helper'
196
- describe "events/index" do
197
- it "renders _event partial for each event" do
198
- assign(:events, [stub_model(Event), stub_model(Event)])
199
- render
200
- expect(view).to render_template(:partial => "_event", :count => 2)
201
- end
202
- end
203
-
204
- describe "events/show" do
205
- it "displays the event location" do
206
- assign(:event, stub_model(Event,
207
- :location => "Chicago"
208
- ))
209
- render
210
- expect(rendered).to include("Chicago")
211
- end
212
- end
168
+ rspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments
213
169
  ```
214
170
 
215
- View specs infer the controller name and path from the path to the view
216
- template. e.g. if the template is "events/index.html.erb" then:
171
+ For an in-depth look at the RSpec DSL, including lots of examples,
172
+ read the official Cucumber documentation for [RSpec Core][].
173
+
174
+ [RSpec Core]: https://relishapp.com/rspec/rspec-core/docs
175
+
176
+ ### Helpful Rails Matchers
177
+
178
+ In RSpec, assertions are called _expectations,_
179
+ and every expectation is built around a _matcher._
180
+ When you `expect(a).to eq(b)`, you’re using the `eq` matcher.
181
+
182
+ In addition to [the matchers that come standard in RSpec][],
183
+ here are some extras that make it easier
184
+ to test the various parts of a Rails system:
185
+
186
+ | RSpec matcher | Delegates to | Available in | Notes |
187
+ | ------------------------ | ----------------- | ------------------------------- | -------------------------------------------------------- |
188
+ | [`be_a_new`][] | | all | primarily intended for controller specs |
189
+ | [`render_template`][] | `assert_template` | request / controller / view | use with `expect(response).to` |
190
+ | [`redirect_to`][] | `assert_redirect` | request / controller | use with `expect(response).to` |
191
+ | [`route_to`] | `assert_routing` | routing / controller | replaces `route_for` from version 1.x |
192
+ | [`be_routable`] | | routing / controller | usu. for `expect(...).not_to be_routable` |
193
+ | [`have_http_status`][] | | request / controller / feature | |
194
+ | [`match_array`][] | | all | for comparing arrays of ActiveRecord objects |
195
+ | [`have_been_enqueued`][] | | all | requires config: `ActiveJob::Base.queue_adapter = :test` |
196
+ | [`have_enqueued_job`][] | | all | requires config: `ActiveJob::Base.queue_adapter = :test` |
197
+
198
+ Follow the links above for examples of how each matcher is used.
199
+
200
+ [the matchers that come standard in RSpec]: https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
201
+ [`be_a_new`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/be-a-new-matcher
202
+ [`render_template`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/render-template-matcher
203
+ [`redirect_to`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/redirect-to-matcher
204
+ [`route_to`]: https://relishapp.com/rspec/rspec-rails/docs/routing-specs/route-to-matcher
205
+ [`be_routable`]: https://relishapp.com/rspec/rspec-rails/docs/routing-specs/be-routable-matcher
206
+ [`have_http_status`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-http-status-matcher
207
+ [`match_array`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/activerecord-relation-match-array
208
+ [`have_been_enqueued`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-been-enqueued-matcher
209
+ [`have_enqueued_job`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-enqueued-job-matcher
210
+
211
+ ### What else does RSpec Rails add?
212
+
213
+ For a comprehensive look at RSpec Rails’ features,
214
+ read the [official Cucumber documentation][].
215
+
216
+ [official Cucumber documentation]: https://relishapp.com/rspec/rspec-rails/docs
217
+
218
+ ## What tests should I write?
219
+
220
+ RSpec Rails defines ten different _types_ of specs
221
+ for testing different parts of a typical Rails application.
222
+ Each one inherits from one of Rails’ built-in `TestCase` classes,
223
+ meaning the helper methods provided by default in Rails tests
224
+ are available in RSpec, as well.
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
+ | [request][] | [`ActionDispatch::IntegrationTest`][] |
236
+ | [feature][] | |
237
+ | [system][] | [`ActionDispatch::SystemTestCase`][] |
238
+
239
+ Follow the links above to see examples of each spec type,
240
+ or for official Rails API documentation on the given `TestCase` class.
241
+
242
+ > **Note: This is not a checklist.**
243
+ >
244
+ > Ask a hundred developers how to test an application,
245
+ > and you’ll get a hundred different answers.
246
+ >
247
+ > RSpec Rails provides thoughtfully selected features
248
+ > to encourage good testing practices, but there’s no “right” way to do it.
249
+ > Ultimately, it’s up to you to decide how your test suite will be composed.
250
+
251
+ When creating a spec file,
252
+ assign it a type in the top-level `describe` block, like so:
217
253
 
218
254
  ```ruby
219
- controller.controller_path == "events"
220
- controller.request.path_parameters[:controller] == "events"
221
- ```
255
+ # spec/models/user_spec.rb
222
256
 
223
- This means that most of the time you don't need to set these values. When
224
- spec'ing a partial that is included across different controllers, you _may_
225
- need to override these values before rendering the view.
226
-
227
- To provide a layout for the render, you'll need to specify _both_ the template
228
- and the layout explicitly. For example:
229
-
230
- ```ruby
231
- render :template => "events/show", :layout => "layouts/application"
257
+ RSpec.describe User, type: :model do
258
+ ...
232
259
  ```
233
260
 
234
- ## `assign(key, val)`
261
+ [request]: https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec
262
+ [feature]: https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec
263
+ [system]: https://relishapp.com/rspec/rspec-rails/docs/system-specs/system-spec
264
+ [model]: https://www.relishapp.com/rspec/rspec-rails/docs/model-specs
265
+ [controller]: https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs
266
+ [mailer]: https://relishapp.com/rspec/rspec-rails/docs/mailer-specs
267
+ [job]: https://relishapp.com/rspec/rspec-rails/docs/job-specs/job-spec
268
+ [view]: https://www.relishapp.com/rspec/rspec-rails/docs/view-specs/view-spec
269
+ [routing]: https://www.relishapp.com/rspec/rspec-rails/docs/routing-specs
270
+ [helper]: https://www.relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
271
+ [`ActionDispatch::IntegrationTest`]: https://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html
272
+ [`ActionDispatch::SystemTestCase`]: https://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html
273
+ [`ActionController::TestCase`]: https://api.rubyonrails.org/classes/ActionController/TestCase.html
274
+ [in the appropriate folder]: https://relishapp.com/rspec/rspec-rails/docs/directory-structure
235
275
 
236
- Use this to assign values to instance variables in the view:
276
+ ### System specs, feature specs, request specs–what’s the difference?
237
277
 
238
- ```ruby
239
- assign(:widget, stub_model(Widget))
240
- render
241
- ```
242
-
243
- The code above assigns `stub_model(Widget)` to the `@widget` variable in the view, and then
244
- renders the view.
278
+ RSpec Rails provides some end-to-end (entire application) testing capability
279
+ to specify the interaction with the client.
245
280
 
246
- Note that because view specs mix in `ActionView::TestCase` behavior, any
247
- instance variables you set will be transparently propagated into your views
248
- (similar to how instance variables you set in controller actions are made
249
- available in views). For example:
281
+ #### System specs
250
282
 
251
- ```ruby
252
- @widget = stub_model(Widget)
253
- render # @widget is available inside the view
254
- ```
283
+ Also called **acceptance tests**, **browser tests**, or **end-to-end tests**,
284
+ system specs test the application from the perspective of a _human client._
285
+ The test code walks through a user’s browser interactions,
255
286
 
256
- RSpec doesn't officially support this pattern, which only works as a
257
- side-effect of the inclusion of `ActionView::TestCase`. Be aware that it may be
258
- made unavailable in the future.
287
+ * `visit '/login'`
288
+ * `fill_in 'Name', with: 'jdoe'`
259
289
 
260
- ### Upgrade note
290
+ and the expectations revolve around page content.
261
291
 
262
- ```ruby
263
- # rspec-rails-1.x
264
- assigns[key] = value
292
+ * `expect(page).to have_text('Welcome')`
265
293
 
266
- # rspec-rails-2.x
267
- assign(key, value)
268
- ```
294
+ Because system specs are a wrapper around Rails’ built-in `SystemTestCase`,
295
+ they’re only available on Rails 5.1+.
296
+ (Feature specs serve the same purpose, but without this dependency.)
269
297
 
270
- ## `rendered`
298
+ #### Feature specs
271
299
 
272
- This represents the rendered view.
300
+ Before Rails introduced system testing facilities,
301
+ feature specs were the only spec type for end-to-end testing.
302
+ While the RSpec team now [officially recommends system specs][] instead,
303
+ feature specs are still fully supported, look basically identical,
304
+ and work on older versions of Rails.
273
305
 
274
- ```ruby
275
- render
276
- expect(rendered).to match /Some text expected to appear on the page/
277
- ```
306
+ On the other hand, feature specs require non-trivial configuration
307
+ to get some important features working,
308
+ like JavaScript testing or making sure each test runs with a fresh DB state.
309
+ With system specs, this configuration is provided out-of-the-box.
278
310
 
279
- ### Upgrade note
311
+ Like system specs, feature specs require the [Capybara][] gem.
312
+ Rails 5.1+ includes it by default as part of system tests,
313
+ but if you don’t have the luxury of upgrading,
314
+ be sure to add it to the `:test` group of your `Gemfile` first:
280
315
 
281
316
  ```ruby
282
- # rspec-rails-1.x
283
- render
284
- response.should xxx
285
-
286
- # rspec-rails-2.x
287
- render
288
- rendered.should xxx
289
-
290
- # rspec-rails-2.x with expect syntax
291
- render
292
- expect(rendered).to xxx
293
- ```
294
-
295
- # Routing specs
296
-
297
- Routing specs live in spec/routing.
298
-
299
- ```ruby
300
- require 'spec_helper'
301
- describe "routing to profiles" do
302
- it "routes /profile/:username to profile#show for username" do
303
- expect(:get => "/profiles/jsmith").to route_to(
304
- :controller => "profiles",
305
- :action => "show",
306
- :username => "jsmith"
307
- )
308
- end
309
-
310
- it "does not expose a list of profiles" do
311
- expect(:get => "/profiles").not_to be_routable
312
- end
313
- end
314
- ```
315
-
316
- ### Upgrade note
317
-
318
- `route_for` from rspec-rails-1.x is gone. Use `route_to` and `be_routable` instead.
319
-
320
- # Helper specs
321
-
322
- Helper specs live in spec/helpers, and mix in ActionView::TestCase::Behavior.
323
-
324
- Provides a `helper` object which mixes in the helper module being spec'd, along
325
- with `ApplicationHelper` (if present).
326
-
327
- ```ruby
328
- require 'spec_helper'
329
- describe EventsHelper do
330
- describe "#link_to_event" do
331
- it "displays the title, and formatted date" do
332
- event = Event.new("Ruby Kaigi", Date.new(2010, 8, 27))
333
- # helper is an instance of ActionView::Base configured with the
334
- # EventsHelper and all of Rails' built-in helpers
335
- expect(helper.link_to_event).to match /Ruby Kaigi, 27 Aug, 2010/
336
- end
337
- end
317
+ group :test do
318
+ gem "capybara"
338
319
  end
339
320
  ```
340
321
 
341
- # Matchers
342
-
343
- rspec-rails exposes domain-specific matchers to each of the example group types. Most
344
- of them simply delegate to Rails' assertions.
345
-
346
- ## `be_a_new`
347
- * Available in all specs.
348
- * Primarily intended for controller specs
349
-
350
- ```ruby
351
- expect(object).to be_a_new(Widget)
352
- ```
353
-
354
-
355
- Passes if the object is a `Widget` and returns true for `new_record?`
356
-
357
- ## `render_template`
358
- * Delegates to Rails' assert_template.
359
- * Available in request, controller, and view specs.
360
-
361
- In request and controller specs, apply to the response object:
362
-
363
- ```ruby
364
- expect(response).to render_template("new")
365
- ```
366
-
367
- In view specs, apply to the view object:
368
-
369
- ```ruby
370
- expect(view).to render_template(:partial => "_form", :locals => { :widget => widget } )
371
- ```
372
-
373
- ## `redirect_to`
374
- * Delegates to assert_redirect
375
- * Available in request and controller specs.
376
-
377
- ```ruby
378
- expect(response).to redirect_to(widgets_path)
379
- ```
380
-
381
- ## `route_to`
382
-
383
- * Delegates to Rails' assert_routing.
384
- * Available in routing and controller specs.
385
-
386
- ```ruby
387
- expect(:get => "/widgets").to route_to(:controller => "widgets", :action => "index")
388
- ```
389
-
390
- ## `be_routable`
391
-
392
- Passes if the path is recognized by Rails' routing. This is primarily intended
393
- to be used with `not_to` to specify routes that should not be routable.
394
-
395
- ```ruby
396
- expect(:get => "/widgets/1/edit").not_to be_routable
397
- ```
398
-
399
- # `rake` tasks
400
-
401
- `rspec-rails` defines rake tasks to run the entire test suite (`rake spec`)
402
- and subsets of tests (e.g., `rake spec:models`).
322
+ [officially recommends system specs]: https://rspec.info/blog/2017/10/rspec-3-7-has-been-released/#rails-actiondispatchsystemtest-integration-system-specs
323
+ [Capybara]: https://github.com/teamcapybara/capybara
403
324
 
404
- A full list of the available rake tasks can be seen by running `rake -T | grep
405
- spec`.
325
+ #### Request specs
406
326
 
407
- ## Customizing `rake` tasks
327
+ Request specs are for testing the application
328
+ from the perspective of a _machine client._
329
+ They begin with an HTTP request and end with the HTTP response,
330
+ so they’re faster than feature specs,
331
+ but do not examine your app’s UI or JavaScript.
408
332
 
409
- If you want to customize the behavior of `rake spec`, you may [define your own
410
- task in the `Rakefile` for your
411
- project](https://www.relishapp.com/rspec/rspec-core/docs/command-line/rake-task).
412
- However, you must first clear the task that rspec-rails defined:
333
+ Request specs provide a high-level alternative to controller specs.
334
+ In fact, as of RSpec 3.5, both the Rails and RSpec teams
335
+ [discourage directly testing controllers][]
336
+ in favor of functional tests like request specs.
413
337
 
414
- ```ruby
415
- task("spec").clear
416
- ```
338
+ When writing them, try to answer the question,
339
+ “For a given HTTP request (verb + path + parameters),
340
+ what HTTP response should the application return?”
417
341
 
418
- ### Webrat and Capybara
342
+ [discourage directly testing controllers]: https://rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5
419
343
 
420
- You can choose between webrat or capybara for simulating a browser, automating
421
- a browser, or setting expectations using the matchers they supply. Just add
422
- your preference to the Gemfile:
423
-
424
- ```ruby
425
- gem "webrat"
426
- # ... or ...
427
- gem "capybara"
428
- ```
344
+ ## Contributing
429
345
 
430
- See [http://rubydoc.info/gems/rspec-rails/file/Capybara.md](http://rubydoc.info/gems/rspec-rails/file/Capybara.md)
431
- for more info on Capybara integration.
346
+ - [Build details](BUILD_DETAIL.md)
347
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
348
+ - [Detailed contributing guide](CONTRIBUTING.md)
432
349
 
433
- # Contribute
350
+ Once you’ve cloned the repo and [set up the environment](DEVELOPMENT.md),
351
+ you can run the specs and Cucumber features, or submit a pull request.
434
352
 
435
- See [http://github.com/rspec/rspec-dev](http://github.com/rspec/rspec-dev).
353
+ ## See Also
436
354
 
437
- For `rspec-rails`-specific development information, see
438
- [DEV-README](https://github.com/rspec/rspec-rails/blob/master/DEV-README.md).
355
+ ### RSpec base libraries
439
356
 
440
- # Also see
357
+ * <https://github.com/rspec/rspec>
358
+ * <https://github.com/rspec/rspec-core>
359
+ * <https://github.com/rspec/rspec-expectations>
360
+ * <https://github.com/rspec/rspec-mocks>
441
361
 
442
- * [http://github.com/rspec/rspec](http://github.com/rspec/rspec)
443
- * [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core)
444
- * [http://github.com/rspec/rspec-expectations](http://github.com/rspec/rspec-expectations)
445
- * [http://github.com/rspec/rspec-mocks](http://github.com/rspec/rspec-mocks)
362
+ ### Recommended third-party extensions
446
363
 
447
- ## Feature Requests & Bugs
364
+ * [FactoryBot](https://github.com/thoughtbot/factory_bot)
365
+ * [Capybara](https://github.com/jnicklas/capybara)
366
+ (Included by default in Rails 5.1+.
367
+ Note that [additional configuration is required][] to use the Capybara DSL
368
+ anywhere other than system specs and feature specs.)
448
369
 
449
- See <http://github.com/rspec/rspec-rails/issues>
370
+ [additional configuration is required]: https://rubydoc.info/gems/rspec-rails/file/Capybara.md