{"id":13428091,"url":"https://github.com/rspec/rspec-rails","last_synced_at":"2025-05-12T22:21:30.615Z","repository":{"id":37789379,"uuid":"447184","full_name":"rspec/rspec-rails","owner":"rspec","description":"RSpec for Rails 7+","archived":false,"fork":false,"pushed_at":"2025-04-30T14:50:58.000Z","size":4998,"stargazers_count":5215,"open_issues_count":50,"forks_count":1043,"subscribers_count":88,"default_branch":"main","last_synced_at":"2025-05-05T10:08:05.003Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://rspec.info","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rspec.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["JonRowe","benoittgt"],"open_collective":"rspec"}},"created_at":"2009-12-23T16:40:53.000Z","updated_at":"2025-05-02T13:48:09.000Z","dependencies_parsed_at":"2024-04-09T12:56:42.204Z","dependency_job_id":"8dd27f49-5b7e-4ccb-b090-567ff7ab324a","html_url":"https://github.com/rspec/rspec-rails","commit_stats":{"total_commits":3102,"total_committers":434,"mean_commits":7.147465437788019,"dds":0.7195357833655707,"last_synced_commit":"609bb83a76c11c67076ff2619fd5f47edd6325ce"},"previous_names":[],"tags_count":161,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rspec","download_url":"https://codeload.github.com/rspec/rspec-rails/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252530562,"owners_count":21763283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T01:00:45.825Z","updated_at":"2025-05-05T16:01:46.148Z","avatar_url":"https://github.com/rspec.png","language":"Ruby","funding_links":["https://github.com/sponsors/JonRowe","https://github.com/sponsors/benoittgt","https://opencollective.com/rspec"],"categories":["Testing","Ruby","Web 后端","Testing \u0026 QA","测试","Gems","Testing \u0026 Quality Assurance"],"sub_categories":["Omniauth","Testing","Articles"],"readme":"# rspec-rails [![Code Climate][]][code-climate] [![Gem Version][]][gem-version]\n\n`rspec-rails` brings the [RSpec][] testing framework to [Ruby on Rails][]\nas a drop-in alternative to its default testing framework, Minitest.\n\nIn RSpec, tests are not just scripts that verify your application code.\nThey’re also specifications (or _specs,_ for short):\ndetailed explanations of how the application is supposed to behave,\nexpressed in plain English.\n\nAccording to [RSpec Rails new versioning strategy][] use:\n* **[`rspec-rails` 7.x][]** for Rails 7.x.\n* **[`rspec-rails` 6.x][]** for Rails 6.1, 7.0 or 7.1.\n* **[`rspec-rails` 5.x][]** for Rails 5.2 or 6.x.\n* **[`rspec-rails` 4.x][]** for Rails from 5.x or 6.x.\n* **[`rspec-rails` 3.x][]** for Rails earlier than 5.0.\n* **[`rspec-rails` 1.x][]** for Rails 2.x.\n\n[Code Climate]: https://codeclimate.com/github/rspec/rspec-rails.svg\n[code-climate]: https://codeclimate.com/github/rspec/rspec-rails\n[Gem Version]: https://badge.fury.io/rb/rspec-rails.svg\n[gem-version]: https://badge.fury.io/rb/rspec-rails\n[RSpec]: https://rspec.info/\n[Ruby on Rails]: https://rubyonrails.org/\n[`rspec-rails` 1.x]: https://github.com/dchelimsky/rspec-rails\n[`rspec-rails` 3.x]: https://github.com/rspec/rspec-rails/tree/3-9-maintenance\n[`rspec-rails` 4.x]: https://github.com/rspec/rspec-rails/tree/4-1-maintenance\n[`rspec-rails` 5.x]: https://github.com/rspec/rspec-rails/tree/5-1-maintenance\n[`rspec-rails` 6.x]: https://github.com/rspec/rspec-rails/tree/6-1-maintenance\n[`rspec-rails` 7.x]: https://github.com/rspec/rspec-rails/tree/7-1-maintenance\n[RSpec Rails new versioning strategy]: https://github.com/rspec/rspec-rails/blob/main/rfcs/versioning-strategy.md\n\n## Installation\n\n**IMPORTANT** This README / branch refers to the current development build.\nSee the [`7-1-maintenance` branch on Github](https://github.com/rspec/rspec-rails/tree/7-1-maintenance) if you want or require the latest stable release.\n\n1. Add `rspec-rails` to **both** the `:development` and `:test` groups\n   of your app’s `Gemfile`:\n\n   ```ruby\n   # Run against this stable release\n   group :development, :test do\n     gem 'rspec-rails', '~\u003e 7.0.0'\n   end\n\n   # Or, run against the main branch\n   group :development, :test do\n     gem 'rspec-rails', git: 'https://github.com/rspec/rspec-rails'\n   end\n   ```\n\n   (Adding it to the `:development` group is not strictly necessary,\n   but without it, generators and rake tasks must be preceded by `RAILS_ENV=test`.)\n\n2. Then, in your project directory:\n\n   ```sh\n   # Download and install\n   $ bundle install\n\n   # Generate boilerplate configuration files\n   # (check the comments in each generated file for more information)\n   $ rails generate rspec:install\n         create  .rspec\n         create  spec\n         create  spec/spec_helper.rb\n         create  spec/rails_helper.rb\n   ```\n\n## Upgrading\n\nIf your project is already using an older version of `rspec-rails`,\nupgrade to the latest version with:\n\n```sh\n$ bundle update rspec-rails\n```\n\nRSpec follows [semantic versioning](https://semver.org/),\nwhich means that “major version” upgrades (_e.g.,_ 2.x → 3.x)\ncome with **breaking changes**.\nIf you’re upgrading from version 2.x or below,\nread the [`rspec-rails` upgrade notes][] to find out what to watch out for.\n\nBe sure to check the general [RSpec upgrade notes][] as well.\n\n[`rspec-rails` upgrade notes]: https://rspec.info/features/7-1/rspec-rails/upgrade\n[RSpec upgrade notes]: https://rspec.info/upgrading-from-rspec-2/\n\n## Usage\n\n### Creating boilerplate specs with `rails generate`\n\n```sh\n# RSpec hooks into built-in generators\n$ rails generate model user\n      invoke  active_record\n      create    db/migrate/20181017040312_create_users.rb\n      create    app/models/user.rb\n      invoke    rspec\n      create      spec/models/user_spec.rb\n\n# RSpec also provides its own spec file generators\n$ rails generate rspec:model user\n      create  spec/models/user_spec.rb\n\n# List all RSpec generators\n$ rails generate --help | grep rspec\n```\n\n### Running specs\n\n```sh\n# Default: Run all spec files (i.e., those matching spec/**/*_spec.rb)\n$ bundle exec rspec\n\n# Run all spec files in a single directory (recursively)\n$ bundle exec rspec spec/models\n\n# Run a single spec file\n$ bundle exec rspec spec/controllers/accounts_controller_spec.rb\n\n# Run a single example from a spec file (by line number)\n$ bundle exec rspec spec/controllers/accounts_controller_spec.rb:8\n\n# See all options for running specs\n$ bundle exec rspec --help\n```\n\n**Optional:** If `bundle exec rspec` is too verbose for you,\nyou can generate a binstub at `bin/rspec` and use that instead:\n\n ```sh\n $ bundle binstubs rspec-core\n ```\n\n## RSpec DSL Basics (or, how do I write a spec?)\n\nIn RSpec, application behavior is described\n**first in (almost) plain English, then again in test code**, like so:\n\n```ruby\nRSpec.describe 'Post' do           #\n  context 'before publication' do  # (almost) plain English\n    it 'cannot have comments' do   #\n      expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid)  # test code\n    end\n  end\nend\n```\n\nRunning `rspec` will execute this test code,\nand then use the plain-English descriptions\nto generate a report of where the application\nconforms to (or fails to meet) the spec:\n\n```\n$ rspec --format documentation spec/models/post_spec.rb\n\nPost\n  before publication\n    cannot have comments\n\nFailures:\n\n  1) Post before publication cannot have comments\n     Failure/Error: expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid)\n       expected ActiveRecord::RecordInvalid but nothing was raised\n     # ./spec/models/post.rb:4:in `block (3 levels) in \u003ctop (required)\u003e'\n\nFinished in 0.00527 seconds (files took 0.29657 seconds to load)\n1 example, 1 failure\n\nFailed examples:\n\nrspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments\n```\n\nFor an in-depth look at the RSpec DSL, including lots of examples,\nread the official Cucumber documentation for [RSpec Core][].\n\n[RSpec Core]: https://rspec.info/features/3-12/rspec-core\n\n### Helpful Rails Matchers\n\nIn RSpec, assertions are called _expectations,_\nand every expectation is built around a _matcher._\nWhen you `expect(a).to eq(b)`, you’re using the `eq` matcher.\n\nIn addition to [the matchers that come standard in RSpec][],\nhere are some extras that make it easier\nto test the various parts of a Rails system:\n\n| RSpec matcher            | Delegates to        | Available in                    | Notes                                                    |\n| ------------------------ | ------------------- | ------------------------------- | -------------------------------------------------------- |\n| [`be_a_new`][]           |                     | all                             | primarily intended for controller specs                  |\n| [`render_template`][]    | `assert_template`   | request / controller / view     | use with `expect(response).to`                           |\n| [`redirect_to`][]        | `assert_redirect`   | request / controller            | use with `expect(response).to`                           |\n| [`route_to`]             | `assert_recognizes` | routing / controller            | use with `expect(...).to route_to`                       |\n| [`be_routable`]          |                     | routing / controller            | use with `expect(...).not_to be_routable`                |\n| [`have_http_status`][]   |                     | request / controller / feature  |                                                          |\n| [`match_array`][]        |                     | all                             | for comparing arrays of ActiveRecord objects             |\n| [`have_been_enqueued`][] |                     | all                             | requires config: `ActiveJob::Base.queue_adapter = :test` |\n| [`have_enqueued_job`][]  |                     | all                             | requires config: `ActiveJob::Base.queue_adapter = :test` |\n\nFollow the links above for examples of how each matcher is used.\n\n[the matchers that come standard in RSpec]: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers\n[`be_a_new`]: https://rspec.info/features/7-1/rspec-rails/matchers/new-record-matcher\n[`render_template`]: https://rspec.info/features/7-1/rspec-rails/matchers/render-template-matcher\n[`redirect_to`]: https://rspec.info/features/7-1/rspec-rails/matchers/redirect-to-matcher\n[`route_to`]: https://rspec.info/features/7-1/rspec-rails/routing-specs/route-to-matcher\n[`be_routable`]: https://rspec.info/features/7-1/rspec-rails/routing-specs/be-routable-matcher\n[`have_http_status`]: https://rspec.info/features/7-1/rspec-rails/matchers/have-http-status-matcher\n[`match_array`]: https://rspec.info/features/7-1/rspec-rails/matchers/relation-match-array\n[`have_been_enqueued`]: https://rspec.info/features/7-1/rspec-rails/matchers/have-been-enqueued-matcher\n[`have_enqueued_job`]: https://rspec.info/features/7-1/rspec-rails/matchers/have-enqueued-job-matcher\n\n### What else does RSpec Rails add?\n\nFor a comprehensive look at RSpec Rails’ features,\nread the [official Cucumber documentation][].\n\n[official Cucumber documentation]: https://rspec.info/features/7-1/rspec-rails\n\n## What tests should I write?\n\nRSpec Rails defines ten different _types_ of specs\nfor testing different parts of a typical Rails application.\nEach one inherits from one of Rails’ built-in `TestCase` classes,\nmeaning the helper methods provided by default in Rails tests\nare available in RSpec, as well.\n\n| Spec type      | Corresponding Rails test class        |\n| -------------- | --------------------------------      |\n| [model][]      |                                       |\n| [controller][] | [`ActionController::TestCase`][]      |\n| [mailer][]     | `ActionMailer::TestCase`              |\n| [job][]        |                                       |\n| [view][]       | `ActionView::TestCase`                |\n| [routing][]    |                                       |\n| [helper][]     | `ActionView::TestCase`                |\n| [request][]    | [`ActionDispatch::IntegrationTest`][] |\n| [feature][]    |                                       |\n| [system][]     | [`ActionDispatch::SystemTestCase`][]  |\n\nFollow the links above to see examples of each spec type,\nor for official Rails API documentation on the given `TestCase` class.\n\n\u003e **Note: This is not a checklist.**\n\u003e\n\u003e Ask a hundred developers how to test an application,\n\u003e and you’ll get a hundred different answers.\n\u003e\n\u003e RSpec Rails provides thoughtfully selected features\n\u003e to encourage good testing practices, but there’s no “right” way to do it.\n\u003e Ultimately, it’s up to you to decide how your test suite will be composed.\n\nWhen creating a spec file,\nassign it a type in the top-level `describe` block, like so:\n\n```ruby\n# spec/models/user_spec.rb\n\nRSpec.describe User, type: :model do\n...\n```\n\n[request]: https://rspec.info/features/7-1/rspec-rails/request-specs/request-spec\n[feature]: https://rspec.info/features/7-1/rspec-rails/feature-specs/feature-spec\n[system]: https://rspec.info/features/7-1/rspec-rails/system-specs/system-specs\n[model]: https://rspec.info/features/7-1/rspec-rails/model-specs\n[controller]: https://rspec.info/features/7-1/rspec-rails/controller-specs\n[mailer]: https://rspec.info/features/7-1/rspec-rails/mailer-specs\n[job]: https://rspec.info/features/7-1/rspec-rails/job-specs/job-spec\n[view]: https://rspec.info/features/7-1/rspec-rails/view-specs/view-spec\n[routing]: https://rspec.info/features/7-1/rspec-rails/routing-specs\n[helper]: https://rspec.info/features/7-1/rspec-rails/helper-specs/helper-spec\n[`ActionDispatch::IntegrationTest`]: https://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html\n[`ActionDispatch::SystemTestCase`]: https://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html\n[`ActionController::TestCase`]: https://api.rubyonrails.org/classes/ActionController/TestCase.html\n[in the appropriate folder]: https://rspec.info/features/7-1/rspec-rails/directory-structure\n\n### System specs, feature specs, request specs–what’s the difference?\n\nRSpec Rails provides some end-to-end (entire application) testing capability\nto specify the interaction with the client.\n\n#### System specs\n\nAlso called **acceptance tests**, **browser tests**, or **end-to-end tests**,\nsystem specs test the application from the perspective of a _human client._\nThe test code walks through a user’s browser interactions,\n\n* `visit '/login'`\n* `fill_in 'Name', with: 'jdoe'`\n\nand the expectations revolve around page content.\n\n* `expect(page).to have_text('Welcome')`\n\nBecause system specs are a wrapper around Rails’ built-in `SystemTestCase`,\nthey’re only available on Rails 5.1+.\n(Feature specs serve the same purpose, but without this dependency.)\n\n#### Feature specs\n\nBefore Rails introduced system testing facilities,\nfeature specs were the only spec type for end-to-end testing.\nWhile the RSpec team now [officially recommends system specs][] instead,\nfeature specs are still fully supported, look basically identical,\nand work on older versions of Rails.\n\nOn the other hand, feature specs require non-trivial configuration\nto get some important features working,\nlike JavaScript testing or making sure each test runs with a fresh DB state.\nWith system specs, this configuration is provided out-of-the-box.\n\nLike system specs, feature specs require the [Capybara][] gem.\nRails 5.1+ includes it by default as part of system tests,\nbut if you don’t have the luxury of upgrading,\nbe sure to add it to the `:test` group of your `Gemfile` first:\n\n```ruby\ngroup :test do\n  gem \"capybara\"\nend\n```\n\n[officially recommends system specs]: https://rspec.info/blog/2017/10/rspec-3-7-has-been-released/#rails-actiondispatchsystemtest-integration-system-specs\n[Capybara]: https://github.com/teamcapybara/capybara\n\n#### Request specs\n\nRequest specs are for testing the application\nfrom the perspective of a _machine client._\nThey begin with an HTTP request and end with the HTTP response,\nso they’re faster than feature specs,\nbut do not examine your app’s UI or JavaScript.\n\nRequest specs provide a high-level alternative to controller specs.\nIn fact, as of RSpec 3.5, both the Rails and RSpec teams\n[discourage directly testing controllers][]\nin favor of functional tests like request specs.\n\nWhen writing them, try to answer the question,\n“For a given HTTP request (verb + path + parameters),\nwhat HTTP response should the application return?”\n\n[discourage directly testing controllers]: https://rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5\n\n## Contributing\n\n- [Build details](BUILD_DETAIL.md)\n- [Code of Conduct](CODE_OF_CONDUCT.md)\n- [Detailed contributing guide](CONTRIBUTING.md)\n\nOnce you’ve cloned the repo and [set up the environment](DEVELOPMENT.md),\nyou can run the specs and Cucumber features, or submit a pull request.\n\n## See Also\n\n### RSpec base libraries\n\n* https://github.com/rspec/rspec\n\n### Recommended third-party extensions\n\n* [FactoryBot](https://github.com/thoughtbot/factory_bot)\n* [Capybara](https://github.com/teamcapybara/capybara)\n  (Included by default in Rails 5.1+.\n  Note that [additional configuration is required][] to use the Capybara DSL\n  anywhere other than system specs and feature specs.)\n\n  [additional configuration is required]: https://rubydoc.info/gems/rspec-rails/file/Capybara.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspec%2Frspec-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frspec%2Frspec-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspec%2Frspec-rails/lists"}