Chapter 07

2-4. Rspec 導入

Masuyama
Masuyama
2022.10.15に更新

Rspec 導入

今回は Rails でテストを書くための準備をしましょう。
そのために本カリキュラムではRSpecという、テストフレームワークの gem を使用します。

RSpec とは?

RSpec は、Ruby や Rails の代表的なテストフレームワークの一つです。

実は RSpec を使わなくても Minitest というライブラリを Ruby では標準で使えるのですが、
RSpec は Minitest と比べ便利な機能が豊富に備わっており、直感的にテストを読み書きできることから非常に人気なフレームワークです。

(RSpec の使い方や基本構文については後述の宿題にて))

RSpec インストール

RSpec も gem であるため、Gemfile に追記して bundle installコマンドでインストールできます。

Rails で使うための RSpec gem は

Gemfile のうち、development と test 環境用のグループに追記しましょう。

group :development, :test do
  ...
  gem 'rspec-rails' # 追加
end
Fetching rspec-rails 5.1.2
Installing rspec-rails 5.1.2
Bundle complete!

Gemfile への追記が完了したら、bundle installコマンドで gem をインストールします。

$ bundle install
...
Fetching rspec-rails 5.1.2
Installing rspec-rails 5.1.2
Bundle complete! ...

bundle install が正常に完了したら、RSpec を動かすために必要なファイル群を rails g で作成します。

$ bundle exec rails g rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

これで rspec コマンドから RSpec を即時実行できるようになります。
試しにコマンドを叩いてみましょう。

$ bundle exec rspec
No examples found.


Finished in 0.00056 seconds (files took 0.07792 seconds to load)
0 examples, 0 failures

現在はテストを作成してないので 0 件のテスト (0 examples) を実行した、という表示ではありますが、とにかく RSpec を使用する準備はできました。

次は便利に使うための初期設定を進めていきましょう。

初期設定

RSpec を使うにあたり、いくつか便利な初期設定や、追加で入れておくと開発しやすくなる gem を導入していきます。
順番にやっていきましょう。

不要なディレクトリ /test 削除

Rails プロジェクトを rails new で作成した際、デフォルトで作成される /testディレクトリは Minitest 用であるため、既に不要になりました。

もう使わないので、この時点で削除しておきましょう。

$ rm -r test/

FactoryBot インストール

FactoryBot とは、Rspec 標準で使える fixture に代わりにテストデータの生成を助けてくれるライブラリです。

FactoryBot を使えば、例えば以下のように 1 行で User モデルのテストデータを準備することができるため、テストを効率的に書くことができます。

user = FactoryBot.create(:user)

(詳しい使い方については後述の宿題にて)

FactoryBot を Rails で使うには、factory_bot_rails という gem をインストールしてあげます。

Gemfile のうち、development と test 環境用のグループに追記しましょう。

group :development, :test do
  ...
  gem 'factory_bot_rails' # 追加
end

Gemfile に追記できたら、いつも通り bundle install を実行します。

$ bundle install
Installing factory_bot_rails 6.2.0
Bundle complete! ...

これで FactoryBot のインストールができました。
これからモデルを作成する時に合わせて FactoryBot 用のファイルを生成していく時に説明しますが、rails g factory_bot:model モデル名というコマンドで FactoryBot 用のファイルを自動生成できます。

さて、追加でもう少し FactoryBot を便利に使う設定をしておきましょう。

RSpec のテストコードで FactoryBot のメソッドを使う際、そのモジュール名 (FactoryBot)を省略できるようにしておくと便利です。
省略するためには RSpec の基本設定をした時に自動生成された spec/rails_helper.rb ファイルに追記します。

spec/rails_helper.rb

RSpec.configure do |config|
  ...
  config.include FactoryBot::Syntax::Methods # 最下段に追記
end

この記述により、FactoryBot というクラス名をつけなくても FactoryBot のメソッドを spec ファイル内で呼び出せるようになります。

例)

user = create(:user)

rails generator 生成ファイル

rails g (rails generater)コマンドでコントローラやモデルを作成する際、
RSpec テスト用のファイルも自動で作成されるのですが、いくつかのファイルについては本カリキュラムにおいては不要なものです。

