【RSpec】spec/rails_helper.rbを和訳&補足してみた

## はじめに

rails_helperの設定をこんな風にしていますという記事はあるのですが、そのオプションによって何をしているのか今一つわからなかったので、自分用に和訳&補足してみました。
忘れた頃の自分やRSpec初心者のためになればと思います。正確性に関しては自信ないです！

RSpecのバージョンは`3.9`です。

（2/9追記）編集リクエストを元に修正しました。

### 導入

```terminal
$ rails g rspec:install
```

コマンドを打つと、`.rspec`, `spec/rails_helper.rb`, `spec/spec_helper.rb`ファイルが生成されます。
`rails_helper.rb`はデフォルトではこのようになっています。

```rb:spec/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/`ディレクトリにコピーされます。

```rb
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
```

本番環境のときにデータベースのTRUNCATE[^1]を防ぎます。

[^1]: テーブルに格納されているデータを全削除すること

```rb
abort("The Rails environment is running in production mode!") if Rails.env.production?
```
```
require 'rspec/rails'
```

追加で`require`する場合はこの下に追加してください。この時点までRailsは読み込まれていません！

### `spec/support/`配下のファイルを読み込む設定

カスタムマッチャやマクロ[^2]などを記述したrubyファイルを読み込みたい場合、`spec/support/`配下に置いてください。

[^2]: ヘルパーメソッド

`spec/`配下にある`_spec.rb`で終わるファイルは`bundle exec rspec`コマンドを実行すると自動的に走ります。つまり、これを`spec/support/`内に置くと、読み込み時とテスト時の二回実行されることになります。
そのため、`spec/support/`に`_spec.rb`で終わるファイルを置くのはやめましょう。

この様式[^3]はコマンドを打つときに`--pattern`を使うか、`~/.rspec`, `.rspec`, `.rspec-local`で設定できます。

[^3]: テスト実行時にどのファイルを実行するか [pattern - Configuration - RSpec Core](https://relishapp.com/rspec/rspec-core/v/3-8/docs/configuration/pattern)

以下の行は手間を省くために用意されています。この行を有効にすると`spec/support/`以下の全てのファイルが自動的に読み込まれるため、起動に時間がかかるという難点もあります。
代わりの方法として、それぞれの`_spec.rb`ファイルで`require`を使って必要なファイルだけを読み込む方法もあります。

```rb
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
```

### マイグレーションの設定

保留にされている[^4]マイグレーションを確認し、テストを走らせる前にマイグレーションを適用します。

[^4]: `db:migrate`されていない状態

ActiveRecordを使わない場合、以下の行（`begin`から`end`まで）を削除できます。

```rb
begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
```

（補足）
自動的にマイグレーションを行い、schemaとマイグレーションファイルに相違がある場合、例外を発生させます。

- [Upgrade - RSpec Rails](https://relishapp.com/rspec/rspec-rails/v/3-9/docs/upgrade)

### ActiveRecordのfixtureを使用する設定

もしActiveRecordやActiveRecordのfixtureを使用しない場合はこの行は必要ありません。

```rb
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
```

（補足）例えばFactoryBotしか使わないというような場合が当てはまりますが、他の人の設定を見たところ、わざわざ削除している人は少ないようです。

### exampleごとにトランザクションを行う設定

ActiveRecordを使わない、またはトランザクション内で複数のexampleを走らせたい場合は、この行を削除するかオプションを`true`から`false`にしてください。

```rb
  config.use_transactional_fixtures = true
```

（補足）
デフォルトの`true`の場合、exampleごとにトランザクションが行われる設定になっています。つまり、exampleが始まるときにはきれいなデータベースが用意され、終わると全てのデータを削除します。
[Database Cleaner](https://github.com/DatabaseCleaner/database_cleaner)などを使って手動で削除する場合や、[特定のSpecでだけトランザクションのロールバックを無効にする](https://qiita.com/takeyuweb/items/e7261e9274b3b31d933c)場合は`false`にします。

- [Transactions - RSpec Rails](https://relishapp.com/rspec/rspec-rails/docs/transactions)
- [RSpec with Railsでテスト時のデータはどのように削除されているか](https://sandragon.hatenablog.com/entry/2019/02/11/111415)

exampleについては以下の説明を参考にしてください。

> `it`はテストを`example`という単位にまとめる役割をします。
`it do ... end`の中のエクスペクテーション（期待値と実際の値の比較）がすべてパスすれば、その`example`はパスしたことになります。
[使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」](https://qiita.com/jnchito/items/42193d066bd61c740612)

### ファイルの場所に応じた機能を使用する設定

RSpec Railsでは、ファイルの場所に応じた動作を使用することができます。
例えば、`spec/controllers`配下のファイルでは、`get`や`post`を使うことができる仕様となっています。

以下の行を削除するとこの仕様が無効になります。
代わりに、

```ruby
  RSpec.describe UsersController, type: :controller do
    # ...
  end
```

の`type: :controller`のように、明示的にタイプを記述することができます。

利用可能なタイプは、以下のサイトに記述しています。
https://relishapp.com/rspec/rspec-rails/docs

```rb
  config.infer_spec_type_from_file_location!
```

### バックトレースをフィルタリングする設定

Railsで読み込まれたgemによる[バックトレース](https://magazine.rubyist.net/articles/0031/0031-BackTrace.html)をフィルタリングします。

```rb
  config.filter_rails_from_backtrace!
```

特定のgemをフィルタリングする場合、次の設定をしてください。

```rb
  config.filter_gems_from_backtrace("gem name")
```

（補足）
テスト失敗時のノイズを減らすための設定です。
テスト実行時に`--backtrace`を付けると、フィルタリングされていないバックトレースが表示されます。

- [backtrace filtering - RSpec Rails](https://relishapp.com/rspec/rspec-rails/v/3-8/docs/backtrace-filtering)

（和訳はここまで）

## ちなみに

FactoryBotやモジュールを使う場合は、以下のように読み込んでください。

```rb
RSpec.configure do |config|
  ...
  # config.filter_gems_from_backtrace("gem name")
  # この下に記述している人が多い印象です

  config.include FactoryBot::Syntax::Methods
  config.include LoginHelpers
end
```

# おわりに

自分で翻訳したり調べたりすると、なんとなくRSpecの仕様への理解が深まった気がします。
また、公式ドキュメントはGoogle翻訳でも読みやすかったです。
間違っていた場合はご指摘をお願いします。