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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +4 -2
- data/Capybara.md +2 -4
- data/Changelog.md +592 -34
- data/{License.txt → LICENSE.md} +5 -2
- data/README.md +290 -369
- data/lib/generators/rspec/controller/controller_generator.rb +1 -0
- data/lib/generators/rspec/controller/templates/controller_spec.rb +5 -5
- data/lib/generators/rspec/controller/templates/view_spec.rb +2 -2
- data/lib/generators/rspec/feature/feature_generator.rb +29 -0
- data/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
- data/lib/generators/rspec/feature/templates/feature_spec.rb +5 -0
- data/lib/generators/rspec/generators/generator_generator.rb +24 -0
- data/lib/generators/rspec/generators/templates/generator_spec.rb +6 -0
- data/lib/generators/rspec/helper/helper_generator.rb +1 -0
- data/lib/generators/rspec/helper/templates/helper_spec.rb +2 -2
- data/lib/generators/rspec/install/install_generator.rb +44 -5
- data/lib/generators/rspec/install/templates/spec/rails_helper.rb +78 -0
- data/lib/generators/rspec/integration/integration_generator.rb +8 -13
- data/lib/generators/rspec/integration/templates/request_spec.rb +4 -9
- data/lib/generators/rspec/job/job_generator.rb +12 -0
- data/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -0
- data/lib/generators/rspec/mailer/mailer_generator.rb +7 -0
- data/lib/generators/rspec/mailer/templates/mailer_spec.rb +7 -7
- data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
- data/lib/generators/rspec/model/model_generator.rb +19 -5
- data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
- data/lib/generators/rspec/model/templates/model_spec.rb +2 -2
- data/lib/generators/rspec/observer/observer_generator.rb +1 -0
- data/lib/generators/rspec/observer/templates/observer_spec.rb +2 -2
- data/lib/generators/rspec/request/request_generator.rb +10 -0
- data/lib/generators/rspec/scaffold/scaffold_generator.rb +68 -138
- data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +165 -0
- data/lib/generators/rspec/scaffold/templates/controller_spec.rb +98 -73
- data/lib/generators/rspec/scaffold/templates/edit_spec.rb +9 -13
- data/lib/generators/rspec/scaffold/templates/index_spec.rb +3 -10
- data/lib/generators/rspec/scaffold/templates/new_spec.rb +10 -14
- data/lib/generators/rspec/scaffold/templates/routing_spec.rb +21 -12
- data/lib/generators/rspec/scaffold/templates/show_spec.rb +4 -11
- data/lib/generators/rspec/system/system_generator.rb +26 -0
- data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
- data/lib/generators/rspec/view/templates/view_spec.rb +2 -2
- data/lib/generators/rspec/view/view_generator.rb +1 -0
- data/lib/generators/rspec.rb +20 -6
- data/lib/rspec/rails/active_record.rb +25 -0
- data/lib/rspec/rails/adapters.rb +104 -37
- data/lib/rspec/rails/configuration.rb +148 -0
- data/lib/rspec/rails/example/controller_example_group.rb +188 -138
- data/lib/rspec/rails/example/feature_example_group.rb +63 -20
- data/lib/rspec/rails/example/helper_example_group.rb +35 -26
- data/lib/rspec/rails/example/job_example_group.rb +23 -0
- data/lib/rspec/rails/example/mailer_example_group.rb +30 -14
- data/lib/rspec/rails/example/model_example_group.rb +8 -7
- data/lib/rspec/rails/example/rails_example_group.rb +3 -1
- data/lib/rspec/rails/example/request_example_group.rb +23 -16
- data/lib/rspec/rails/example/routing_example_group.rb +49 -40
- data/lib/rspec/rails/example/system_example_group.rb +108 -0
- data/lib/rspec/rails/example/view_example_group.rb +168 -135
- data/lib/rspec/rails/example.rb +2 -33
- data/lib/rspec/rails/extensions/active_record/proxy.rb +0 -1
- data/lib/rspec/rails/extensions.rb +0 -1
- data/lib/rspec/rails/feature_check.rb +64 -0
- data/lib/rspec/rails/file_fixture_support.rb +17 -0
- data/lib/rspec/rails/fixture_file_upload_support.rb +40 -0
- data/lib/rspec/rails/fixture_support.rb +32 -13
- data/lib/rspec/rails/matchers/active_job.rb +317 -0
- data/lib/rspec/rails/matchers/base_matcher.rb +184 -0
- data/lib/rspec/rails/matchers/be_a_new.rb +69 -62
- data/lib/rspec/rails/matchers/be_new_record.rb +24 -21
- data/lib/rspec/rails/matchers/be_valid.rb +42 -33
- data/lib/rspec/rails/matchers/have_enqueued_mail.rb +174 -0
- data/lib/rspec/rails/matchers/have_http_status.rb +381 -0
- data/lib/rspec/rails/matchers/have_rendered.rb +54 -31
- data/lib/rspec/rails/matchers/redirect_to.rb +30 -29
- data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
- data/lib/rspec/rails/matchers/routing_matchers.rb +107 -93
- data/lib/rspec/rails/matchers.rb +13 -14
- data/lib/rspec/rails/tasks/rspec.rake +1 -1
- data/lib/rspec/rails/vendor/capybara.rb +10 -4
- data/lib/rspec/rails/version.rb +3 -1
- data/lib/rspec/rails/view_assigns.rb +18 -18
- data/lib/rspec/rails/view_path_builder.rb +29 -0
- data/lib/rspec/rails/view_rendering.rb +89 -63
- data/lib/rspec/rails/view_spec_methods.rb +56 -0
- data/lib/rspec/rails.rb +10 -10
- data/lib/rspec-rails.rb +66 -1
- data.tar.gz.sig +0 -0
- metadata +92 -77
- metadata.gz.sig +0 -0
- data/lib/autotest/rails_rspec2.rb +0 -85
- data/lib/generators/rspec/install/templates/.rspec +0 -1
- data/lib/generators/rspec/install/templates/spec/spec_helper.rb.tt +0 -49
- data/lib/rspec/rails/extensions/active_record/base.rb +0 -58
- data/lib/rspec/rails/matchers/have_extension.rb +0 -36
- data/lib/rspec/rails/mocks.rb +0 -274
- data/lib/rspec/rails/module_inclusion.rb +0 -19
- data/lib/rspec/rails/vendor/webrat.rb +0 -33
data/README.md
CHANGED
@@ -1,449 +1,370 @@
|
|
1
|
-
# rspec-rails [![Build Status]
|
1
|
+
# rspec-rails [![Build Status][]][travis-ci] [![Code Climate][]][code-climate] [![Gem Version][]](gem-version)
|
2
2
|
|
3
|
-
|
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
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
23
|
+
## Installation
|
20
24
|
|
21
|
-
|
22
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
37
|
-
bundle exec rspec spec/models
|
81
|
+
## Usage
|
38
82
|
|
39
|
-
|
40
|
-
bundle exec rspec spec/controllers/accounts_controller_spec.rb
|
41
|
-
```
|
83
|
+
### Creating boilerplate specs with `rails generate`
|
42
84
|
|
43
|
-
|
44
|
-
|
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
|
-
|
47
|
-
|
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
|
-
|
56
|
-
when commands like `rails generate model` and `rails generate controller` are
|
57
|
-
used.
|
102
|
+
### Running specs
|
58
103
|
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
108
|
+
# Run all spec files in a single directory (recursively)
|
109
|
+
$ bundle exec rspec spec/models
|
65
110
|
|
66
|
-
|
67
|
-
|
111
|
+
# Run a single spec file
|
112
|
+
$ bundle exec rspec spec/controllers/accounts_controller_spec.rb
|
68
113
|
|
69
|
-
|
70
|
-
|
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
|
-
|
73
|
-
|
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
|
-
|
83
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
125
|
+
```sh
|
126
|
+
$ bundle binstubs rspec-core
|
127
|
+
```
|
109
128
|
|
110
|
-
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
```
|
129
|
+
## RSpec DSL Basics (or, how do I write a spec?)
|
115
130
|
|
116
|
-
|
117
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
152
|
+
Post
|
153
|
+
before publication
|
154
|
+
cannot have comments
|
177
155
|
|
178
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
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
|
-
|
163
|
+
Finished in 0.00527 seconds (files took 0.29657 seconds to load)
|
164
|
+
1 example, 1 failure
|
191
165
|
|
192
|
-
|
166
|
+
Failed examples:
|
193
167
|
|
194
|
-
|
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
|
-
|
216
|
-
|
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
|
-
|
220
|
-
controller.request.path_parameters[:controller] == "events"
|
221
|
-
```
|
255
|
+
# spec/models/user_spec.rb
|
222
256
|
|
223
|
-
|
224
|
-
|
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
|
-
|
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
|
-
|
276
|
+
### System specs, feature specs, request specs–what’s the difference?
|
237
277
|
|
238
|
-
|
239
|
-
|
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
|
-
|
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
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
257
|
-
|
258
|
-
made unavailable in the future.
|
287
|
+
* `visit '/login'`
|
288
|
+
* `fill_in 'Name', with: 'jdoe'`
|
259
289
|
|
260
|
-
|
290
|
+
and the expectations revolve around page content.
|
261
291
|
|
262
|
-
|
263
|
-
# rspec-rails-1.x
|
264
|
-
assigns[key] = value
|
292
|
+
* `expect(page).to have_text('Welcome')`
|
265
293
|
|
266
|
-
|
267
|
-
|
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
|
-
|
298
|
+
#### Feature specs
|
271
299
|
|
272
|
-
|
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
|
-
|
275
|
-
|
276
|
-
|
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
|
-
|
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
|
-
|
283
|
-
|
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
|
-
|
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
|
-
|
405
|
-
spec`.
|
325
|
+
#### Request specs
|
406
326
|
|
407
|
-
|
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
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
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
|
-
|
415
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
431
|
-
|
346
|
+
- [Build details](BUILD_DETAIL.md)
|
347
|
+
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
348
|
+
- [Detailed contributing guide](CONTRIBUTING.md)
|
432
349
|
|
433
|
-
|
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
|
353
|
+
## See Also
|
436
354
|
|
437
|
-
|
438
|
-
[DEV-README](https://github.com/rspec/rspec-rails/blob/master/DEV-README.md).
|
355
|
+
### RSpec base libraries
|
439
356
|
|
440
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
370
|
+
[additional configuration is required]: https://rubydoc.info/gems/rspec-rails/file/Capybara.md
|