そのため、Rails の初期設定をした時と同じく config/application.rbに追記します。
前回追記した config.generators do |g|ブロックの中に追記してください。

config/application.rb

    config.generators do |g|
      g.assets false
      g.helper     false
      g.test_framework :rspec, # ここから5行を追記
        fixtures: false, # テストDBにレコードを作るfixtureの作成をスキップ(FactoryBotを使用するため)
        view_specs: false, # ビューファイル用のスペックを作成しない
        helper_specs: false, # ヘルパーファイル用のスペックを作成しない
        routing_specs: false # routes.rb用のスペックファイル作成しない
    end

各行の意味については、コメントで説明をつけてあります。

1 点、ビュー (view) ファイルについて補足しますと、view で表示する内容については他の (画面内を操作するような) システムテストで検査をするため、ユニットテスト(view 単体のテスト)を書かないことが一般的です。
そのため、本カリキュラムにおいても view のテストは自動で作成されないように設定しました。

テスト結果の出力調整

デフォルトの形式 → ドキュメント形式へ変更
必須ではないですが、RSpec の出力結果を見やすくします。

Rails プロジェクト(./workspace/techlog-app)の直下にある .rspec ファイルの最下段に、以下の 1 行を追加します。

.rspec

--format documentation # 出力結果をドキュメント風に見やすくする

まだテストを実際に書いて、出力結果を見ていないため恩恵は受けていませんが、今後出力されるテスト結果が少し見やすくなります。

テスト起動の高速化

ソースコードを修正した後、テストの実行は少しでも早い方がいいですよね。
そんな時、Spring という仕組みを使うと少しですがテストの実行を早くできます。

これも gem を使って導入できるので、サクッとやっておきましょう。

Gemfile の development グループに gem 'spring-commands-rspec'を追記して

Gemfile

group :development do
  ...
  gem 'spring-commands-rspec' # 追記
end

Gemfile に書けたら、いつも通り bundle install を実行します。

$ bundle install
Installing spring 4.0.0
Fetching spring-commands-rspec 1.0.4
Installing spring-commands-rspec 1.0.4
Bundle complete!

その後、高速起動用のファイルである bin/rspecを作成するのですが、コマンド一発で作成することができます。

$ bundle exec spring binstub rspec
* bin/rspec: generated with Spring

実行すると、bin/ ディレクトリ内に rspec という実行用ファイルが作成されているはずです。

$ ls bin/
bundle          importmap       rake            setup
dev             rails           rspec           spring

最後に、テスト環境では Spring がキャッシュをしないよう、アプリケーション側で reload を有効にしてあげます。
config/environments/test.rbファイルを開き、config.cache_classesと書かれた 1 行を編集します。

config/environments/test.rb

config.cache_classes = false # trueからfalseに変更

これで Spring を使って RSpec を高速で起動する準備ができました。
実際に使ってみましょう。

Spring の恩恵を受けるためには bundle exec rspecではなく bin/rspecコマンドでテストを実行してあげます。

$ bin/rspec
DEBUGGER: Attaching after process 37366 fork to child process 37415
Running via Spring preloader in process 37415
No examples found.

Finished in 0.00047 seconds (files took 0.10171 seconds to load)
0 examples, 0 failures

まだテストが 0 件であるため bundle exec rspec コマンドで普通に実行した時との違いはほとんど分かりませんが、テストが増えてきたら比べてみるといいでしょう。

ここまでで一旦、初期設定をできたのでコミットしておきます。

$ git add .
$ git commit -m "RSpecの初期設定を完了"

Rubocopチェック

色々と設定ファイルの自動生成や追記を行ったので、 Rubocop でのチェックを行なっておきましょう。

$ bundle exec rubocop
Inspecting 12 files
C.........CC

Offenses:

Gemfile:58:3: C: [Correctable] Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem factory_bot_rails should appear before rspec-rails.
  gem 'factory_bot_rails' # 追加
  ^^^^^^^^^^^^^^^^^^^^^^^
spec/rails_helper.rb:6:7: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
abort("The Rails environment is running in production mode!") if Rails.env.production?
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
spec/spec_helper.rb:49:1: C: [Correctable] Style/BlockComments: Do not use block comments.
=begin ...
^^^^^^

