- 更新日: 2014年3月3日
- RSpec
Rails モデルの RSpec 単体テストで validation と DB に対するテストを区別した
モデルの単体テストで validation と DB に対するテストで、describe ブロックを区別して書くように修正しました。
— 環境 —
rails-4.0.1
rspec-rails-2.14.0
capybara-2.2.0
以下の記事を読んだのがきっかけです。
それでは,ActiveRecord モデルの,どこの何をテストすればよいのでしょうか.先に答えを言ってしまうと,どこをテストするのかについては
・Validation
・データベース
です.
…
データベースに関するテストでは,
制約テスト
・CHECK
・NOT NULL
・UNIQUE
参照整合性テスト
・FOREIGN KEY
を行ないます.
テストの書き方は超勉強中なので、こういう実践的な記事はとてもありがたい。これまで、validation と DB に対するテストは意識して書くようにしていて、それが正解なのを確認できたのは良かったです。しかし、両者のテストコードがごちゃ混ぜになっており、頭が混乱しがちでした。
describe ブロックを validation と DB で分けた
モデルの単体テスト(spec/models/user_spec.rb)で、validation に対するテストと DB に対するテストで describe ブロックを分けました。これで随分と見通しが良くなった。
spec/models/user_spec.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
describe User do #... describe "with validation" do #... end describe "with DB" do describe "column having not-null constraint" do #... end describe "column having unique-key constraint" do #... end describe "column having foreign-key constraint" do #... end end #... end |
validation を RSpec でテスト
元記事は、Test::Unit を使われていますが、私は RSpec を使っているので、validation が invalid な場合に対する各々の具体的なテストは以下のように書く。
例えば、uid 属性が presence: true の validation なら以下。
1 2 3 4 |
describe "when uid is not present" do before { @user.uid = " " } it { should_not be_valid } end |
uid が空の場合、it { should_not be_valid } で、@user が正当でないとテストできます。
データベースの例外発生を RSpec でテスト
再び引用。DB に対するテストについてです。
データベースに対するネガティブテストではデータベース例外の発生を確認します.具体的には,
・ActiveRecord::StatementInvalid … NOT NULL, CHECK 制約違反
・ActiveRecord::RecordNotUnique … UNIQUE 制約違反
・ActiveRecord::InvalidForeignKey … FOREIGN KEY 制約違反
が発生することを確認します.
RSpec で例外発生をテストするのは次の書き方を使う。
1 2 3 |
expect do # do something end.to raise_error( 例外クラス名 ) |
または、
1 2 3 |
lambda do # do something end.should raise_error( 例外クラス名 ) |
例えば DB の email カラムに unique 制約が付いているのをテストする場合は以下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
describe "with DB" do describe "column having unique-key constraint" do describe "when email address is already taken" do before { @user.save! } it "should raise error ActiveRecord::RecordNotUnique" do expect do user_with_same_email = @user.dup user_with_same_email.email = @user.email user_with_same_email.save! end.to raise_error( ActiveRecord::RecordNotUnique ) end end end #... end |
既存のユーザーと email が同一のユーザーをレコードに保存しようとしたら、ActiveRecord::RecordNotUnique の例外が発生することを意図したテストです。
テストは何よりも読みやすさが大事なので、以上気を付けて書いていきたい。
- – 参考リンク –
- Rails の ActiveRecord モデルテストの書き方ガイドライン – passingloopの日記
- raise_error matcher – Built in matchers – RSpec Expectations – RSpec – Relish
- Rails4 rspecによる例外のテスト – ayaketanのプログラミング勉強日記
RSpecで例外の発生をテストする方法 – memo.yomukaku.net
- RSpec の関連記事
- FactoryGirlをSpringと共に使う時の注意
- 複数モデルのpost :createをテストするRSpecコード(Controller Spec)
- RSpec3でTime.nowをスタブ化(stub)
- RSpecでJSONによるPOSTリクエストをテスト
- RSpec & Capybara の雑感
- RSpec+Capybaraで同名の複数要素の並び順をテストする
- RSpec3ではrails_helper.rbがrequireされる
- Capybara + Launchy で RSpec テストをブラウザで確認
- CapybaraのwithinをRSpecで使う
- Serverspec(RSpec)のテスト出力に色を付けて見やすくフォーマット
Leave Your Message!