メインコンテンツまでスキップ

RSpec Rails

rspec-railsは、デフォルトのテストフレームワークであるMinitestの代わりに、 Ruby on RailsRSpecテストフレームワークを導入します。

RSpecでは、テストは単にアプリケーションコードを検証するスクリプトではありません。 それらは仕様(または_specs_とも呼ばれる)でもあります。 アプリケーションの振る舞いを詳細に説明したもので、 平易な英語で表現されます。

RSpec Railsの新しいバージョニング戦略に従って、次のように使用します:

インストール

重要 このREADME / ブランチは、6.1.xの安定リリースシリーズに対応しています。 このシリーズからのバグ修正のみがここに追加されます。 最新の不安定な機能を利用する場合は、Githubのmainブランチを参照してください。

  1. アプリケーションのGemfiledevelopmentグループとtestグループの両方rspec-railsを追加します:

    # Run against this stable release
    group :development, :test do
    gem 'rspec-rails', '~> 6.1.0'
    end

    # Or, run against the main branch
    # (requires main-branch versions of all related RSpec libraries)
    group :development, :test do
    %w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
    gem lib, git: "https://github.com/rspec/#{lib}.git", branch: 'main'
    end
    end

    developmentグループに追加する必要は厳密にはありませんが、 追加しない場合、ジェネレータやrakeタスクはRAILS_ENV=testで先行する必要があります。)

  2. プロジェクトディレクトリ内で次の手順を実行します。

    # 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

アップグレード

既にプロジェクトで古いバージョンの rspec-rails を使用している場合は、次のコマンドで最新バージョンにアップグレードします。

$ bundle update rspec-rails

RSpecはセマンティックバージョニングに従っています。つまり、「メジャーバージョン」のアップグレード(例:2.x → 3.x)には互換性のない変更が含まれます。バージョン2.x以下からアップグレードする場合は、rspec-rails のアップグレードノートを確認して注意点を把握してください。

一般的なRSpecのアップグレードノートも確認してください。

使用方法

rails generate を使用してボイラープレートのスペックを作成する

# 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)
$ bundle exec rspec

# Run all spec files in a single directory (recursively)
$ bundle exec rspec spec/models

# Run a single spec file
$ bundle exec rspec spec/controllers/accounts_controller_spec.rb

# Run a single example from a spec file (by line number)
$ bundle exec rspec spec/controllers/accounts_controller_spec.rb:8

# See all options for running specs
$ bundle exec rspec --help

オプション: bundle exec rspec の出力が多すぎる場合は、bin/rspecにバイナリスタブを生成して代わりに使用することもできます。

$ bundle binstubs rspec-core

RSpec DSLの基本(スペックの書き方)

RSpecでは、アプリケーションの振る舞いをほぼプレーンな英語で記述し、その後にテストコードで再度記述します。例えば、次のようになります。

RSpec.describe 'Post' do           #
context 'before publication' do # (almost) plain English
it 'cannot have comments' do #
expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid) # test code
end
end
end

rspecを実行すると、このテストコードが実行され、プレーンな英語の記述を使用してアプリケーションがスペックに準拠しているかどうかのレポートが生成されます。

$ rspec --format documentation spec/models/post_spec.rb

Post
before publication
cannot have comments

Failures:

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 failure

Failed examples:

rspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments

詳細なRSpec DSLの説明や多くの例については、公式のCucumberドキュメントであるRSpec Coreを参照してください。

便利なRails Matcher

RSpecでは、アサーションは_expectations_と呼ばれ、すべてのexpectationは_matcher_を中心に構築されます。expect(a).to eq(b)のようにeqマッチャーを使用しています。

[RSpecで標準で提供されているマッチャー][]に加えて、Railsシステムのさまざまな部分をテストするのに便利ないくつかの追加のマッチャーがあります。

RSpecマッチャーデリゲート先利用可能な場所ノート
be_a_newすべて主にコントローラースペックで使用される
render_templateassert_templateリクエスト / コントローラー / ビューexpect(response).toと組み合わせて使用します
redirect_toassert_redirectリクエスト / コントローラーexpect(response).toと組み合わせて使用します
route_toassert_recognizesルーティング / コントローラーexpect(...).to route_toと組み合わせて使用します
be_routableルーティング / コントローラーexpect(...).not_to be_routableと組み合わせて使用します
have_http_statusリクエスト / コントローラー / フィーチャー
match_arrayすべてActiveRecordオブジェクトの配列を比較するためのもの
have_been_enqueuedすべて設定が必要です: ActiveJob::Base.queue_adapter = :test
have_enqueued_jobすべて設定が必要です: ActiveJob::Base.queue_adapter = :test

