diff options
Diffstat (limited to 'guides/source/testing.md')
-rw-r--r-- | guides/source/testing.md | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/guides/source/testing.md b/guides/source/testing.md index 6678db21f8..d54f431d54 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -82,7 +82,7 @@ Each fixture is given a name followed by an indented list of colon-separated key If you are working with [associations](/association_basics.html), you can simply define a reference node between two different fixtures. Here's an example with -a belongs_to/has_many association: +a `belongs_to`/`has_many` association: ```yaml # In fixtures/categories.yml @@ -728,7 +728,7 @@ class UserFlowsTest < ActionDispatch::IntegrationTest https!(false) get "/articles/all" assert_response :success - assert assigns(:products) + assert assigns(:articles) end end ``` @@ -785,14 +785,13 @@ end Rake Tasks for Running your Tests --------------------------------- -You don't need to set up and run your tests by hand on a test-by-test basis. -Rails comes with a number of commands to help in testing. -The table below lists all commands that come along in the default Rakefile -when you initiate a Rails project. +Rails comes with a number of built-in rake tasks to help with testing. The +table below lists the commands included in the default Rakefile when a Rails +project is created. | Tasks | Description | | ----------------------- | ----------- | -| `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake` as Rails will run all the tests by default | +| `rake test` | Runs all tests in the `test` folder. You can also simply run `rake` as Rails will run all the tests by default | | `rake test:controllers` | Runs all the controller tests from `test/controllers` | | `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional` | | `rake test:helpers` | Runs all the helper tests from `test/helpers` | @@ -801,11 +800,10 @@ when you initiate a Rails project. | `rake test:mailers` | Runs all the mailer tests from `test/mailers` | | `rake test:models` | Runs all the model tests from `test/models` | | `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit` | -| `rake test:all` | Runs all tests quickly by merging all types and not resetting db | -| `rake test:all:db` | Runs all tests quickly by merging all types and resetting db | +| `rake test:db` | Runs all tests in the `test` folder and resets the db | -Brief Note About `Minitest` +A Brief Note About Minitest ----------------------------- 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. @@ -902,13 +900,17 @@ end Testing Routes -------------- -Like everything else in your Rails application, it is recommended that you test your routes. An example test for a route in the default `show` action of `Articles` controller above should look like: +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: ```ruby class ArticleRoutesTest < ActionController::TestCase test "should route to article" do assert_routing '/articles/1', { controller: "articles", action: "show", id: "1" } end + + test "should route to create article" do + assert_routing({ method: 'post', path: '/articles' }, { controller: "articles", action: "create" }) + end end ``` @@ -1045,6 +1047,68 @@ end Moreover, since the test class extends from `ActionView::TestCase`, you have access to Rails' helper methods such as `link_to` or `pluralize`. +Testing Jobs +------------ + +Since your custom jobs can be queued at different levels inside your application, +you'll need to test both jobs themselves (their behavior when they get enqueued) +and that other entities correctly enqueue them. + +### A Basic Test Case + +By default, when you generate a job, an associated test will be generated as well +under the `test/jobs` directory. Here's an example test with a billing job: + +```ruby +require 'test_helper' + +class BillingJobTest < ActiveJob::TestCase + test 'that account is charged' do + BillingJob.perform_now(account, product) + assert account.reload.charged_for?(product) + end +end +``` + +This test is pretty simple and only asserts that the job get the work done +as expected. + +By default, `ActiveJob::TestCase` will set the queue adapter to `:test` so that +your jobs are performed inline. It will also ensure that all previously performed +and enqueued jobs are cleared before any test run so you can safely assume that +no jobs have already been executed in the scope of each test. + +### Custom Assertions And Testing Jobs Inside Other Components + +Active Job ships with a bunch of custom assertions that can be used to lessen +the verbosity of tests: + +| Assertion | Purpose | +| -------------------------------------- | ------- | +| `assert_enqueued_jobs(number)` | Asserts that the number of enqueued jobs matches the given number. | +| `assert_performed_jobs(number)` | Asserts that the number of performed jobs matches the given number. | +| `assert_no_enqueued_jobs { ... }` | Asserts that no jobs have been enqueued. | +| `assert_no_performed_jobs { ... }` | Asserts that no jobs have been performed. | +| `assert_enqueued_with([args]) { ... }` | Asserts that the job passed in the block has been enqueued with the given arguments. | +| `assert_performed_with([args]) { ... }`| Asserts that the job passed in the block has been performed with the given arguments. | + +It's a good practice to ensure that your jobs correctly get enqueued or performed +wherever you invoke them (e.g. inside your controllers). This is precisely where +the custom assertions provided by Active Job are pretty useful. For instance, +within a model: + +```ruby +require 'test_helper' + +class ProductTest < ActiveSupport::TestCase + test 'billing job scheduling' do + assert_enqueued_with(job: BillingJob) do + product.charge(account) + end + end +end +``` + Other Testing Approaches ------------------------ @@ -1056,3 +1120,4 @@ The built-in `minitest` based testing is not the only way to test Rails applicat * [MiniTest::Spec Rails](https://github.com/metaskills/minitest-spec-rails), use the MiniTest::Spec DSL within your rails tests. * [Shoulda](http://www.thoughtbot.com/projects/shoulda), an extension to `test/unit` with additional helpers, macros, and assertions. * [RSpec](http://relishapp.com/rspec), a behavior-driven development framework +* [Capybara](http://jnicklas.github.com/capybara/), Acceptance test framework for web applications |