rails 4.1.6 → 4.2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +12 -10
- data/guides/CHANGELOG.md +64 -17
- data/guides/Rakefile +21 -6
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_gem.rb +3 -3
- data/guides/bug_report_templates/action_controller_master.rb +3 -2
- data/guides/bug_report_templates/active_record_gem.rb +1 -1
- data/guides/bug_report_templates/generic_gem.rb +15 -0
- data/guides/bug_report_templates/generic_master.rb +26 -0
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +27 -21
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides.rb +2 -2
- data/guides/source/2_2_release_notes.md +1 -1
- data/guides/source/2_3_release_notes.md +4 -4
- data/guides/source/3_0_release_notes.md +8 -8
- data/guides/source/3_1_release_notes.md +6 -3
- data/guides/source/3_2_release_notes.md +6 -3
- data/guides/source/4_0_release_notes.md +6 -3
- data/guides/source/4_1_release_notes.md +9 -10
- data/guides/source/4_2_release_notes.md +877 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +6 -8
- data/guides/source/action_controller_overview.md +25 -8
- data/guides/source/action_mailer_basics.md +97 -29
- data/guides/source/action_view_overview.md +142 -191
- data/guides/source/active_job_basics.md +339 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +25 -24
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +264 -268
- data/guides/source/active_record_validations.md +23 -13
- data/guides/source/active_support_core_extensions.md +115 -123
- data/guides/source/active_support_instrumentation.md +10 -18
- data/guides/source/api_documentation_guidelines.md +63 -17
- data/guides/source/asset_pipeline.md +259 -120
- data/guides/source/association_basics.md +96 -80
- data/guides/source/autoloading_and_reloading_constants.md +1311 -0
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +161 -33
- data/guides/source/contributing_to_ruby_on_rails.md +198 -114
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +440 -286
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +217 -196
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +359 -219
- data/guides/source/i18n.md +110 -66
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +109 -62
- data/guides/source/layout.html.erb +5 -11
- data/guides/source/layouts_and_rendering.md +26 -26
- data/guides/source/maintenance_policy.md +6 -3
- data/guides/source/nested_model_forms.md +7 -4
- data/guides/source/plugins.md +27 -27
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +8 -5
- data/guides/source/routing.md +113 -73
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +40 -34
- data/guides/source/testing.md +199 -119
- data/guides/source/upgrading_ruby_on_rails.md +289 -31
- data/guides/source/working_with_javascript_in_rails.md +19 -17
- data/guides/w3c_validator.rb +2 -0
- metadata +42 -95
- data/guides/code/getting_started/Gemfile +0 -40
- data/guides/code/getting_started/Gemfile.lock +0 -125
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -60
- data/guides/code/getting_started/public/422.html +0 -60
- data/guides/code/getting_started/public/500.html +0 -59
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -12
data/guides/source/testing.md
CHANGED
@@ -49,7 +49,9 @@ The `test_helper.rb` file holds the default configuration for your tests.
|
|
49
49
|
|
50
50
|
### The Low-Down on Fixtures
|
51
51
|
|
52
|
-
For good tests, you'll need to give some thought to setting up test data.
|
52
|
+
For good tests, you'll need to give some thought to setting up test data.
|
53
|
+
In Rails, you can handle this by defining and customizing fixtures.
|
54
|
+
You can find comprehensive documentation in the [fixture api documentation](http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html).
|
53
55
|
|
54
56
|
#### What Are Fixtures?
|
55
57
|
|
@@ -80,7 +82,7 @@ Each fixture is given a name followed by an indented list of colon-separated key
|
|
80
82
|
|
81
83
|
If you are working with [associations](/association_basics.html), you can simply
|
82
84
|
define a reference node between two different fixtures. Here's an example with
|
83
|
-
a belongs_to
|
85
|
+
a `belongs_to`/`has_many` association:
|
84
86
|
|
85
87
|
```yaml
|
86
88
|
# In fixtures/categories.yml
|
@@ -94,6 +96,12 @@ one:
|
|
94
96
|
category: about
|
95
97
|
```
|
96
98
|
|
99
|
+
Note: For associations to reference one another by name, you cannot specify the `id:`
|
100
|
+
attribute on the fixtures. Rails will auto assign a primary key to be consistent between
|
101
|
+
runs. If you manually specify an `id:` attribute, this behavior will not work. For more
|
102
|
+
information on this association behavior please read the
|
103
|
+
[fixture api documentation](http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html).
|
104
|
+
|
97
105
|
#### ERB'in It Up
|
98
106
|
|
99
107
|
ERB allows you to embed Ruby code within templates. The YAML fixture format is pre-processed with ERB when Rails loads fixtures. This allows you to use Ruby to help you generate some sample data. For example, the following code generates a thousand users:
|
@@ -134,27 +142,27 @@ Unit Testing your Models
|
|
134
142
|
|
135
143
|
In Rails, models tests are what you write to test your models.
|
136
144
|
|
137
|
-
For this guide we will be using Rails _scaffolding_. It will create the model, a migration, controller and views for the new resource in a single operation. It will also create a full test suite following Rails best practices.
|
145
|
+
For this guide we will be using Rails _scaffolding_. It will create the model, a migration, controller and views for the new resource in a single operation. It will also create a full test suite following Rails best practices. We will be using examples from this generated code and will be supplementing it with additional examples where necessary.
|
138
146
|
|
139
|
-
NOTE: For more information on Rails
|
147
|
+
NOTE: For more information on Rails _scaffolding_, refer to [Getting Started with Rails](getting_started.html)
|
140
148
|
|
141
149
|
When you use `rails generate scaffold`, for a resource among other things it creates a test stub in the `test/models` folder:
|
142
150
|
|
143
151
|
```bash
|
144
|
-
$ bin/rails generate scaffold
|
152
|
+
$ bin/rails generate scaffold article title:string body:text
|
145
153
|
...
|
146
|
-
create app/models/
|
147
|
-
create test/models/
|
148
|
-
create test/fixtures/
|
154
|
+
create app/models/article.rb
|
155
|
+
create test/models/article_test.rb
|
156
|
+
create test/fixtures/articles.yml
|
149
157
|
...
|
150
158
|
```
|
151
159
|
|
152
|
-
The default test stub in `test/models/
|
160
|
+
The default test stub in `test/models/article_test.rb` looks like this:
|
153
161
|
|
154
162
|
```ruby
|
155
163
|
require 'test_helper'
|
156
164
|
|
157
|
-
class
|
165
|
+
class ArticleTest < ActiveSupport::TestCase
|
158
166
|
# test "the truth" do
|
159
167
|
# assert true
|
160
168
|
# end
|
@@ -170,15 +178,15 @@ require 'test_helper'
|
|
170
178
|
As you know by now, `test_helper.rb` specifies the default configuration to run our tests. This is included with all the tests, so any methods added to this file are available to all your tests.
|
171
179
|
|
172
180
|
```ruby
|
173
|
-
class
|
181
|
+
class ArticleTest < ActiveSupport::TestCase
|
174
182
|
```
|
175
183
|
|
176
|
-
The `
|
184
|
+
The `ArticleTest` class defines a _test case_ because it inherits from `ActiveSupport::TestCase`. `ArticleTest` thus has all the methods available from `ActiveSupport::TestCase`. You'll see those methods a little later in this guide.
|
177
185
|
|
178
|
-
Any method defined within a class inherited from `
|
179
|
-
(which is the superclass of `ActiveSupport::TestCase`) that begins with `
|
186
|
+
Any method defined within a class inherited from `Minitest::Test`
|
187
|
+
(which is the superclass of `ActiveSupport::TestCase`) that begins with `test_` (case sensitive) is simply called a test. So, `test_password` and `test_valid_password` are legal test names and are run automatically when the test case is run.
|
180
188
|
|
181
|
-
Rails adds a `test` method that takes a test name and a block. It generates a normal `
|
189
|
+
Rails adds a `test` method that takes a test name and a block. It generates a normal `Minitest::Unit` test with method names prefixed with `test_`. So,
|
182
190
|
|
183
191
|
```ruby
|
184
192
|
test "the truth" do
|
@@ -213,14 +221,23 @@ Every test contains one or more assertions. Only when all the assertions are suc
|
|
213
221
|
|
214
222
|
### Maintaining the test database schema
|
215
223
|
|
216
|
-
In order to run your tests, your test database will need to have the current
|
224
|
+
In order to run your tests, your test database will need to have the current
|
225
|
+
structure. The test helper checks whether your test database has any pending
|
226
|
+
migrations. If so, it will try to load your `db/schema.rb` or `db/structure.sql`
|
227
|
+
into the test database. If migrations are still pending, an error will be
|
228
|
+
raised. Usually this indicates that your schema is not fully migrated. Running
|
229
|
+
the migrations against the development database (`bin/rake db:migrate`) will
|
230
|
+
bring the schema up to date.
|
231
|
+
|
232
|
+
NOTE: If existing migrations required modifications, the test database needs to
|
233
|
+
be rebuilt. This can be done by executing `bin/rake db:test:prepare`.
|
217
234
|
|
218
235
|
### Running Tests
|
219
236
|
|
220
237
|
Running a test is as simple as invoking the file containing the test cases through `rake test` command.
|
221
238
|
|
222
239
|
```bash
|
223
|
-
$ bin/rake test test/models/
|
240
|
+
$ bin/rake test test/models/article_test.rb
|
224
241
|
.
|
225
242
|
|
226
243
|
Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s.
|
@@ -231,7 +248,7 @@ Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s.
|
|
231
248
|
You can also run a particular test method from the test case by running the test and providing the `test method name`.
|
232
249
|
|
233
250
|
```bash
|
234
|
-
$ bin/rake test test/models/
|
251
|
+
$ bin/rake test test/models/article_test.rb test_the_truth
|
235
252
|
.
|
236
253
|
|
237
254
|
Finished tests in 0.009064s, 110.3266 tests/s, 110.3266 assertions/s.
|
@@ -243,25 +260,25 @@ This will run all test methods from the test case. Note that `test_helper.rb` is
|
|
243
260
|
|
244
261
|
The `.` (dot) above indicates a passing test. When a test fails you see an `F`; when a test throws an error you see an `E` in its place. The last line of the output is the summary.
|
245
262
|
|
246
|
-
To see how a test failure is reported, you can add a failing test to the `
|
263
|
+
To see how a test failure is reported, you can add a failing test to the `article_test.rb` test case.
|
247
264
|
|
248
265
|
```ruby
|
249
|
-
test "should not save
|
250
|
-
|
251
|
-
assert_not
|
266
|
+
test "should not save article without title" do
|
267
|
+
article = Article.new
|
268
|
+
assert_not article.save
|
252
269
|
end
|
253
270
|
```
|
254
271
|
|
255
272
|
Let us run this newly added test.
|
256
273
|
|
257
274
|
```bash
|
258
|
-
$ bin/rake test test/models/
|
275
|
+
$ bin/rake test test/models/article_test.rb test_should_not_save_article_without_title
|
259
276
|
F
|
260
277
|
|
261
278
|
Finished tests in 0.044632s, 22.4054 tests/s, 22.4054 assertions/s.
|
262
279
|
|
263
280
|
1) Failure:
|
264
|
-
|
281
|
+
test_should_not_save_article_without_title(ArticleTest) [test/models/article_test.rb:6]:
|
265
282
|
Failed assertion, no message given.
|
266
283
|
|
267
284
|
1 tests, 1 assertions, 1 failures, 0 errors, 0 skips
|
@@ -270,9 +287,9 @@ Failed assertion, no message given.
|
|
270
287
|
In the output, `F` denotes a failure. You can see the corresponding trace shown under `1)` along with the name of the failing test. The next few lines contain the stack trace followed by a message which mentions the actual value and the expected value by the assertion. The default assertion messages provide just enough information to help pinpoint the error. To make the assertion failure message more readable, every assertion provides an optional message parameter, as shown here:
|
271
288
|
|
272
289
|
```ruby
|
273
|
-
test "should not save
|
274
|
-
|
275
|
-
assert_not
|
290
|
+
test "should not save article without title" do
|
291
|
+
article = Article.new
|
292
|
+
assert_not article.save, "Saved the article without a title"
|
276
293
|
end
|
277
294
|
```
|
278
295
|
|
@@ -280,14 +297,14 @@ Running this test shows the friendlier assertion message:
|
|
280
297
|
|
281
298
|
```bash
|
282
299
|
1) Failure:
|
283
|
-
|
284
|
-
Saved the
|
300
|
+
test_should_not_save_article_without_title(ArticleTest) [test/models/article_test.rb:6]:
|
301
|
+
Saved the article without a title
|
285
302
|
```
|
286
303
|
|
287
304
|
Now to get this test to pass we can add a model level validation for the _title_ field.
|
288
305
|
|
289
306
|
```ruby
|
290
|
-
class
|
307
|
+
class Article < ActiveRecord::Base
|
291
308
|
validates :title, presence: true
|
292
309
|
end
|
293
310
|
```
|
@@ -295,7 +312,7 @@ end
|
|
295
312
|
Now the test should pass. Let us verify by running the test again:
|
296
313
|
|
297
314
|
```bash
|
298
|
-
$ bin/rake test test/models/
|
315
|
+
$ bin/rake test test/models/article_test.rb test_should_not_save_article_without_title
|
299
316
|
.
|
300
317
|
|
301
318
|
Finished tests in 0.047721s, 20.9551 tests/s, 20.9551 assertions/s.
|
@@ -320,15 +337,15 @@ end
|
|
320
337
|
Now you can see even more output in the console from running the tests:
|
321
338
|
|
322
339
|
```bash
|
323
|
-
$ bin/rake test test/models/
|
340
|
+
$ bin/rake test test/models/article_test.rb test_should_report_error
|
324
341
|
E
|
325
342
|
|
326
343
|
Finished tests in 0.030974s, 32.2851 tests/s, 0.0000 assertions/s.
|
327
344
|
|
328
345
|
1) Error:
|
329
|
-
test_should_report_error(
|
330
|
-
NameError: undefined local variable or method `some_undefined_variable' for #<
|
331
|
-
test/models/
|
346
|
+
test_should_report_error(ArticleTest):
|
347
|
+
NameError: undefined local variable or method `some_undefined_variable' for #<ArticleTest:0x007fe32e24afe0>
|
348
|
+
test/models/article_test.rb:10:in `block in <class:ArticleTest>'
|
332
349
|
|
333
350
|
1 tests, 0 assertions, 0 failures, 1 errors, 0 skips
|
334
351
|
```
|
@@ -345,7 +362,7 @@ backtrace. simply set the `BACKTRACE` environment variable to enable this
|
|
345
362
|
behavior:
|
346
363
|
|
347
364
|
```bash
|
348
|
-
$ BACKTRACE=1 bin/rake test test/models/
|
365
|
+
$ BACKTRACE=1 bin/rake test test/models/article_test.rb
|
349
366
|
```
|
350
367
|
|
351
368
|
### What to Include in Your Unit Tests
|
@@ -357,7 +374,7 @@ Ideally, you would like to include a test for everything which could possibly br
|
|
357
374
|
By now you've caught a glimpse of some of the assertions that are available. Assertions are the worker bees of testing. They are the ones that actually perform the checks to ensure that things are going as planned.
|
358
375
|
|
359
376
|
There are a bunch of different types of assertions you can use.
|
360
|
-
Here's an extract of the assertions you can use with `minitest
|
377
|
+
Here's an extract of the assertions you can use with [`Minitest`](https://github.com/seattlerb/minitest), the default testing library used by Rails. The `[msg]` parameter is an optional string message you can specify to make your test failure messages clearer. It's not required.
|
361
378
|
|
362
379
|
| Assertion | Purpose |
|
363
380
|
| ---------------------------------------------------------------- | ------- |
|
@@ -369,8 +386,12 @@ Here's an extract of the assertions you can use with `minitest`, the default tes
|
|
369
386
|
| `assert_not_same( expected, actual, [msg] )` | Ensures that `expected.equal?(actual)` is false.|
|
370
387
|
| `assert_nil( obj, [msg] )` | Ensures that `obj.nil?` is true.|
|
371
388
|
| `assert_not_nil( obj, [msg] )` | Ensures that `obj.nil?` is false.|
|
389
|
+
| `assert_empty( obj, [msg] )` | Ensures that `obj` is `empty?`.|
|
390
|
+
| `assert_not_empty( obj, [msg] )` | Ensures that `obj` is not `empty?`.|
|
372
391
|
| `assert_match( regexp, string, [msg] )` | Ensures that a string matches the regular expression.|
|
373
392
|
| `assert_no_match( regexp, string, [msg] )` | Ensures that a string doesn't match the regular expression.|
|
393
|
+
| `assert_includes( collection, obj, [msg] )` | Ensures that `obj` is in `collection`.|
|
394
|
+
| `assert_not_includes( collection, obj, [msg] )` | Ensures that `obj` is not in `collection`.|
|
374
395
|
| `assert_in_delta( expecting, actual, [delta], [msg] )` | Ensures that the numbers `expected` and `actual` are within `delta` of each other.|
|
375
396
|
| `assert_not_in_delta( expecting, actual, [delta], [msg] )` | Ensures that the numbers `expected` and `actual` are not within `delta` of each other.|
|
376
397
|
| `assert_throws( symbol, [msg] ) { block }` | Ensures that the given block throws the symbol.|
|
@@ -384,16 +405,20 @@ Here's an extract of the assertions you can use with `minitest`, the default tes
|
|
384
405
|
| `assert_not_respond_to( obj, symbol, [msg] )` | Ensures that `obj` does not respond to `symbol`.|
|
385
406
|
| `assert_operator( obj1, operator, [obj2], [msg] )` | Ensures that `obj1.operator(obj2)` is true.|
|
386
407
|
| `assert_not_operator( obj1, operator, [obj2], [msg] )` | Ensures that `obj1.operator(obj2)` is false.|
|
408
|
+
| `assert_predicate ( obj, predicate, [msg] )` | Ensures that `obj.predicate` is true, e.g. `assert_predicate str, :empty?`|
|
409
|
+
| `assert_not_predicate ( obj, predicate, [msg] )` | Ensures that `obj.predicate` is false, e.g. `assert_not_predicate str, :empty?`|
|
387
410
|
| `assert_send( array, [msg] )` | Ensures that executing the method listed in `array[1]` on the object in `array[0]` with the parameters of `array[2 and up]` is true. This one is weird eh?|
|
388
411
|
| `flunk( [msg] )` | Ensures failure. This is useful to explicitly mark a test that isn't finished yet.|
|
389
412
|
|
413
|
+
The above are subset of assertions that minitest supports. For an exhaustive & more up-to-date list, please check [Minitest API documentation](http://docs.seattlerb.org/minitest/), specifically [`Minitest::Assertions`](http://docs.seattlerb.org/minitest/Minitest/Assertions.html)
|
414
|
+
|
390
415
|
Because of the modular nature of the testing framework, it is possible to create your own assertions. In fact, that's exactly what Rails does. It includes some specialized assertions to make your life easier.
|
391
416
|
|
392
417
|
NOTE: Creating your own assertions is an advanced topic that we won't cover in this tutorial.
|
393
418
|
|
394
419
|
### Rails Specific Assertions
|
395
420
|
|
396
|
-
Rails adds some custom assertions of its own to the `
|
421
|
+
Rails adds some custom assertions of its own to the `minitest` framework:
|
397
422
|
|
398
423
|
| Assertion | Purpose |
|
399
424
|
| --------------------------------------------------------------------------------- | ------- |
|
@@ -422,26 +447,26 @@ You should test for things such as:
|
|
422
447
|
* was the correct object stored in the response template?
|
423
448
|
* was the appropriate message displayed to the user in the view?
|
424
449
|
|
425
|
-
Now that we have used Rails scaffold generator for our `
|
450
|
+
Now that we have used Rails scaffold generator for our `Article` resource, it has already created the controller code and tests. You can take look at the file `articles_controller_test.rb` in the `test/controllers` directory.
|
426
451
|
|
427
|
-
Let me take you through one such test, `test_should_get_index` from the file `
|
452
|
+
Let me take you through one such test, `test_should_get_index` from the file `articles_controller_test.rb`.
|
428
453
|
|
429
454
|
```ruby
|
430
|
-
class
|
455
|
+
class ArticlesControllerTest < ActionController::TestCase
|
431
456
|
test "should get index" do
|
432
457
|
get :index
|
433
458
|
assert_response :success
|
434
|
-
assert_not_nil assigns(:
|
459
|
+
assert_not_nil assigns(:articles)
|
435
460
|
end
|
436
461
|
end
|
437
462
|
```
|
438
463
|
|
439
|
-
In the `test_should_get_index` test, Rails simulates a request on the action called `index`, making sure the request was successful and also ensuring that it assigns a valid `
|
464
|
+
In the `test_should_get_index` test, Rails simulates a request on the action called `index`, making sure the request was successful and also ensuring that it assigns a valid `articles` instance variable.
|
440
465
|
|
441
466
|
The `get` method kicks off the web request and populates the results into the response. It accepts 4 arguments:
|
442
467
|
|
443
468
|
* The action of the controller you are requesting. This can be in the form of a string or a symbol.
|
444
|
-
* An optional hash of request parameters to pass into the action (eg. query string parameters or
|
469
|
+
* An optional hash of request parameters to pass into the action (eg. query string parameters or article variables).
|
445
470
|
* An optional hash of session variables to pass along with the request.
|
446
471
|
* An optional hash of flash values.
|
447
472
|
|
@@ -457,17 +482,17 @@ Another example: Calling the `:view` action, passing an `id` of 12 as the `param
|
|
457
482
|
get(:view, {'id' => '12'}, nil, {'message' => 'booya!'})
|
458
483
|
```
|
459
484
|
|
460
|
-
NOTE: If you try running `
|
485
|
+
NOTE: If you try running `test_should_create_article` test from `articles_controller_test.rb` it will fail on account of the newly added model level validation and rightly so.
|
461
486
|
|
462
|
-
Let us modify `
|
487
|
+
Let us modify `test_should_create_article` test in `articles_controller_test.rb` so that all our test pass:
|
463
488
|
|
464
489
|
```ruby
|
465
|
-
test "should create
|
466
|
-
assert_difference('
|
467
|
-
post :create,
|
490
|
+
test "should create article" do
|
491
|
+
assert_difference('Article.count') do
|
492
|
+
post :create, article: {title: 'Some title'}
|
468
493
|
end
|
469
494
|
|
470
|
-
assert_redirected_to
|
495
|
+
assert_redirected_to article_path(assigns(:article))
|
471
496
|
end
|
472
497
|
```
|
473
498
|
|
@@ -576,12 +601,12 @@ is the correct way to assert for the layout when the view renders a partial with
|
|
576
601
|
Here's another example that uses `flash`, `assert_redirected_to`, and `assert_difference`:
|
577
602
|
|
578
603
|
```ruby
|
579
|
-
test "should create
|
580
|
-
assert_difference('
|
581
|
-
post :create,
|
604
|
+
test "should create article" do
|
605
|
+
assert_difference('Article.count') do
|
606
|
+
post :create, article: {title: 'Hi', body: 'This is my first article.'}
|
582
607
|
end
|
583
|
-
assert_redirected_to
|
584
|
-
assert_equal '
|
608
|
+
assert_redirected_to article_path(assigns(:article))
|
609
|
+
assert_equal 'Article was successfully created.', flash[:notice]
|
585
610
|
end
|
586
611
|
```
|
587
612
|
|
@@ -589,13 +614,13 @@ end
|
|
589
614
|
|
590
615
|
Testing the response to your request by asserting the presence of key HTML elements and their content is a useful way to test the views of your application. The `assert_select` assertion allows you to do this by using a simple yet powerful syntax.
|
591
616
|
|
592
|
-
NOTE: You may find references to `assert_tag` in other documentation
|
617
|
+
NOTE: You may find references to `assert_tag` in other documentation. This has been removed in 4.2. Use `assert_select` instead.
|
593
618
|
|
594
619
|
There are two forms of `assert_select`:
|
595
620
|
|
596
|
-
`assert_select(selector, [equality], [message])` ensures that the equality condition is met on the selected elements through the selector. The selector may be a CSS selector expression (String)
|
621
|
+
`assert_select(selector, [equality], [message])` ensures that the equality condition is met on the selected elements through the selector. The selector may be a CSS selector expression (String) or an expression with substitution values.
|
597
622
|
|
598
|
-
`assert_select(element, selector, [equality], [message])` ensures that the equality condition is met on all the selected elements through the selector starting from the _element_ (instance of `
|
623
|
+
`assert_select(element, selector, [equality], [message])` ensures that the equality condition is met on all the selected elements through the selector starting from the _element_ (instance of `Nokogiri::XML::Node` or `Nokogiri::XML::NodeSet`) and its descendants.
|
599
624
|
|
600
625
|
For example, you could verify the contents on the title element in your response with:
|
601
626
|
|
@@ -625,7 +650,7 @@ assert_select "ol" do
|
|
625
650
|
end
|
626
651
|
```
|
627
652
|
|
628
|
-
The `assert_select` assertion is quite powerful. For more advanced usage, refer to its [documentation](
|
653
|
+
The `assert_select` assertion is quite powerful. For more advanced usage, refer to its [documentation](https://github.com/rails/rails-dom-testing/blob/master/lib/rails/dom/testing/assertions/selector_assertions.rb).
|
629
654
|
|
630
655
|
#### Additional View-Based Assertions
|
631
656
|
|
@@ -710,9 +735,9 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
|
|
710
735
|
assert_equal 'Welcome david!', flash[:notice]
|
711
736
|
|
712
737
|
https!(false)
|
713
|
-
get "/
|
738
|
+
get "/articles/all"
|
714
739
|
assert_response :success
|
715
|
-
assert assigns(:
|
740
|
+
assert assigns(:articles)
|
716
741
|
end
|
717
742
|
end
|
718
743
|
```
|
@@ -769,76 +794,71 @@ end
|
|
769
794
|
Rake Tasks for Running your Tests
|
770
795
|
---------------------------------
|
771
796
|
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
when you initiate a Rails project.
|
797
|
+
Rails comes with a number of built-in rake tasks to help with testing. The
|
798
|
+
table below lists the commands included in the default Rakefile when a Rails
|
799
|
+
project is created.
|
776
800
|
|
777
801
|
| Tasks | Description |
|
778
802
|
| ----------------------- | ----------- |
|
779
|
-
| `rake test` | Runs all
|
803
|
+
| `rake test` | Runs all tests in the `test` folder. You can also simply run `rake` as Rails will run all the tests by default |
|
780
804
|
| `rake test:controllers` | Runs all the controller tests from `test/controllers` |
|
781
805
|
| `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional` |
|
782
806
|
| `rake test:helpers` | Runs all the helper tests from `test/helpers` |
|
783
807
|
| `rake test:integration` | Runs all the integration tests from `test/integration` |
|
808
|
+
| `rake test:jobs` | Runs all the job tests from `test/jobs` |
|
784
809
|
| `rake test:mailers` | Runs all the mailer tests from `test/mailers` |
|
785
810
|
| `rake test:models` | Runs all the model tests from `test/models` |
|
786
811
|
| `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit` |
|
787
|
-
| `rake test:
|
788
|
-
| `rake test:all:db` | Runs all tests quickly by merging all types and resetting db |
|
812
|
+
| `rake test:db` | Runs all tests in the `test` folder and resets the db |
|
789
813
|
|
790
814
|
|
791
|
-
Brief Note About
|
815
|
+
A Brief Note About Minitest
|
792
816
|
-----------------------------
|
793
817
|
|
794
|
-
Ruby ships with a
|
795
|
-
us to use all of the basic assertions in our tests.
|
818
|
+
Ruby ships with a vast Standard Library for all common use-cases including testing. Since version 1.9, Ruby provides `Minitest`, a framework for testing. All the basic assertions such as `assert_equal` discussed above are actually defined in `Minitest::Assertions`. The classes `ActiveSupport::TestCase`, `ActionController::TestCase`, `ActionMailer::TestCase`, `ActionView::TestCase` and `ActionDispatch::IntegrationTest` - which we have been inheriting in our test classes - include `Minitest::Assertions`, allowing us to use all of the basic assertions in our tests.
|
796
819
|
|
797
|
-
|
798
|
-
|
799
|
-
NOTE: For more information on `Test::Unit`, refer to [test/unit Documentation](http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/)
|
800
|
-
For more information on `MiniTest`, refer to [Minitest](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/minitest/unit/rdoc/)
|
820
|
+
NOTE: For more information on `Minitest`, refer to [Minitest](http://ruby-doc.org/stdlib-2.1.0/libdoc/minitest/rdoc/MiniTest.html)
|
801
821
|
|
802
822
|
Setup and Teardown
|
803
823
|
------------------
|
804
824
|
|
805
|
-
If you would like to run a block of code before the start of each test and another block of code after the end of each test you have two special callbacks for your rescue. Let's take note of this by looking at an example for our functional test in `
|
825
|
+
If you would like to run a block of code before the start of each test and another block of code after the end of each test you have two special callbacks for your rescue. Let's take note of this by looking at an example for our functional test in `Articles` controller:
|
806
826
|
|
807
827
|
```ruby
|
808
828
|
require 'test_helper'
|
809
829
|
|
810
|
-
class
|
830
|
+
class ArticlesControllerTest < ActionController::TestCase
|
811
831
|
|
812
832
|
# called before every single test
|
813
833
|
def setup
|
814
|
-
@
|
834
|
+
@article = articles(:one)
|
815
835
|
end
|
816
836
|
|
817
837
|
# called after every single test
|
818
838
|
def teardown
|
819
|
-
# as we are re-initializing @
|
839
|
+
# as we are re-initializing @article before every test
|
820
840
|
# setting it to nil here is not essential but I hope
|
821
841
|
# you understand how you can use the teardown method
|
822
|
-
@
|
842
|
+
@article = nil
|
823
843
|
end
|
824
844
|
|
825
|
-
test "should show
|
826
|
-
get :show, id: @
|
845
|
+
test "should show article" do
|
846
|
+
get :show, id: @article.id
|
827
847
|
assert_response :success
|
828
848
|
end
|
829
849
|
|
830
|
-
test "should destroy
|
831
|
-
assert_difference('
|
832
|
-
delete :destroy, id: @
|
850
|
+
test "should destroy article" do
|
851
|
+
assert_difference('Article.count', -1) do
|
852
|
+
delete :destroy, id: @article.id
|
833
853
|
end
|
834
854
|
|
835
|
-
assert_redirected_to
|
855
|
+
assert_redirected_to articles_path
|
836
856
|
end
|
837
857
|
|
838
858
|
end
|
839
859
|
```
|
840
860
|
|
841
|
-
Above, the `setup` method is called before each test and so `@
|
861
|
+
Above, the `setup` method is called before each test and so `@article` is available for each of the tests. Rails implements `setup` and `teardown` as `ActiveSupport::Callbacks`. Which essentially means you need not only use `setup` and `teardown` as methods in your tests. You could specify them by using:
|
842
862
|
|
843
863
|
* a block
|
844
864
|
* a method (like in the earlier example)
|
@@ -850,38 +870,38 @@ Let's see the earlier example by specifying `setup` callback by specifying a met
|
|
850
870
|
```ruby
|
851
871
|
require 'test_helper'
|
852
872
|
|
853
|
-
class
|
873
|
+
class ArticlesControllerTest < ActionController::TestCase
|
854
874
|
|
855
875
|
# called before every single test
|
856
|
-
setup :
|
876
|
+
setup :initialize_article
|
857
877
|
|
858
878
|
# called after every single test
|
859
879
|
def teardown
|
860
|
-
@
|
880
|
+
@article = nil
|
861
881
|
end
|
862
882
|
|
863
|
-
test "should show
|
864
|
-
get :show, id: @
|
883
|
+
test "should show article" do
|
884
|
+
get :show, id: @article.id
|
865
885
|
assert_response :success
|
866
886
|
end
|
867
887
|
|
868
|
-
test "should update
|
869
|
-
patch :update, id: @
|
870
|
-
assert_redirected_to
|
888
|
+
test "should update article" do
|
889
|
+
patch :update, id: @article.id, article: {}
|
890
|
+
assert_redirected_to article_path(assigns(:article))
|
871
891
|
end
|
872
892
|
|
873
|
-
test "should destroy
|
874
|
-
assert_difference('
|
875
|
-
delete :destroy, id: @
|
893
|
+
test "should destroy article" do
|
894
|
+
assert_difference('Article.count', -1) do
|
895
|
+
delete :destroy, id: @article.id
|
876
896
|
end
|
877
897
|
|
878
|
-
assert_redirected_to
|
898
|
+
assert_redirected_to articles_path
|
879
899
|
end
|
880
900
|
|
881
901
|
private
|
882
902
|
|
883
|
-
def
|
884
|
-
@
|
903
|
+
def initialize_article
|
904
|
+
@article = articles(:one)
|
885
905
|
end
|
886
906
|
end
|
887
907
|
```
|
@@ -889,11 +909,17 @@ end
|
|
889
909
|
Testing Routes
|
890
910
|
--------------
|
891
911
|
|
892
|
-
Like everything else in your Rails application, it is recommended that you test your routes.
|
912
|
+
Like everything else in your Rails application, it is recommended that you test your routes. Below are example tests for the routes of default `show` and `create` action of `Articles` controller above and it should look like:
|
893
913
|
|
894
914
|
```ruby
|
895
|
-
|
896
|
-
|
915
|
+
class ArticleRoutesTest < ActionController::TestCase
|
916
|
+
test "should route to article" do
|
917
|
+
assert_routing '/articles/1', { controller: "articles", action: "show", id: "1" }
|
918
|
+
end
|
919
|
+
|
920
|
+
test "should route to create article" do
|
921
|
+
assert_routing({ method: 'post', path: '/articles' }, { controller: "articles", action: "create" })
|
922
|
+
end
|
897
923
|
end
|
898
924
|
```
|
899
925
|
|
@@ -924,7 +950,7 @@ In order to test that your mailer is working as expected, you can use unit tests
|
|
924
950
|
|
925
951
|
For the purposes of unit testing a mailer, fixtures are used to provide an example of how the output _should_ look. Because these are example emails, and not Active Record data like the other fixtures, they are kept in their own subdirectory apart from the other fixtures. The name of the directory within `test/fixtures` directly corresponds to the name of the mailer. So, for a mailer named `UserMailer`, the fixtures should reside in `test/fixtures/user_mailer` directory.
|
926
952
|
|
927
|
-
|
953
|
+
If you generated your mailer, the generator does not create stub fixtures for the mailers actions. You'll have to create those files yourself as described above.
|
928
954
|
|
929
955
|
#### The Basic Test Case
|
930
956
|
|
@@ -937,7 +963,7 @@ class UserMailerTest < ActionMailer::TestCase
|
|
937
963
|
test "invite" do
|
938
964
|
# Send the email, then test that it got queued
|
939
965
|
email = UserMailer.create_invite('me@example.com',
|
940
|
-
'friend@example.com', Time.now).
|
966
|
+
'friend@example.com', Time.now).deliver_now
|
941
967
|
assert_not ActionMailer::Base.deliveries.empty?
|
942
968
|
|
943
969
|
# Test the body of the sent email contains what we expect it to
|
@@ -992,7 +1018,7 @@ class UserControllerTest < ActionController::TestCase
|
|
992
1018
|
|
993
1019
|
assert_equal "You have been invited by me@example.com", invite_email.subject
|
994
1020
|
assert_equal 'friend@example.com', invite_email.to[0]
|
995
|
-
assert_match(/Hi friend@example.com/, invite_email.body)
|
1021
|
+
assert_match(/Hi friend@example.com/, invite_email.body.to_s)
|
996
1022
|
end
|
997
1023
|
end
|
998
1024
|
```
|
@@ -1002,17 +1028,9 @@ Testing helpers
|
|
1002
1028
|
|
1003
1029
|
In order to test helpers, all you need to do is check that the output of the
|
1004
1030
|
helper method matches what you'd expect. Tests related to the helpers are
|
1005
|
-
located under the `test/helpers` directory.
|
1006
|
-
generates both the helper and the test file:
|
1007
|
-
|
1008
|
-
```bash
|
1009
|
-
$ bin/rails generate helper User
|
1010
|
-
create app/helpers/user_helper.rb
|
1011
|
-
invoke test_unit
|
1012
|
-
create test/helpers/user_helper_test.rb
|
1013
|
-
```
|
1031
|
+
located under the `test/helpers` directory.
|
1014
1032
|
|
1015
|
-
|
1033
|
+
A helper test looks like so:
|
1016
1034
|
|
1017
1035
|
```ruby
|
1018
1036
|
require 'test_helper'
|
@@ -1038,15 +1056,77 @@ end
|
|
1038
1056
|
Moreover, since the test class extends from `ActionView::TestCase`, you have
|
1039
1057
|
access to Rails' helper methods such as `link_to` or `pluralize`.
|
1040
1058
|
|
1059
|
+
Testing Jobs
|
1060
|
+
------------
|
1061
|
+
|
1062
|
+
Since your custom jobs can be queued at different levels inside your application,
|
1063
|
+
you'll need to test both jobs themselves (their behavior when they get enqueued)
|
1064
|
+
and that other entities correctly enqueue them.
|
1065
|
+
|
1066
|
+
### A Basic Test Case
|
1067
|
+
|
1068
|
+
By default, when you generate a job, an associated test will be generated as well
|
1069
|
+
under the `test/jobs` directory. Here's an example test with a billing job:
|
1070
|
+
|
1071
|
+
```ruby
|
1072
|
+
require 'test_helper'
|
1073
|
+
|
1074
|
+
class BillingJobTest < ActiveJob::TestCase
|
1075
|
+
test 'that account is charged' do
|
1076
|
+
BillingJob.perform_now(account, product)
|
1077
|
+
assert account.reload.charged_for?(product)
|
1078
|
+
end
|
1079
|
+
end
|
1080
|
+
```
|
1081
|
+
|
1082
|
+
This test is pretty simple and only asserts that the job get the work done
|
1083
|
+
as expected.
|
1084
|
+
|
1085
|
+
By default, `ActiveJob::TestCase` will set the queue adapter to `:test` so that
|
1086
|
+
your jobs are performed inline. It will also ensure that all previously performed
|
1087
|
+
and enqueued jobs are cleared before any test run so you can safely assume that
|
1088
|
+
no jobs have already been executed in the scope of each test.
|
1089
|
+
|
1090
|
+
### Custom Assertions And Testing Jobs Inside Other Components
|
1091
|
+
|
1092
|
+
Active Job ships with a bunch of custom assertions that can be used to lessen
|
1093
|
+
the verbosity of tests:
|
1094
|
+
|
1095
|
+
| Assertion | Purpose |
|
1096
|
+
| -------------------------------------- | ------- |
|
1097
|
+
| `assert_enqueued_jobs(number)` | Asserts that the number of enqueued jobs matches the given number. |
|
1098
|
+
| `assert_performed_jobs(number)` | Asserts that the number of performed jobs matches the given number. |
|
1099
|
+
| `assert_no_enqueued_jobs { ... }` | Asserts that no jobs have been enqueued. |
|
1100
|
+
| `assert_no_performed_jobs { ... }` | Asserts that no jobs have been performed. |
|
1101
|
+
| `assert_enqueued_with([args]) { ... }` | Asserts that the job passed in the block has been enqueued with the given arguments. |
|
1102
|
+
| `assert_performed_with([args]) { ... }`| Asserts that the job passed in the block has been performed with the given arguments. |
|
1103
|
+
|
1104
|
+
It's a good practice to ensure that your jobs correctly get enqueued or performed
|
1105
|
+
wherever you invoke them (e.g. inside your controllers). This is precisely where
|
1106
|
+
the custom assertions provided by Active Job are pretty useful. For instance,
|
1107
|
+
within a model:
|
1108
|
+
|
1109
|
+
```ruby
|
1110
|
+
require 'test_helper'
|
1111
|
+
|
1112
|
+
class ProductTest < ActiveJob::TestCase
|
1113
|
+
test 'billing job scheduling' do
|
1114
|
+
assert_enqueued_with(job: BillingJob) do
|
1115
|
+
product.charge(account)
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
```
|
1120
|
+
|
1041
1121
|
Other Testing Approaches
|
1042
1122
|
------------------------
|
1043
1123
|
|
1044
|
-
The built-in `
|
1124
|
+
The built-in `minitest` based testing is not the only way to test Rails applications. Rails developers have come up with a wide variety of other approaches and aids for testing, including:
|
1045
1125
|
|
1046
1126
|
* [NullDB](http://avdi.org/projects/nulldb/), a way to speed up testing by avoiding database use.
|
1047
1127
|
* [Factory Girl](https://github.com/thoughtbot/factory_girl/tree/master), a replacement for fixtures.
|
1048
|
-
* [Machinist](https://github.com/notahat/machinist/tree/master), another replacement for fixtures.
|
1049
1128
|
* [Fixture Builder](https://github.com/rdy/fixture_builder), a tool that compiles Ruby factories into fixtures before a test run.
|
1050
1129
|
* [MiniTest::Spec Rails](https://github.com/metaskills/minitest-spec-rails), use the MiniTest::Spec DSL within your rails tests.
|
1051
1130
|
* [Shoulda](http://www.thoughtbot.com/projects/shoulda), an extension to `test/unit` with additional helpers, macros, and assertions.
|
1052
1131
|
* [RSpec](http://relishapp.com/rspec), a behavior-driven development framework
|
1132
|
+
* [Capybara](http://jnicklas.github.com/capybara/), Acceptance test framework for web applications
|