3 つの指摘が出ました。
今回は丁寧に一つずつ見ておきます。

    1. Bundler/OrderedGems: Gems should be sorted in an alphabetical order...
    • Gemfile に gem 名を書く時はアルファベット順に書こうね、という指摘です。
    • 直さなくても特に支障はないものの、現時点での順番に意味があるわけではないので直しておきましょう。
    • Correctableと書いてあるので、-aオプションを付ければ自動修正可能な指摘です。
    1. Style/StringLiterals: Prefer single-quoted strings...
    • RSpec 設定ファイル作成時、自動で生成されたファイルで ""を使った文字囲いがありました。
    • これもただ '' に直すだけなので、自動修正で OK です。
    1. Style/BlockComments: Do not use block comments.
    • これも自動生成されたファイルに関する指摘です。
    • =begin という書き方がコメントアウトをしていますが、パッと見でコメントであると分かりにくいため指摘が入っています。
    • コメントなので、直しても動作への影響はないため自動修正してしまいましょう。

以上 3 点、すべて自動修正で問題ないことを確認できたので -a オプションをつけて自動修正します。

$ bundle exec rubocop -a
Inspecting 12 files
C.........CC

Offenses:

Gemfile:58:3: C: [Corrected] Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem factory_bot_rails should appear before rspec-rails.
  gem 'factory_bot_rails' # 追加
  ^^^^^^^^^^^^^^^^^^^^^^^
spec/rails_helper.rb:6:7: C: [Corrected] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
abort("The Rails environment is running in production mode!") if Rails.env.production?
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
spec/spec_helper.rb:49:1: C: [Corrected] Style/BlockComments: Do not use block comments.
=begin ...
^^^^^^
spec/spec_helper.rb:91:1: C: [Corrected] Layout/CommentIndentation: Incorrect indentation detected (column 0 instead of 2).
#   Kernel.srand config.seed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

12 files inspected, 4 offenses detected, 4 offenses corrected

3 点については既に見ていましたが、4 つ目の指摘事項として「コメントのインデント」に対する指摘が追加され、そのまま自動修正されています。

Layout/CommentIndentation: Incorrect indentation detected (column 0 instead of 2)

※詳しい説明はドキュメントをご参照ください。

これは、指摘事項の修正を行なったことで追加の指摘事項が浮上したためです。
このように、自動修正は予期せぬところまで修正をされてしまう可能性があるため、事前にコミットをしておくことをおすすめします。
(現場の方針によっては、Rubocop での検査を終えてからコミットすべしという場合もあります。チームルールを確認してください。)

変更をコミット

さて、Rubocop でのチェックと修正を終えたため、変更内容をコミットしておきます。

$ git add .
$ git commit -m "Rubocop による指摘事項修正(Lint)"
$ git push

宿題

今回は盛りだくさんの内容でした。
本カリキュラムだけでなく、実際の現場では当たり前のようにテストを書くので、宿題記事をしっかりと読んでテストの書き方を今のうちに覚えておきましょう!

RSpec の基本構文や便利機能

RSpec でのテストの書き方自体は使い回しをしやすいため、一度書いてしまえば色々な画面で流用できるのですが
便利な機能が豊富な分、構文やルールが多いために初心者は取っ付きにくいものではあります。
(RSpec の書き方だけで本が一冊出るほどです。)

本カリキュラムだけでは RSpec の構文のうち主要なものしか使わないですが、
どういった構文や機能があるのかを知っておくことはテストを書く上で重要ですので、
本カリキュラムでテストを書く前に、以下 記事を予め読んでおくことを強くおすすめします。

実際に現場で開発する際にも、よくこちらを参照するぐらい有用な記事です。

ボリュームが多く、初心者の方はくじけそうになるかもしれませんが、現場で開発するには必須級のスキルですのでこのタイミングで頑張りましょう!

FactoryBot の使い方

FactoryBot を用いたテストデータの用意本カリキュラムでも度々使うため、基本的な使い方は事前に知っておくとスムーズに導入できます。
User モデルを例にした使い方がまとめられているので、軽くでも読んでおきましょう。