Rails標準のテスト準備

Railsのテストツールはminitestがバンドルされています。rails testコマンドがテストランナーのコマンドです。以下の指定方法をよく使いますが、さらに細かいオプションで単体ケースの実行なども可能です。

  • rails test
    • test/ディレクトリ以下のテストを一式実行
  • rails test test/some-directory
    • 特定ディレクトリ内のテストを一式実行。末尾にスラッシュがつくと適切に動作しない
  • rails test test/some-directory/some-test.rb
    • 特定ファイルのテストを実行

ミドルウェア設定

テストはRAILS_ENV=testで実行されます。RDBMSやRedisなどの接続設定は、config/database.ymlのtest用設定や、config/environments/test.rbなどで設定でき、depelopmentと異なる構成をとれます。

サーバーインスタンス構成はdevelopmentの実行環境を流用し、データベースのみ切り分ける設定でも問題はないでしょう。実行環境は自動選択され、たとえばrails console実行時はdevelopment環境で動作し、rails testはtest環境で動作する挙動になります。

DB側の事前セットアップはCREATE DATABASEGRANTまでは完了しておく必要があります。また、あらかじめデーモン起動しておき、接続可能な状態が必要です。

また、アプリケーションでストアドプロシージャなどのDB機能を使用している場合、あらかじめRAILS_ENV=test用のDBにセットアップしておくことで、テストコードからも問題なく利用できます。 ridgepoleでセットアップする場合は、以下のように-EオプションでDBを指定できます。

$ ridgepole -c config/database.yml -f config/Schemafile -a -E test

Rails minitestのDB準備

テスト実行時の準備動作として db/schema.rb が実行され、テーブルをセットアップします。

DBスキーマの管理ツールに、ridgepoleなど非標準の手段を利用している場合、schema.rbを最新の状態にしておく必要があります。

rails db:schema:dumpを実行するとschema.rbが更新されます。
リリース前にテストを実行する実情を考慮すると、このコマンドの実行環境はdevelopmentが妥当でしょう。

なお、テストコードからDBMSへの書き込み操作については、テストの最後にROLLBACKが走ります。基本的なテスト実行のためのクリーンアップ処理を追加する必要はありません。

fixture

テストにデータが必要かどうかは個別のテストケースに依存します。テストは冪等に実行すべきものであるため、データも個別のテストケース実装に近いレイヤのコードとして供給した方が良いでしょう。

Railsの場合、テーブル作成後のデータロードはfixtureを通じて行われます。
ロードされたfixtureオブジェクトはかなり高機能です。以下のようなUserモデルのfixtureの場合、User.find(1)users(:john)は同様のActiveRecordオブジェクトを返し、リレーションも機能します。

john:
  id: 1
  name: John
  email: [email protected]

デフォルトでは test/test_helper.rbのfixtures :allが設定されており、すべてのfixtureファイルをロードする挙動になります。テーブル名に対応するシンボルをカンマ区切りで列挙することで、特定のフィクスチャのみロードさせることも可能です。

fixturesはrails generateした際に空の定義が生成されることがあり、NULLカラムに満ちたデータを作成する挙動になります。 DBテーブル定義でNOT NULL制約を指定しているカラムがあると、空のfixturesロード時にエラーになります。

そのため、中途半端に空のfixtureを置いた状態ではテストを実行できないケースが多々起こります。初期段階でデータを利用しないテストを実行したい場合はtest_helper.rbのfixtures設定をコメントアウトすれば、データロードを回避できます。

カバレッジ計測

カバレッジ計測には simplecovを使います。 Gemfileのtest環境向けブロックでsimplecovをインストールしておきます。

gem 'simplecov', require: false

test/testhelper.rbの冒頭でrequireします。アプリケーションのロード前にrequireしないとカバレッジを適切に計測できません。

require 'simplecov'

計測の設定はプロジェクトルートに.simplecovというファイルを以下の内容で作成しています。

SimpleCov.start do
  # exclude uneeded dirs
  add_filter ['test/', 'config/']

  add_group "Models", "app/models"
  add_group "Controllers", "app/controllers"
  add_group "Helpers", "app/helpers"
end

設定が完了したら、あとはrails testなどのテストランナーを一般的な手順で実行するだけです。レポートはcoverageディレクトリに生成されます。レポートは人が読むためのファイルであるため、.gitignoreでcoverageディレクトリを除外するのが適切でしょう。

なお、テストコードを1つも書いていないクラスはカバレッジの母数にも含まれないため、まずは広く薄くテストケースを書いておいた方が把握しやすくなります。

まとめ

まず、rails testコマンドを実行してみて、DBMS関連のエラーで停止する場合にはテスト環境の事前準備が完了していない可能性が高いと言えます。

DB接続、スキーマ、fixtureを確認することで、テスト時セットアップ動作のトラブルに対処できます。

中馬崇尋
Chuma Takahiro