上記のリンクを参照して、各マッチャの使用例を確認してください。

RSpec Rails は他に何を追加しますか?

RSpec Rails の機能について詳しくは、公式のCucumberドキュメントを参照してください。

どのようなテストを書くべきですか?

RSpec Rails では、典型的なRailsアプリケーションのさまざまな部分をテストするために、10種類の異なるスペックタイプが定義されています。 それぞれはRailsの組み込みのTestCaseクラスのいずれかを継承しており、Railsのデフォルトのテストで提供されるヘルパーメソッドはRSpecでも利用できます。

スペックタイプ対応するRailsテストクラス
model
controllerActionController::TestCase
mailerActionMailer::TestCase
job
viewActionView::TestCase
routing
helperActionView::TestCase
requestActionDispatch::IntegrationTest
feature
systemActionDispatch::SystemTestCase

上記のリンクを参照して、各仕様タイプの例を確認するか、指定された TestCase クラスの公式Rails APIドキュメントを参照してください。

注意: これはチェックリストではありません。

アプリケーションのテスト方法について100人の開発者に尋ねると、100通りの異なる回答が得られます。

RSpec Railsは、良いテストの実践を促進するために慎重に選ばれた機能を提供していますが、それには「正しい」方法はありません。 最終的には、テストスイートの構成方法はあなた次第です。

仕様ファイルを作成する場合は、次のようにトップレベルの describe ブロックにタイプを割り当てます。

# spec/models/user_spec.rb

RSpec.describe User, type: :model do
...

システム仕様、フィーチャ仕様、リクエスト仕様 - 違いは何ですか?

RSpec Railsは、いくつかのエンドツーエンド(アプリケーション全体)のテスト機能を提供し、クライアントとのやり取りを指定します。

システム仕様

または 受け入れテストブラウザテスト、または エンドツーエンドテスト とも呼ばれるシステム仕様は、人間のクライアント の視点からアプリケーションをテストします。 テストコードは、ユーザーのブラウザの操作をたどります。

  • visit '/login'
  • fill_in 'Name', with: 'jdoe'

そして期待値はページの内容に関連しています。

  • expect(page).to have_text('Welcome')

システムスペックはRailsの組み込みのSystemTestCaseをラップしたものであり、Rails 5.1以降でのみ利用可能です。 (同じ目的を持つフィーチャースペックもありますが、この依存関係はありません。)

フィーチャースペック

Railsがシステムテストの機能を導入する前は、エンドツーエンドテストのための唯一のスペックタイプでした。 RSpecチームは現在公式にはシステムスペックを推奨していますが、フィーチャースペックはまだ完全にサポートされており、基本的に同じように見え、古いバージョンのRailsでも動作します。

一方、フィーチャースペックには重要な機能を動作させるために非自明な設定が必要です。 例えば、JavaScriptのテストや各テストが新しいDBの状態で実行されることを確認するためです。 システムスペックでは、この設定はすぐに提供されます。

システムスペックと同様に、フィーチャースペックにはCapybara gemが必要です。 Rails 5.1+では、システムテストの一部としてデフォルトで含まれていますが、アップグレードする余裕がない場合は、まずGemfile:testグループに追加してください。

group :test do
gem "capybara"
end

リクエストスペック

リクエストスペックは、アプリケーションを_マシンクライアント_の視点からテストするためのものです。 HTTPリクエストで始まり、HTTPレスポンスで終わるため、フィーチャースペックよりも高速ですが、アプリのUIやJavaScriptを検証しません。

リクエストスペックは、コントローラースペックの高レベルな代替手段を提供します。 実際、RSpec 3.5以降、RailsチームとRSpecチームの両方がコントローラーの直接テストを非推奨し、リクエストスペックのような機能テストを推奨しています。

書く際には、次の質問に答えるようにしてください。 「与えられたHTTPリクエスト(動詞+パス+パラメータ)に対して、アプリケーションはどのようなHTTPレスポンスを返すべきですか?」

関連情報

RSpecの基本ライブラリ

推奨されるサードパーティの拡張機能