2. RSpecのセットアップ
第1章で述べたように、プロジェクト管理アプリケーションは 動いています 。少なくとも 動いている とは言えるのですが、その根拠は何かと言われたら、リンクをクリックし、ダミーのアカウントとプロジェクトをいくつか作り、ブラウザを使ってデータを追加したり編集したりできた、ということだけです。もちろん、機能を追加するたびに毎回こんなやり方を繰り返しているといつか破綻します。このアプリケーションへ新しい機能を追加する前に、私たちはいったん手を止め、RSpecを使って 自動化されたテストスイート を追加する必要があります。私たちはここから先のいくつかの章にわたってこのアプリケーションにどんどんテストを追加していきます。最初はRSpecだけで始め、それからその他のテスト用のライブラリを必要に応じてテストスイートに追加していきます。
最初に、RSpecをインストールし、RSpecを使ってテストできるようにアプリケーションを設定しなければなりません。ちょっと前まではRSpecとRailsを組み合わせて使うためにそこそこの労力が必要でしたが、今はもう違います。とはいえ、それでもスペックを書く前にいくつかのgemをインストールし、ちょっとした設定を行う必要はあります。
この章では次のようなタスクを完了させます。
- まずBundlerを使って、RSpecをインストールするところから始めます。
- 必要に応じてテスト用データベースの確認とインストールを行います。
- 次にテストしたい項目をテストできるようにRSpecを設定します。
- 最後に、新しい機能を追加するときにテスト用のファイルを自動生成できるよう、Railsアプリケーションを設定します。
Gemfile
RSpecはRailsアプリケーションにデフォルトでは含まれていないため、まずインストールする必要があります。RSpecをインストールするためにはBundlerを使います。 Gemfile を開き、RSpecをそこに追加しましょう。
group :development, :test do
# Railsで元から追加されているgemは省略
gem 'rspec-rails'
end
少し詳しい話をすると、ここでは rspec-rails ライブラリをインストールしようとしています。 rspec-rails には rspec-core とその他の独立したgemが含まれます。もしあなたがSinatraアプリケーションやその他の非RailsアプリケーションをテストするためにRSpecを使いたい場合は、そうしたgemを個別にインストールしなければなりません。rspec-railsは必要なgemをひとつにパッケージングし、インストールを楽にしてくれます。また、それに加えて、このあとで説明するRails向けの便利機能も提供してくれます。
コマンドラインから bundle コマンドを実行して、rspec-railsと関連するgemをシステムにインストールしてください。これで私たちのアプリケーションは、堅牢なテストスイートを構築するために必要な最初のブロックを手に入れました。続いて、テスト用のデータベースを作成しましょう。
テストデータベース
もし既存のRailsアプリケーションにスペックを追加するのであれば、もうすでにテストデータベースを作ってあるかもしれません。作っていないのなら、追加する方法を今から説明します。
config/database.yml というファイルを開き、あなたのアプリケーションがどのデータベースにアクセスできるか確認してください。もしこのファイルを全く変更していなければ、次のようになっているはずです。たとえばSQLiteであればこうなっています。
1 test:
2 <<: *default
3 database: db/test.sqlite3
MySQLやPostgreSQLを使っている場合はこうなります。
1 test:
2 <<: *default
3 database: projects_test
こうしたコードが見つからなければ、必要なコードを config/database.yml に追加しましょう。 projects_test の部分は自分のアプリケーションにあわせて適切に置き換えてください。
最後に、次のrakeタスクを実行して接続可能なデータベースを作成しましょう。
$ bin/rails db:create:all
もしテストデータベースをまだ作っていないなら、今実行してみてください。すでに作成済みなら、 rails タスクはテストデータベースがすでにあることをちゃんと教えてくれるはずです。既存のデータベースを間違って消してしまう心配はいりません。ではRSpec自体の設定に進みましょう。
RSpecの設定
これでアプリケーションにspecフォルダを追加し、RSpecの基本的な設定ができるようになりました。次のようなコマンドを使ってRSpecをインストールしましょう。
$ bin/rails generate rspec:install
するとジェネレータはこんな情報を表示します。
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
ここで作成されたのは、RSpec用の設定ファイル( .rspec )と、私たちが作成したスペックファイルを格納するディレクトリ( spec )、それと、のちほどRSpecの動きをカスタマイズするヘルパーファイル( spec/spec_helper.rb と spec/rails_helper.rb )です。最後の2つのファイルにはカスタマイズできる内容がコメントで詳しく書かれています。今はまだ全部読む必要はありませんが、あなたにとってRSpecがRails開発に欠かせないものになってきた頃に、設定をいろいろ変えながらコメントを読んでみることを強くお勧めします。設定の役割を理解するためにはそうするのが一番です。
次に、必須ではありませんが、私はRSpecの出力をデフォルトの形式から読みやすいドキュメント形式に変更するのが好みです。これによってテストスイートの実行中にどのスペックがパスし、どのスペックが失敗したのかがわかりやすくなります。それだけでなく、スペックのアウトラインが美しく出力されます。予想していたかもしれませんが、この出力を仕様書のように使うこともできます。先ほど作成された .rspec ファイルを開き、以下のように変更してください。
--require spec_helper
--format documentation
このほかにも --warnings フラグをこのファイルに追加することもできます。 warnings が有効になっていると、RSpecはあなたのアプリケーションや使用中のgemから出力された警告をすべて表示します。確かに、警告の表示は実際のアプリケーションを開発するときは便利です。テストの実行中に出力された非推奨メソッドの警告にはいつでも注意を払うべきでしょう。しかし、学習目的なのであれば、警告は非表示にしてテストの実行結果からノイズを減らすことをお勧めします。この設定はあとからいつでも戻せます。
試してみよう!
私たちはまだ一つもテストを書いていませんが、RSpecが正しくインストールできているかどうかは確認できます。以下のコマンドを使ってRSpecを起動してみましょう。
$ bundle exec rspec
ちゃんとインストールされていれば、次のように出力されるはずです。
No examples found.
Finished in 0.00074 seconds (files took 0.14443 seconds to load)
0 examples, 0 failures
出力結果が異なる場合は、もう一度読み直してちゃんと手順どおりに作業したかどうかを確認してください。 Gemfile にgemを追加し、 それから bundle コマンドを実行することをお忘れなく。
rspec binstubを使って短いコマンドで実行できるようにする
RailsアプリケーションはBundlerの使用が必須であるため、RSpecを実行する際は bundle exec rspec のように毎回 bundle exec を付ける必要があります。binstubを作成すると bin/rspec のように少しタイプ量を減らすことができます。binstubを作成する場合は以下のコマンドを実行します。
$ bundle binstubs rspec-core
こうするとアプリケーションの bin ディレクトリ内に rspec という名前の実行用ファイルが作成されます。ただし、binstubを使うかどうかは読者のみなさんにお任せします。このほかにも bundle exec に独自のエイリアスを設定してコマンドを短くする方法もあります(例 be rspec など)。ですが、本書では標準的な bundle exec rspec を使うことにします。
ちなみに、Rails 6.1まではアプリケーションの起動時間を短くするSpringを使うためにbinstubを作成することがありましたが、Rails 7.0からはSpringはデフォルトではインストールされなくなりました。
ジェネレータ
さらに、もうひとつ手順があります。 rails generate コマンドを使ってアプリケーションにコードを追加する際に、RSpec用のスペックファイルも一緒に作ってもらうようRailsを設定しましょう。
RSpecはもうインストール済みなので、Railsのジェネレータを使っても、もともとデフォルトだったMinitestのファイルは test ディレクトリに作成されなくなっています。その代わり、RSpecのファイルが spec ディレクトリに作成されます。しかし、好みに応じてジェネレータの設定を変更することができます。たとえば、 scaffold ジェネレータを使ってコードを追加するときに気になるのは、本書であまり詳しく説明しない不要なスペックがたくさん作られてしまう点かもしれません。そこで最初からそうしたファイルを作成しないようにしてみましょう。
config/application.rb を開き、次のコードをApplicationクラスの内部に追加してください。
1 require_relative "boot"
2
3 require "rails/all"
4
5 # Railsが最初から書いているコメントは省略 ...
6 Bundler.require(*Rails.groups)
7
8 module Projects
9 class Application < Rails::Application
10 config.load_defaults 7.1
11 config.autoload_lib(ignore: %w(assets tasks))
12
13 config.generators do |g|
14 g.test_framework :rspec,
15 fixtures: false,
16 view_specs: false,
17 helper_specs: false,
18 routing_specs: false
19 end
20 end
21 end
このコードが何をしているかわかりますか?今から説明していきます。
-
fixtures: falseはテストデータベースにレコードを作成するファイルの作成をスキップします。この設定は第4章でtrueに変更します。第4章以降ではファクトリを使ってテストデータを作成します。 -
view_specs: falseはビュースペックを作成しないことを指定します。本書ではビュースペックを説明しません。代わりに システムスペック でUIをテストします。 -
helper_specs: falseはヘルパーファイル用のスペックを作成しないことを指定します。ヘルパーファイルはRailsがコントローラごとに作成するファイルです。RSpecを自在に操れるようになってきたら、このオプションをtrueにしてヘルパーファイルをテストするようにしても良いでしょう。 -
routing_specs: falseはconfig/routes.rb用のスペックファイルの作成を省略します。あなたのアプリケーションが本書で説明するものと同じぐらいシンプルなら、このスペックを作らなくても問題ないと思います。しかし、アプリケーションが大きくなってルーティングが複雑になってきたら、ルーティングスペックを導入するのは良い考えです。
モデルスペックとリクエストスペックの定型コードはデフォルトで自動的に作成されます。もし自動的に作成されたくなければ、同じように設定ブロックに記述してください。たとえば、リクエストスペックの生成をスキップしたいのであれば、 request_specs: false を追加します。
ただし、次の内容を忘れないでください。RSpecはいくつかのファイルを自動生成しないというだけであって、そのファイルを手作業で追加したり、自動生成された使う予定のないファイルを削除してはいけない、という意味ではありません。たとえば、もしヘルパースペックを追加する必要があるなら、次に説明するスペックファイルの命名規則に従ってファイルを作成し、 spec/helpers ディレクトリに追加してください。命名規則は以下のとおりです。もし、 app/helpers/projects_helper.rb をテストするのであれば、 spec/helpers/projects_helper_spec.rb を追加します。 lib/my_library.rb という架空のライブラリをテストしたいなら、 spec/lib/my_library_spec.rb を追加します。その他のファイルについても同様です。
まとめ
この章ではRSpecをアプリケーションの開発環境とテスト環境に追加し、テスト実行時に接続するテスト用のデータベースを設定しました。また、RSpec用にいくつかのデフォルト設定ファイルを追加し、Railsがアプリケーション側のファイルに応じてテストファイルを自動的に作成する(または作成しない)ように設定することもしました。
さあ、これでテストを書く準備が整いました!次の章ではモデル層からアプリケーションの機能テストを書いていきます。
Q&A
-
testディレクトリは削除しても良いのですか? ゼロから新しいアプリケーションを作るのであればイエスです。これまでにアプリケーションをある程度作ってきたのであれば、まず
rails test:allコマンドを実行し、既存のテストがないことを確認してください。既存のテストがあるなら、それらをRSpecに移行させる必要があるかもしれません。 - なぜビューはテストしないのですか? 信頼性の高いビューのテストを作ることは非常に面倒だからです。さらにメンテナンスしようと思ったらもっと大変になります。ジェネレータを設定する際に私が述べたように、UI関連のテストは統合テストに任せようとしています。これはRails開発者の中では標準的なプラクティスです。
演習問題
既存のコードベースから始める場合は次の課題に取り組んでください。
-
rspec-rails を Gemfile に追加し、
bundleコマンドでインストールしてください。本書はRails 7.1とRSpec Rails 6.1を対象にしていますが、テストに関連しているコードとテクニックはそれより古いバージョンでも大半が使えるはずです。 - アプリケーションが正しく設定され、テストデータベースと接続できることを確認してください。必要であればテストデータベースを作成してください。
- 新しくアプリケーションコードを追加するときはRSpecを使うようにRailsの
generateコマンドを設定してください。 rspec-rails が提供しているデフォルトの設定をそのまま使うこともできます。そのままにすると、余分な定型コードも一緒に作成されます。使わないコードは手で消してもいいですし、無視しても構いません(使わないコードは削除することをお勧めします)。 - 既存のアプリケーションで必要となるテスト項目をリストアップしてください。このリストにはアプリケーションで必要不可欠な機能、過去に修正した不具合、既存の機能を壊した新機能、境界値の挙動を検証するテストなどが含まれます。こうしたシナリオはすべて次章以降で説明していきます。
新しくてきれいなコードベースから始める場合は次の課題に取り組んでください。
- 前述の説明に従い、Bundlerを使ってRSpecをインストールしてください。
- あなたの database.yml ファイルはテストデータベースを使うように設定されているかもしれません。SQLite以外のデータベースを使っているなら、まずデータベースを作る必要があるかもしれません。まだ作っていなければ、
bin/rails db:create:allで作成してください。 - 必須ではありませんが、RailsのジェネレータがRSpecを使うように設定してみましょう。新しいモデルとコントローラをアプリケーションに追加する際は、開発のワークフローとしてジェネレータを使えるようにし、スペックが自動的に生成されるようにしてください。
ボーナス課題
もしあなたがたくさん新しいRailsアプリケーションを作るなら、Railsアプリケーションテンプレートを作ることもできます。テンプレートを使うと自動的にRSpecや関連する設定を Gemfile に追加したり、設定ファイルに追加したりすることができます。もちろんテストデータベースも作れます。好みのアプリケーションテンプレートを作りたい場合は、 Daniel KehoeのRails Composerから始めてみるのが良いと思います。