Railsの自動テスト(RSpecでModelのテスト編)
rails rspec テスト

Railsの自動テスト(RSpecでModelのテスト編)

このエントリーをはてなブックマークに追加

いよいよJリーグも始まり、嬉しく思っているGMOメディア技術推進室の中村です。今年は何処が優勝するのでしょうかね?自分が応援しているチームが優勝すると良いのですが・・・。

今回はRailsで自動テストをする時に使うRSpecを紹介したいと思います。RSpecはBDD(behavior driven development) 用のテストフレームワークです。RailsではデフォルトでTestUnitがありますが、RSpecも結構人気があり使う人が多いです。

以降ではRailsの中でRSpecを使ったテストの準備から実際にモデルクラスに対するテストの実施までの流れを書いて行きたいと思います。

1. 環境設定

Gemfile に以下のように追記します。

group :test do
  gem "rspec"
  gem "rspec-rails"
end

追記したら「bundle install」を実行します。実行してライブラリをダウンロードしたら、次のコマンドを実行しHelperクラスを生成します。

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

2. テスト作成

それではテストを作成していきましょう。まずはテスト対象のモデルクラスを作成します。今回はapp/model/user.rbを作成します。以下のコマンドを入力してください。

$ rails g model user name:string age:integer profile:text

      invoke  active_record
      create    db/migrate/20130301144608_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/unit/user_test.rb
 

これでapp/model/user.rbが生成されます。次にapp/model/user.rbのテストクラスを生成します。生成するには以下のコマンドを入力してください。

$ rails g rspec:model user
    create  spec/models/user_spec.rb

spec/model/user_spec.rbを見てみると次のようになっています

まだ何もテストコードを書いていないですが、この後describe do endの中にテストコードを追記していきます。ではまずapp/model/user.rbに一つメソッドを追加してみましょう。例えば自分の名前の最後に「でござる」という文字列を追加するメソッドを作成してみましょう。

続いてテストクラスを以下のように編集します。

describe句ではテスト対象の説明を書きます。ここではUserクラスのhelloメソッドになります。そしてcontext句ではテストの状況を表します。ここでは正常ケースで戻り値のチェックを行っています。before句ではテスト実行前に行う処理を記述します。it句の中ではテスト内容を記述します。今回は「helloメソッドの戻り値がnilでない」ということをテストしています。

3. テスト実施

ではテストを実施してみましょう。最初にテスト環境(Rails_ENV=test)にUsersテーブルを作成しましょう。以下のようにrakeコマンドを使います。

$ rake db:migrate RAILS_ENV=test

==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.0015s
==  CreateUsers: migrated (0.0016s) ===========================================

ではテストを実行してみましょう。

$ bundle exec rspec spec/models/user_spec.rb 

.

Finished in 0.02093 seconds
1 example, 0 failures

成功しましたね。今回のような「bundle exec rspec 」という呼び方をすると対象のrspecを一つだけ実行します。「rake spec」と入力すると「spec」フォルダ以下にあるファイルを全て実行します。この辺りは状況により使い分けると良いと思います。それではもっとテストを書いてみましょう。

4. matcherについて

先ほどの例ではメソッドの戻り値がnilかどうかのテストでした。今度は戻り値が期待した値と同じかどうかをチェックしてみましょう。

18行目から22行目にかけて一つテストを追加しています。今回はメソッドの戻り値が期待した値かどうかを2通りのやり方でチェックしています。片方は「==」を使い、もう一方では「eql」メソッドを使っています。では、実行してみましょう。

$ bundle exec rspec spec/models/user_spec.rb 
..

Finished in 0.02235 seconds
2 examples, 0 failures

Randomized with seed 62130
続いてUserクラスにメソッドを追加して更に別のテストを追加してみましょう。 今度はageの値を変更するメソッドを作成し、テストではメソッドの戻り値が想定した範囲内かをチェックさせてみましょう。 age_upというメソッドを追加しました。このage_upメソッドではUserクラスのage属性がカウントアップさます。それではこのメソッドの動きを確認するテストコードを書いてみましょう。 24行目から38行目に掛けて新たにテストコードを追加しました。ここで35行目の「be_close(30,5)」です。これは値が30から+-5の範囲に収まっているかをチェックするテストです。RSpecではbe_nil、eqlやbe_closeの他にも様々な検証用メソッド(matcher)があります。 ここで幾つか例を挙げます。
値がtrue/falseを返すかチェック:be_true/be_false
配列の中身が空かどうかのチェック:be_empty
例外が発生しているかのチェック:raise_error、raise_error(error,msg)

詳細はリファレンス等を参照してください。

今回はテストデータをプログラム中で作成してしまっていますが、spec/fixtures以下にusers.ymlを定義するか、またはfactory_girlを使ってテストデータを用意し、それを使った方が良いです。次回はその辺りの説明から始めてControllerのテストを紹介したいと思います。


名無しのエンジニア
社内LT大会をやりましたというお話
初心者でも分かるRailsで始めるHeroku入門 その2 知って損しないadd onとgem