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