- Notifications
You must be signed in to change notification settings - Fork1k
rspec/rspec-rails
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
rspec-rails
brings theRSpec testing framework toRuby on Railsas a drop-in alternative to its default testing framework, Minitest.
In RSpec, tests are not just scripts that verify your application code.They’re also specifications (orspecs, for short):detailed explanations of how the application is supposed to behave,expressed in plain English.
According toRSpec Rails new versioning strategy use:
rspec-rails
7.x for Rails 7.x.rspec-rails
6.x for Rails 6.1, 7.0 or 7.1.rspec-rails
5.x for Rails 5.2 or 6.x.rspec-rails
4.x for Rails from 5.x or 6.x.rspec-rails
3.x for Rails earlier than 5.0.rspec-rails
1.x for Rails 2.x.
IMPORTANT This README / branch refers to the current development build.See the7-1-maintenance
branch on Github if you want or require the latest stable release.
Add
rspec-rails
toboth the:development
and:test
groupsof your app’sGemfile
:# Run against this stable releasegroup:development,:testdogem'rspec-rails','~> 7.0.0'end# Or, run against the main branchgroup:development,:testdogem'rspec-rails',git:'https://github.com/rspec/rspec-rails'end
(Adding it to the
:development
group is not strictly necessary,but without it, generators and rake tasks must be preceded byRAILS_ENV=test
.)Then, in your project directory:
# Download and install$ bundle install# Generate boilerplate configuration files# (check the comments in each generated file for more information)$ rails generate rspec:install create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb
If your project is already using an older version ofrspec-rails
,upgrade to the latest version with:
$ bundle update rspec-rails
RSpec followssemantic versioning,which means that “major version” upgrades (e.g., 2.x → 3.x)come withbreaking changes.If you’re upgrading from version 2.x or below,read therspec-rails
upgrade notes to find out what to watch out for.
Be sure to check the generalRSpec upgrade notes as well.
# RSpec hooks into built-in generators$ rails generate model user invoke active_record create db/migrate/20181017040312_create_users.rb create app/models/user.rb invoke rspec create spec/models/user_spec.rb# RSpec also provides its own spec file generators$ rails generate rspec:model user create spec/models/user_spec.rb# List all RSpec generators$ rails generate --help| grep rspec
# Default: Run all spec files (i.e., those matching spec/**/*_spec.rb)$ bundleexec rspec# Run all spec files in a single directory (recursively)$ bundleexec rspec spec/models# Run a single spec file$ bundleexec rspec spec/controllers/accounts_controller_spec.rb# Run a single example from a spec file (by line number)$ bundleexec rspec spec/controllers/accounts_controller_spec.rb:8# See all options for running specs$ bundleexec rspec --help
Optional: Ifbundle exec rspec
is too verbose for you,you can generate a binstub atbin/rspec
and use that instead:
$ bundle binstubs rspec-core
In RSpec, application behavior is describedfirst in (almost) plain English, then again in test code, like so:
RSpec.describe'Post'do#context'before publication'do# (almost) plain Englishit'cannot have comments'do#expect{Post.create.comments.create!}.toraise_error(ActiveRecord::RecordInvalid)# test codeendendend
Runningrspec
will execute this test code,and then use the plain-English descriptionsto generate a report of where the applicationconforms to (or fails to meet) the spec:
$ rspec --format documentation spec/models/post_spec.rbPost before publication cannot have commentsFailures: 1) Post before publication cannot have comments Failure/Error: expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid) expected ActiveRecord::RecordInvalid but nothing was raised # ./spec/models/post.rb:4:in `block (3 levels) in <top (required)>'Finished in 0.00527 seconds (files took 0.29657 seconds to load)1 example, 1 failureFailed examples:rspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments
For an in-depth look at the RSpec DSL, including lots of examples,read the official Cucumber documentation forRSpec Core.
In RSpec, assertions are calledexpectations,and every expectation is built around amatcher.When youexpect(a).to eq(b)
, you’re using theeq
matcher.
In addition tothe matchers that come standard in RSpec,here are some extras that make it easierto test the various parts of a Rails system:
RSpec matcher | Delegates to | Available in | Notes |
---|---|---|---|
be_a_new | all | primarily intended for controller specs | |
render_template | assert_template | request / controller / view | use withexpect(response).to |
redirect_to | assert_redirect | request / controller | use withexpect(response).to |
route_to | assert_recognizes | routing / controller | use withexpect(...).to route_to |
be_routable | routing / controller | use withexpect(...).not_to be_routable | |
have_http_status | request / controller / feature | ||
match_array | all | for comparing arrays of ActiveRecord objects | |
have_been_enqueued | all | requires config:ActiveJob::Base.queue_adapter = :test | |
have_enqueued_job | all | requires config:ActiveJob::Base.queue_adapter = :test |
Follow the links above for examples of how each matcher is used.
For a comprehensive look at RSpec Rails’ features,read theofficial Cucumber documentation.
RSpec Rails defines ten differenttypes of specsfor testing different parts of a typical Rails application.Each one inherits from one of Rails’ built-inTestCase
classes,meaning the helper methods provided by default in Rails testsare available in RSpec, as well.
Spec type | Corresponding Rails test class |
---|---|
model | |
controller | ActionController::TestCase |
mailer | ActionMailer::TestCase |
job | |
view | ActionView::TestCase |
routing | |
helper | ActionView::TestCase |
request | ActionDispatch::IntegrationTest |
feature | |
system | ActionDispatch::SystemTestCase |
Follow the links above to see examples of each spec type,or for official Rails API documentation on the givenTestCase
class.
Note: This is not a checklist.
Ask a hundred developers how to test an application,and you’ll get a hundred different answers.
RSpec Rails provides thoughtfully selected featuresto encourage good testing practices, but there’s no “right” way to do it.Ultimately, it’s up to you to decide how your test suite will be composed.
When creating a spec file,assign it a type in the top-leveldescribe
block, like so:
# spec/models/user_spec.rbRSpec.describeUser,type::modeldo...
RSpec Rails provides some end-to-end (entire application) testing capabilityto specify the interaction with the client.
Also calledacceptance tests,browser tests, orend-to-end tests,system specs test the application from the perspective of ahuman client.The test code walks through a user’s browser interactions,
visit '/login'
fill_in 'Name', with: 'jdoe'
and the expectations revolve around page content.
expect(page).to have_text('Welcome')
Because system specs are a wrapper around Rails’ built-inSystemTestCase
,they’re only available on Rails 5.1+.(Feature specs serve the same purpose, but without this dependency.)
Before Rails introduced system testing facilities,feature specs were the only spec type for end-to-end testing.While the RSpec team nowofficially recommends system specs instead,feature specs are still fully supported, look basically identical,and work on older versions of Rails.
On the other hand, feature specs require non-trivial configurationto get some important features working,like JavaScript testing or making sure each test runs with a fresh DB state.With system specs, this configuration is provided out-of-the-box.
Like system specs, feature specs require theCapybara gem.Rails 5.1+ includes it by default as part of system tests,but if you don’t have the luxury of upgrading,be sure to add it to the:test
group of yourGemfile
first:
group:testdogem"capybara"end
Request specs are for testing the applicationfrom the perspective of amachine client.They begin with an HTTP request and end with the HTTP response,so they’re faster than feature specs,but do not examine your app’s UI or JavaScript.
Request specs provide a high-level alternative to controller specs.In fact, as of RSpec 3.5, both the Rails and RSpec teamsdiscourage directly testing controllersin favor of functional tests like request specs.
When writing them, try to answer the question,“For a given HTTP request (verb + path + parameters),what HTTP response should the application return?”
Once you’ve cloned the repo andset up the environment,you can run the specs and Cucumber features, or submit a pull request.
- FactoryBot
- Capybara(Included by default in Rails 5.1+.Note thatadditional configuration is required to use the Capybara DSLanywhere other than system specs and feature specs.)
About
RSpec for Rails 7+