aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/testing.md
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source/testing.md')
-rw-r--r--guides/source/testing.md171
1 files changed, 148 insertions, 23 deletions
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 4ee3267261..9fd29672c7 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -1,7 +1,7 @@
**DO NOT READ THIS FILE ON GITHUB, GUIDES ARE PUBLISHED ON http://guides.rubyonrails.org.**
-A Guide to Testing Rails Applications
-=====================================
+Testing Rails Applications
+==========================
This guide covers built-in mechanisms in Rails for testing your application.
@@ -33,8 +33,8 @@ Rails creates a `test` directory for you as soon as you create a Rails project u
```bash
$ ls -F test
-controllers/ helpers/ mailers/ system/ test_helper.rb
-fixtures/ integration/ models/ application_system_test_case.rb
+application_system_test_case.rb fixtures/ integration/ models/ test_helper.rb
+controllers/ helpers/ mailers/ system/
```
The `helpers`, `mailers`, and `models` directories are meant to hold tests for view helpers, mailers, and models, respectively. The `controllers` directory is meant to hold tests for controllers, routes, and views. The `integration` directory is meant to hold tests for interactions between controllers.
@@ -319,6 +319,8 @@ specify to make your test failure messages clearer.
| `assert_not_includes( collection, obj, [msg] )` | Ensures that `obj` is not in `collection`.|
| `assert_in_delta( expected, actual, [delta], [msg] )` | Ensures that the numbers `expected` and `actual` are within `delta` of each other.|
| `assert_not_in_delta( expected, actual, [delta], [msg] )` | Ensures that the numbers `expected` and `actual` are not within `delta` of each other.|
+| `assert_in_epsilon ( expected, actual, [epsilon], [msg] )` | Ensures that the numbers `expected` and `actual` have a relative error less than `epsilon`.|
+| `assert_not_in_epsilon ( expected, actual, [epsilon], [msg] )` | Ensures that the numbers `expected` and `actual` don't have a relative error less than `epsilon`.|
| `assert_throws( symbol, [msg] ) { block }` | Ensures that the given block throws the symbol.|
| `assert_raises( exception1, exception2, ... ) { block }` | Ensures that the given block raises one of the given exceptions.|
| `assert_instance_of( class, obj, [msg] )` | Ensures that `obj` is an instance of `class`.|
@@ -431,16 +433,8 @@ at the end of test run and so on. Check the documentation of the test runner as
```bash
$ bin/rails test -h
-minitest options:
- -h, --help Display this help.
- -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake
- -v, --verbose Verbose. Show progress processing files.
- -n, --name PATTERN Filter run on /regexp/ or string.
- --exclude PATTERN Exclude /regexp/ or string from run.
-
-Known extensions: rails, pride
-
Usage: bin/rails test [options] [files or directories]
+
You can run a single test by appending a line number to a filename:
bin/rails test test/models/user_test.rb:27
@@ -451,13 +445,105 @@ You can run multiple files and directories at the same time:
By default test failures and errors are reported inline during a run.
-Rails options:
+minitest options:
+ -h, --help Display this help.
+ --no-plugins Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS).
+ -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake
+ -v, --verbose Verbose. Show progress processing files.
+ -n, --name PATTERN Filter run on /regexp/ or string.
+ --exclude PATTERN Exclude /regexp/ or string from run.
+
+Known extensions: rails, pride
-w, --warnings Run with Ruby warnings enabled
- -e, --environment Run tests in the ENV environment
+ -e, --environment ENV Run tests in the ENV environment
-b, --backtrace Show the complete backtrace
-d, --defer-output Output test failures and errors after the test run
-f, --fail-fast Abort test run on first failure or error
-c, --[no-]color Enable color in the output
+ -p, --pride Pride. Show your testing pride!
+```
+
+Parallel Testing
+----------------
+
+Parallel testing allows you to parallelize your test suite. While forking processes is the
+default method, threading is supported as well. Running tests in parallel reduces the time it
+takes your entire test suite to run.
+
+### Parallel testing with processes
+
+The default parallelization method is to fork processes using Ruby's DRb system. The processes
+are forked based on the number of workers provided. The default is 2, but can be changed by the
+number passed to the parallelize method. Active Record automatically handles creating and
+migrating a new database for each worker to use.
+
+To enable parallelization add the following to your `test_helper.rb`:
+
+```
+class ActiveSupport::TestCase
+ parallelize(workers: 2)
+end
+```
+
+The number of workers passed is the number of times the process will be forked. You may want to
+parallelize your local test suite differently from your CI, so an environment variable is provided
+to be able to easily change the number of workers a test run should use:
+
+```
+PARALLEL_WORKERS=15 bin/rails test
+```
+
+When parallelizing tests, Active Record automatically handles creating and migrating a database for each
+process. The databases will be suffixed with the number corresponding to the worker. For example, if you
+have 2 workers the tests will create `test-database-0` and `test-database-1` respectively.
+
+If the number of workers passed is 1 or fewer the processes will not be forked and the tests will not
+be parallelized and the tests will use the original `test-database` database.
+
+Two hooks are provided, one runs when the process is forked, and one runs before the processes are closed.
+These can be useful if your app uses multiple databases or perform other tasks that depend on the number of
+workers.
+
+The `parallelize_setup` method is called right after the processes are forked. The `parallelize_teardown` metod
+is called right before the processes are closed.
+
+```
+class ActiveSupport::TestCase
+ parallelize_setup do |worker|
+ # setup databases
+ end
+
+ parallelize_teardown do |worker|
+ # cleanup database
+ end
+
+ parallelize(workers: 2)
+end
+```
+
+These methods are not needed or available when using parallel testing with threads.
+
+### Parallel testing with threads
+
+If you prefer using threads or are using JRuby, a threaded parallelization option is provided. The threaded
+parallelizer is backed by Minitest's `Parallel::Executor`.
+
+To change the parallelization method to use threads over forks put the following in your `test_helper.rb`
+
+```
+class ActiveSupport::TestCase
+ parallelize(workers: 2, with: :threads)
+end
+```
+
+Rails applications generated from JRuby will automatically include the `with: :threads` option.
+
+The number of workers passed to `parallelize` determines the number of threads the tests will use. You may
+want to parallelize your local test suite differently from your CI, so an environment variable is provided
+to be able to easily change the number of workers a test run should use:
+
+```
+PARALLEL_WORKERS=15 bin/rails test
```
The Test Database
@@ -605,7 +691,7 @@ System Testing
--------------
System tests allow you to test user interactions with your application, running tests
-in either a real or a headless browser. System tests uses Capybara under the hood.
+in either a real or a headless browser. System tests use Capybara under the hood.
For creating Rails system tests, you use the `test/system` directory in your
application. Rails provides a generator to create a system test skeleton for you.
@@ -645,7 +731,7 @@ system tests should live.
If you want to change the default settings you can change what the system
tests are "driven by". Say you want to change the driver from Selenium to
-Poltergeist. First add the `poltergeist` gem to your Gemfile. Then in your
+Poltergeist. First add the `poltergeist` gem to your `Gemfile`. Then in your
`application_system_test_case.rb` file do the following:
```ruby
@@ -671,6 +757,17 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
end
```
+If you want to use a headless browser, you could use Headless Chrome or Headless Firefox by adding
+`headless_chrome` or `headless_firefox` in the `:using` argument.
+
+```ruby
+require "test_helper"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+ driven_by :selenium, using: :headless_chrome
+end
+```
+
If your Capybara configuration requires more setup than provided by Rails, this
additional configuration could be added into the `application_system_test_case.rb`
file.
@@ -765,9 +862,37 @@ Then the test will fill in the title and body of the article with the specified
text. Once the fields are filled in, "Create Article" is clicked on which will
send a POST request to create the new article in the database.
-We will be redirected back to the the articles index page and there we assert
+We will be redirected back to the articles index page and there we assert
that the text from the new article's title is on the articles index page.
+#### Testing for multiple screen sizes
+If you want to test for mobile sizes on top of testing for desktop,
+you can create another class that inherits from SystemTestCase and use in your
+test suite. In this example a file called `mobile_system_test_case.rb` is created
+in the `/test` directory with the following configuration.
+
+```ruby
+require "test_helper"
+
+class MobileSystemTestCase < ActionDispatch::SystemTestCase
+ driven_by :selenium, using: :chrome, screen_size: [375, 667]
+end
+```
+To use this configuration, create a test inside `test/system` that inherits from `MobileSystemTestCase`.
+Now you can test your app using multiple different configurations.
+
+```ruby
+require "mobile_system_test_case"
+
+class PostsTest < MobileSystemTestCase
+
+ test "visiting the index" do
+ visit posts_url
+ assert_selector "h1", text: "Posts"
+ end
+end
+```
+
#### Taking it further
The beauty of system testing is that it is similar to integration testing in
@@ -1360,7 +1485,7 @@ located under the `test/helpers` directory.
Given we have the following helper:
```ruby
-module UserHelper
+module UsersHelper
def link_to_user(user)
link_to "#{user.first_name} #{user.last_name}", user
end
@@ -1370,7 +1495,7 @@ end
We can test the output of this method like this:
```ruby
-class UserHelperTest < ActionView::TestCase
+class UsersHelperTest < ActionView::TestCase
test "should return the user's full name" do
user = users(:david)
@@ -1476,7 +1601,7 @@ Functional testing for mailers involves more than just checking that the email b
```ruby
require 'test_helper'
-class UserControllerTest < ActionDispatch::IntegrationTest
+class UsersControllerTest < ActionDispatch::IntegrationTest
test "invite friend" do
assert_difference 'ActionMailer::Base.deliveries.size', +1 do
post invite_friend_url, params: { email: 'friend@example.com' }
@@ -1494,7 +1619,7 @@ Testing Jobs
------------
Since your custom jobs can be queued at different levels inside your application,
-you'll need to test both, the jobs themselves (their behavior when they get enqueued)
+you'll need to test both the jobs themselves (their behavior when they get enqueued)
and that other entities correctly enqueue them.
### A Basic Test Case
@@ -1513,7 +1638,7 @@ class BillingJobTest < ActiveJob::TestCase
end
```
-This test is pretty simple and only asserts that the job get the work done
+This test is pretty simple and only asserts that the job got the work done
as expected.
By default, `ActiveJob::TestCase` will set the queue adapter to `:test` so that