はじめに
rails_helperの設定をこんな風にしていますという記事はあるのですが、そのオプションによって何をしているのか今一つわからなかったので、自分用に和訳&補足してみました。
忘れた頃の自分やRSpec初心者のためになればと思います。正確性に関しては自信ないです!
RSpecのバージョンは3.9
です。
(2/9追記)編集リクエストを元に修正しました。
導入
$ rails g rspec:install
コマンドを打つと、.rspec
, spec/rails_helper.rb
, spec/spec_helper.rb
ファイルが生成されます。
rails_helper.rb
はデフォルトではこのようになっています。
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
#
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
# RSpec.describe UsersController, :type => :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
end
このコメントアウトされた部分が今回のポイントです。
thisが何を示しているのかだとか、ちょっとした用語を噛み砕けるといいなと思います。
自分なりに和訳&補足してみた
rails generate rspec:install
を実行すると、このファイルはspec/
ディレクトリにコピーされます。
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
本番環境のときにデータベースのTRUNCATE1を防ぎます。
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
追加でrequire
する場合はこの下に追加してください。この時点までRailsは読み込まれていません!
spec/support/
配下のファイルを読み込む設定
カスタムマッチャやマクロ2などを記述したrubyファイルを読み込みたい場合、spec/support/
配下に置いてください。
spec/
配下にある_spec.rb
で終わるファイルはbundle exec rspec
コマンドを実行すると自動的に走ります。つまり、これをspec/support/
内に置くと、読み込み時とテスト時の二回実行されることになります。
そのため、spec/support/
に_spec.rb
で終わるファイルを置くのはやめましょう。
この様式3はコマンドを打つときに--pattern
を使うか、~/.rspec
, .rspec
, .rspec-local
で設定できます。
以下の行は手間を省くために用意されています。この行を有効にするとspec/support/
以下の全てのファイルが自動的に読み込まれるため、起動に時間がかかるという難点もあります。
代わりの方法として、それぞれの_spec.rb
ファイルでrequire
を使って必要なファイルだけを読み込む方法もあります。
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
マイグレーションの設定
保留にされている4マイグレーションを確認し、テストを走らせる前にマイグレーションを適用します。
ActiveRecordを使わない場合、以下の行(begin
からend
まで)を削除できます。
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
(補足)
自動的にマイグレーションを行い、schemaとマイグレーションファイルに相違がある場合、例外を発生させます。
ActiveRecordのfixtureを使用する設定
もしActiveRecordやActiveRecordのfixtureを使用しない場合はこの行は必要ありません。
config.fixture_path = "#{::Rails.root}/spec/fixtures"
(補足)例えばFactoryBotしか使わないというような場合が当てはまりますが、他の人の設定を見たところ、わざわざ削除している人は少ないようです。
exampleごとにトランザクションを行う設定
ActiveRecordを使わない、またはトランザクション内で複数のexampleを走らせたい場合は、この行を削除するかオプションをtrue
からfalse
にしてください。
config.use_transactional_fixtures = true
(補足)
デフォルトのtrue
の場合、exampleごとにトランザクションが行われる設定になっています。つまり、exampleが始まるときにはきれいなデータベースが用意され、終わると全てのデータを削除します。
Database Cleanerなどを使って手動で削除する場合や、特定のSpecでだけトランザクションのロールバックを無効にする場合はfalse
にします。
exampleについては以下の説明を参考にしてください。
it
はテストをexample
という単位にまとめる役割をします。
it do ... end
の中のエクスペクテーション(期待値と実際の値の比較)がすべてパスすれば、そのexample
はパスしたことになります。
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
ファイルの場所に応じた機能を使用する設定
RSpec Railsでは、ファイルの場所に応じた動作を使用することができます。
例えば、spec/controllers
配下のファイルでは、get
やpost
を使うことができる仕様となっています。
以下の行を削除するとこの仕様が無効になります。
代わりに、
RSpec.describe UsersController, type: :controller do
# ...
end
のtype: :controller
のように、明示的にタイプを記述することができます。
利用可能なタイプは、以下のサイトに記述しています。
https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
バックトレースをフィルタリングする設定
Railsで読み込まれたgemによるバックトレースをフィルタリングします。
config.filter_rails_from_backtrace!
特定のgemをフィルタリングする場合、次の設定をしてください。
config.filter_gems_from_backtrace("gem name")
(補足)
テスト失敗時のノイズを減らすための設定です。
テスト実行時に--backtrace
を付けると、フィルタリングされていないバックトレースが表示されます。
(和訳はここまで)
ちなみに
FactoryBotやモジュールを使う場合は、以下のように読み込んでください。
RSpec.configure do |config|
...
# config.filter_gems_from_backtrace("gem name")
# この下に記述している人が多い印象です
config.include FactoryBot::Syntax::Methods
config.include LoginHelpers
end
おわりに
自分で翻訳したり調べたりすると、なんとなくRSpecの仕様への理解が深まった気がします。
また、公式ドキュメントはGoogle翻訳でも読みやすかったです。
間違っていた場合はご指摘をお願いします。
-
テーブルに格納されているデータを全削除すること ↩
-
ヘルパーメソッド ↩
-
テスト実行時にどのファイルを実行するか pattern - Configuration - RSpec Core ↩
-
db:migrate
されていない状態 ↩