Rails の ActiveRecord モデルテストの書き方ガイドライン
このエントリでは,Ruby on Rails (以下 Rails)の ActiveRecord モデルテストについて,1) どこの何をテストすればよいか,2) どのようにテストを書けばよいか,のガイドラインを示します.このガイドラインは Rails 公式のものではなく,id:passingloop が使っている私的なものです.疑問・質問・批判・間違いの指摘はページ下部のコメント欄までお願いします.
はじめに
Rails は TDD/BDD サポートが充実した Web アプリケーション開発フレームワークです.Rails で使える Test::Unit や RSpec などといったテスティングフレームワークの使い方に関する解説も豊富にあります.しかし,「どこをどうテストすればよいのか」についての解説は,「使い方」の解説と比較して少ないように思います.もっとも,テスト一般についてどう書くかはアプリケーション次第というところもあるので,これは仕方ありません.とはいえ,ビジネスロジックを含まない「ActiveRecord モデル」なら,ある程度定型化できるのではないでしょうか.
ActiveRecord モデルのテストに関する情報源は多いものの,たくさんあり過ぎて全体像を把握しにくいのも問題です.思いつくだけでも,
- Ruby on Rails Guides: A Guide to Testing Rails Applications
- Agile Web Development with Rails 本
- Rails Test Prescription 本
- GitHub にある数多くの Rails アプリケーションリポジトリ
があります.そこで,この文書では,私が収集したテストに関する情報をもとに,ActiveRecord モデルに対するテストの書き方ガイドラインを示すことを目標にします.
この文書では,まず,「ActiveRecord モデル」を定義します.この文書で扱う ActiveRecord モデル は MVC の 'M' ではないことに注意してください.次に,ActiveRecord モデルについて,どこの何をテストすればよいのか示します.最後に,Test::Unit を使ってテストをどう書けばよいのかを具体例で説明します.
ソースコードを埋め込むときに Gist を使っている箇所があります.JavaScript を無効にしていたり,https://gist.github.com へのリクエストを拒否していたりすると一部のソースコードが正しく表示されないことがあります.その場合は,直接 Gist を参照してください.
ActiveRecord モデルとは
ActiveRecord モデルとは,狭義には ActiveRecord::Base
の派生クラスであり,app/models/model_name.rb
ファイルで定義されるモデルクラスのことを指します.しかし,これだけでは,本文書の ActiveRecord モデル定義の半分です.残りの半分を定義するための材料として,Rails のモデルへの批判とそれに対する私の対応策について説明します.
Rails のモデルへの批判
人気 Web アプリケーションフレームワークの Rails は,その人気ゆえ,批判にさらされることも多くなります.その一例が Rails の モデルへの批判です.たとえば,Ruby on Railsの「えせMVC」の弊害 では,Rails のモデルが ドメインモデル貧血症 に陥りやすい設計であることを批判しています.実は,私もこの批判と同じ意見です.
貧血の治療法
しかし,ビジネスロジックをすべて ActiveRecord モデルに実装する必要があるかというと,必ずしも,そうではありません.たとえば,Dan Chak は著書 "Enterprise Rails" で物理モデルと論理モデルの分離を提案しています.Dan Chak の物理モデルはデータベースとテーブルの抽象化で,ActiveRecord で実現されるものです.物理モデルにビジネスロジックを含めてはいけません.一方,論理モデルはドメインモデルに相当し,ビジネスロジックは全てここに含めます.そして,コントローラなどクライアント向け API は論理モデルにだけ定義します.この方法の利点の一つめは,データベース設計に手を入れてもクライアント向け API が安定すること,二つめは,コントローラが容易にビジネスロジックを利用でき,データの整合性が保証されることです.
本文書の ActiveRecord モデル
私は,Dan Chak の方法とは少し違うやり方でドメインモデル貧血症を予防します.Dan Chak の実装では物理モデルと論理モデルを別々のクラスにしています.この方法では,物理モデルを app/models/physical
に,論理モデルを app/models/logical
に配置します.この方法は Rails のディレクトリ構成規約からやや外れる方法で,物理モデルクラス名が ::Physical
で修飾されるため不必要に長くなるという問題があります.そこで,私は,
- ActiveRecord 派生クラスを物理モデルとして実装する
- 論理モデルはモジュールとして実装する
- 物理モデルに論理モデルモジュールを
include
して MVC の M を実現する
方法を採用しています.これにより,
を実現しています.
本文書の「ActiveRecord モデル」とは,ここで説明した物理モデルのことです.したがって,ActiveRecord モデルに対するテストは物理モデルに対するテストということになります.
どこをテストするのか
それでは,ActiveRecord モデルの,どこの何をテストすればよいのでしょうか.先に答えを言ってしまうと,どこをテストするのかについては
- Validation
- データベース
です.
Validation のテストについては,Ruby on Rails Guides が「validation をテストせよ」と書いています.Validation は ActiveRecord モデルクラスに定義されるもので,このクラスでしかテストできないものなので,ActiveRecord モデルでテストします.データベースに関するテストについては ActiveRecord モデルが物理モデルであることから,当然ここでテストします.
と書きましたが,本当に当然なのでしょうか? 次のデータベースに関するテストに関する議論で当然が正しかったかどうか確認します.
データベースに関するテストとは?
データベースに関するテストでは,
- 制約テスト
- CHECK
- NOT NULL
- UNIQUE
- 参照整合性テスト
- FOREIGN KEY
を行ないます.これらはデータベースのスキーマに関するテストなので,SqlUnit とか SchemaUnit とかというのを使ってデータベース側でテストすべきと考えるかもしれません.しかし,制約や参照整合性に違反するデータをデータベースに投入しようとした場合,ActiveRecord モデルは例外を投げることを思い出しましょう.そうなると,最早データベースから離れて ActiveRecord モデルの振舞いの問題なので,例外が期待通りに起こることを振舞いテストとしてテストする必要が出てきます.
つまり,データベースに関するテストとは,制約や参照整合性に違反したデータをデータベースに投入しようとしたときに発生する例外が,期待通りに発生することを確かめるネガティブテストだということになります.
他にもテストすべきものがあるのでは?
ここまで,ActiveRecord モデルでは validation とデータベースをテストすることを説明しましたが,他にもテストするべきものがあるのでは,と疑問に思う人がいるかもしれません.たとえば,
has_many
やbelongs_to
のような関連定義- スコープ
- その他のメソッド
です.しかし,これらは ActiveRecord モデルではテストしません.それはどうしてかというと,
has_many や belongs_to, スコープをテストしないのは?
has_many
などやスコープといった ActiveRecord が提供するクラスメソッドは,Rails 本体でさんざんテストされているので,テスト無しに使っても大丈夫です.ただし,条件に lambda
ブロックを使うなど,複雑なものはテストしてもいいかもしれません.でも,やっぱりしなくてもいいかもしれません.その理由は次を読んで考えてください.
その他のメソッドをテストしないのは?
ActiveRecord モデルクラスに定義されるメソッドは,インクルードされる論理モデルモジュールからのみ呼び出されるべきです.よって,これらのメソッドは基本的にはプライベートメソッドとして定義されます.ユニットテストでプライベートメソッドもテストすべきかどうかは議論が分かれるところですが,私は「プライベートメソッドまで無理してまでテストする必要はない.Ruby だからできるけど」という考えなので,テストしません.
プライベートメソッドをテストしなくても,それを呼び出す論理モデルモジュールのメソッドをテストするのですから,カバレッジ上は問題ありません.
Ruby on Rails Guides には違うことが書いてあるけど?
さんざん参考文献として例に挙げてきた Ruby on Rails Guides ですが,実は,ここで言っているのとは違うことが書いてあります.該当部分を引用して確認してみると,
3.3 What to Include in Your Unit Tests
Ideally, you would like to include a test for everything which could possibly break. It’s a good practice to have at least one test for each of your validations and at least one test for every method in your model.
と,本当は,
- Validation
- 全てのメソッド
をテストせよと書いてあります.この Ruby on Rails Guides とこの文書は矛盾しています.それでは,どちらが間違っているかというと,どちらも間違ってはいません.というのも,Ruby on Rails Guides とこの文書とではユニットテストの対象としているモデルの考え方が違うからです.
Ruby on Rails Guides が対象としているモデルがどのようなものかというと,...実は,はっきりと書いていません.ですので,validation とメソッドだけをテストすればいいようなケースも,きっと含んでいるのだと思います.一方,繰り返しですが,この文書のモデルは,より明確に定義された「ActiveRecord モデル」なので,validation とデータベースをテストします.
どのようにテストを書くか
ここまで,ActiveRecord モデルに対するテストは validation に関するテストとデータベースに関するテストの 2 つであることを説明してきました.それでは,これらの 2 つのテストをどのように書けばよいのでしょうか.これらのテストを書く際にはポジティブテスト(成功するテスト)とネガティブテスト(失敗するテスト)の 2 つを書きます.すなわち,
- 正常値オブジェクト → エラーにならないこと
- 異常値オブジェクト → エラーになること
をテストします.
ここでは,まず,ActiveRecord モデルの例として Item モデルを用意し,このモデルに対してテストを具体的に書いていきます.
例: Item モデル
何もないところにテストは書けないので,例として Item モデルを用意しました.
Item モデルは,Vendor モデルに対して belongs_to
関連をもっています.この Item モデルのマイグレーションは次のようになります.
vendor_id
, title
, price
の 3 つのカラムには NOT NULL 制約が設定されています.NOT NULL 制約は add_column
メソッドで簡単に設定できます.さらに,11 行目から execute
メソッドで SQL を実行しています.データベースには CHECK 制約と FOREIGN KEY 制約を追加したいのですが,Rails のマイグレーションにはこの 2 つの制約を追加するメソッドが無いので仕方なく生 SQL に頼ります.余談ですが,この execute
メソッドは,「簡単なことは簡単に,そうでないことはそれなりに」実現できる ActiveRecord の懐の深さを感じられるので,私が気に入っているメソッドの一つです.
話を元に戻して,Item モデルの ActiveRecord モデルは次のようになります.
belongs_to
関連と validation が設定されています.
データベースに制約があるのに同じ意味の validation を書くのはなぜか
Item モデルの title
, price
2 つのカラムにはデータベース制約と validation の両方が設定されています.データベース制約があるのに同じ意味の validation を書くのは冗長だと思った人がいるかもしれません.しかし,validation が無いと,モデルの異常値でデータベースの例外がアプリケーションに飛んでしまいます.アプリケーションに不必要に例外を飛ばさないためにも,validation を設定しましょう.さらに,データベースの例外からデータの異常を探るのは難しいのですが,validation があるとアプリケーションで捕捉できるというメリットもあります.
実は,データベース制約と validation とでは検出する異常の意味合いが異なります.Validation で検出する異常は入力エラーです.ユーザにデータの修正を促すためのものです.一方,データベースで検出する異常はアプリケーションのバグです.開発者にコードの修正を促すためのものです.というわけで,私はデータベース制約と validation の両方を設定することにしています.
association_id である vendor_id のバリデーションを書かなかったのはなぜか
データベースの vendor_id
カラムには NOT NULL 制約と FOREIGN KEY 制約がありました.しかし,ActiveRecord モデルの vendor_id
には NOT NULL 制約に相当する validation はありませんでした.これは,vendor_id == nil
は入力データの異常ではなく,アプリケーションのバグだと想定しているからです.すなわち,このアプリケーションは vendor_id
をユーザが直接指定するような仕様ではなく,さらに,item.vendor = nil
と書くようなユースケースも想定していないことを意味しています.そんなこと今までどこにも書いていませんでしたが,今書いたので許してください.
まとめると,NOT NULL/FOREIGN KEY 制約違反はバグというアプリケーションの仕様を想定しているので,validation で検出するよりデータベース例外を投げたほうがよいということです.
準備 1) スキーマを Ruby ではなく SQL で保存するよう Rails を設定する
テストを書いていく前の準備が 2 つあります.一つめは,スキーマを Ruby ではなく SQL で保存するよう Rails を設定することです.Rails が test 環境のデータベースを用意するときには,development 環境のデータベーススキーマをコピーします.このときに使うスキーマは,development 環境のデータベースをマイグレーションしたときに自動で保存されるスキーマで,デフォルトでは Ruby で書かれたマイグレーションコードとして保存されます.ここで問題となるのが,execute
メソッドなどで追加した Ruby のマイグレーションで表現できない SQL 文です.これらの SQL 文はデフォルトの Ruby 形式スキーマには保存されないので,test 環境のデータベースにコピーされません.このままでは制約をテストできません.
そこで,スキーマの保存形式を Ruby から SQL に変更します.config/applicaiton.rb に,
# config/application.rb
module Dummy
class Application < Rails::Application
config.active_record.schema_format = :sql
end
end
と, config.active_record.schema_format = :sql
を追加しましょう.これで test 環境のデータベースにも制約がコピーされます.
準備 2) factory_girl を導入する
テストデータの作成に利用する factory_girl を導入します.Rails に factory_girl を導入する際は,factory_girl_rails gem が便利です.factory_girl_rails gem を導入するとジェネレータがフィクスチャリプレースメントとして factory_girl を使うようになります.Gemfile に
group :test do
gem 'factory_girl_rails'
end
を追加して,bundle update
します.さらに,test/test_helper.rb で,
# test/test_helper.rb
class ActiveSupport::TestCase
include Factory::Syntax::Methods
end
と,ActiveSupport::TestCase
クラスに Factory::Syntax::Methods
モジュールをインクルードしておきましょう.このモジュールをインクルードすると,テストメソッド中で FactoryGirl.create(:foo)
とする代わりに create(:foo)
とスッキリ書けます.
なぜ Fixtures を使わないのか
Fixtures はデータベースの状態を用意します.だから,データベースに制約があるときには,制約に違反する異常値 fixture を作成したくでもできません.このため Fixtures は異常値テストには向きません.ActiveRecord モデルのテストでは,正常値のテストだけでなく異常値のテストも行なうため,フィクスチャリプレースメントとして factory_girl を採用しました.
だからといって,アプリケーションのテスト全体から Fixtures を追放するかというと,そういうわけではなく,論理モデルのテストでは Fixtures のほうが便利で,こちらを使うこともあります.つまり,Fixtures をフィクスチャリプレースメントで完全に置き換えるのではなく,いいとこ取りで併用します.併用する理由,すなわち,完全に置き換えない理由については factory_girl の採用面接 も合わせて読んでみてください.
Validation をテストする
ようやく準備が整いました.まずは validation のテストから書いていきます.
正常値オブジェクトがエラーにならないことを確認する
まず,ポジティブテストを書きます.すなわち,正常値オブジェクトがエラーにならないことを確認するテストです.このときに用意する正常値オブジェクトの属性値には,境界値を設定します.この境界値ファクトリの名前はそのまま,item_with_boundary_value_attributes
という何のひねりもない名前にします.ファクトリ定義は,
# test/facytories/items.rb
FactoryGirl.define do
factory :item, aliases: [:item_with_boundary_value_attributes] do
vendor
title "Q"
description "Using this item, you will be taller."
price '0.00'
end
end
となります.このファクトリは Item
クラスのオブジェクトを作るものなので,名前を :item
として定義しておくとクラス名の設定が不要になり便利です.そして,本来つけたかった名前,:item_with_boundary_value_attributes
をエイリアスとして設定しています.
そして,いよいよテストメソッドです.テストメソッドは,"{ファクトリ名} is valid" とします.今回のファクトリ名は item_with_boundary_value_attributes
だったので,
# test/units/item_test.rb
test 'an item with boundary value attributes is valid' do
assert build(:item_with_boundary_value_attributes).valid?
end
となります.build
でデータベースに保存しないオブジェクトを作って valid?
するだけです.簡単でしょ.
異常値オブジェクトがエラーになることを確認する
次にネガティブテストを書きます.すなわち,異常値オブジェクトがエラーになることを確認するテストです.異常値を用意する異常値ファクトリには,:{モデル名}_with_{異常な}_{属性名}
という命名規則で名前をつけます.今回は,
:item_with_empty_title
:item_with_blank_title
:item_with_empty_price
:item_with_negative_price
の 4 つの異常値ファクトリを用意しました.このときに用意する異常値ファクトリは,ポジティブテストで用意した正常値(境界値)を少し修正するだけで用意できます.こんなときには factory_girl の継承機能が便利です.異常値ファクトリを追加して完成した Item モデルのファクトリ定義を次に示します.
次に,テストメソッドを書いていきます.テストメソッドは "{異常値ファクトリ名} is invalid" とします.今回用意したファクトリのそれぞれについてテストを書くと,
# test/units/item_test.rb
test 'an item with empty title is invalid' do
item = build(:item_with_empty_title)
assert item.invalid?
assert item.errors[:title].any?
end test 'an item with blank title is invalid' do
item = build(:item_with_blank_title)
assert item.invalid?
assert item.errors[:title].any?
end
test 'an item with empty price is invalid' do
item = build(:item_with_empty_price)
assert item.invalid?
assert item.errors[:price].any?
end
test 'an item with negative price is invalid' do
item = build(:item_with_negative_price)
assert item.invalid?
assert item.errors[:price].any?
end
となります.各テストメソッドでは,異常値オブジェクトが invalid?
であることと,異常値属性がエラーになっていることを確認します.
これで,validation のテストは完成です.
データベース制約・参照整合性をテストする
Validation のテストが片づいたところで,データベース制約・参照整合性テストに移ります.テストを書く前に,ActiveSupport::TestCase
にデータベーステスト用のアサーションを追加しましょう.
準備: データベースエラーのためのアサーションを追加する
データベースに対するネガティブテストではデータベース例外の発生を確認します.具体的には,
ActiveRecord::StatementInvalid
... NOT NULL, CHECK 制約違反ActiveRecord::RecordNotUnique
... UNIQUE 制約違反ActiveRecord::InvalidForeignKey
... FOREIGN KEY 制約違反
が発生することを確認します.例外発生のアサーションには assert_raise
が使えるのですが,毎回
assert_raise ActiveRecord::StatementInvalid do
...
endassert_raise ActiveRecord::RecordNotUnique do
...
end
assert_raise ActiveRecord::InvalidForeignKey do
...
end
と長い例外名を書くのは面倒なので,専用のアサーションを用意します.それぞれ名前を,
assert_statement_invalid
assert_record_not_unique
assert_invalid_foreign_key
として,ActiveSupport::TestCase
に追加しましょう.追加する場所は test/test_helper.rb が適当です.
# test/test_helper.rb
class ActiveSupport::TestCase
include Factory::Syntax::Methods def assert_statement_invalid(&block)
assert_raise(ActiveRecord::StatementInvalid, &block)
end
def assert_record_not_unique(&block)
assert_raise(ActiveRecord::RecordNotUnique, &block)
end
def assert_invalid_foreign_key(&block)
assert_raise(ActiveRecord::InvalidForeignKey, &block)
end
end
これで準備が整いました.
正常値オブジェクトを保存できることを確認する
Validation のテストと同様,ポジティブテストから書いていきます.データベースのテストでは validation のテストで用意したファクトリを再利用します.:item_with_boundary_value_attributes
ファクトリを使って,"db allows saving an item with boundary value attributes" テストメソッドを書きます.言い忘れましたが,データベースのポジティブテストでテストメソッドを書くときにはメソッド名を "db allows saving {正常値ファクトリ名}" とします.
test 'db allows saving an item with boundary value attributes' do
assert build(:item_with_boundary_value_attributes).save
end
制約をテストする
ここでも,validation のテストで用意した異常値ファクトリを全部そのまま再利用します.ただし,vendor_id
カラムに NULL を設定するファクトリだけは用意していないので,build(:item, vendor_id: nil)
として異常値オブジェクトを作ります.また,単に save!
とするとデータベース制約よりも先に validation がエラーを検出してしまうので,{ :validate => false }
として validation を回避します.テストメソッド名は,"db can catch {異常な状態の} {属性}" という命名規則で名前をつけます.そして,例外の捕捉には,準備しておいた制約違反用のアサーション assert_statement_invalid
を使います.
test 'db can catch null title' do
assert_statement_invalid do
build(:item_with_empty_title).save!(validate: false)
end
endtest 'db can catch blank title' do
assert_statement_invalid do
build(:item_with_blank_title).save!(validate: false)
end
end
test 'db can catch null price' do
assert_statement_invalid do
build(:item_with_empty_price).save!(validate: false)
end
end
test 'db can catch negative price' do
assert_statement_invalid do
build(:item_with_negative_price).save!(validate: false)
end
end
test 'db can catch null vendor_id' do
assert_statement_invalid do
build(:item, vendor_id: nil).save!(validate: false)
end
end
参照整合性をテストする
参照整合性をテストするためのファクトリも validation のテストで用意していないので,正常値(境界値)オブジェクトの vendor_id
を変更して,build(:item, vendor_id: 99999999)
のようにして異常値オブジェクトを作成します.テストメソッド名は,"db can catch {モデル名} with invalid reference" とします.
test 'db can catch an item with invalid reference' do
assert_invalid_foreign_key do
build(:item, vendor_id: 99999999).save!(validate: false)
end
end
参照整合性テストで新たにファクトリを定義しなかったのはなぜか
参照整合性テストで異常値オブジェクトを作るときは新たにファクトリを定義せず,既存のファクトリを流用しました.:item_with_invalid_reference
というファクトリを新しく作ってもよさそうなのに,と思った方がいたかもしれません.新たに定義しなかったのは理由は簡単で,ファクトリを定義したとしても一度しか呼び出されないからです.Validation のテストで用意したファクトリは,データベースのテストでも使われており,全て二回呼び出されています.制約テストで :item_with_null_vendor_id
というファクトリを定義しなかったのも同様の理由です.
テスト完成
これで,テストを全て書き終えました.これまで書いたものを全て繋いで test/units/item_test.rb とします.
(参考)例で登場しなかったパターン: UNIQUE 制約のテスト
データベースの制約には三種類あります.
- CHECK
- FOREIGN KEY
- UNIQUE
このうち,UNIQUE 制約は今回の例では登場しなかったので(参考)として補足します.UNIQUE 制約をもつモデルとして Foo モデルを別に用意しました.テストの説明に使えればいいので名前も中身もかなり適当ですが,必要十分です.まずは,マイグレーションから,
UNIQUE 制約は add_index
メソッドで { :unique => true }
することで設定できます.次に,ActiveRecord モデルクラスです.
UNIQUE 制約違反はバグではなく入力エラーなので validation を設定しています.
Validation のテスト
それでは UNIQUE 制約について validation のテストから書いていきましょう.テストメソッド名は "{モデル名} with duplicate {UNIQUE 属性} is invalid" とします.
# test/units/foo_test.rb
test 'a foo with a duplicate bar is invalid' do
create(:foo)
foo = build(:foo)
assert foo.invalid?
assert foo.errors[:bar].any?
end
3 行目の create(:foo)
で作ったオブジェクトと同じ属性値をもつオブジェクトを 4 行目で作り,そのオブジェクトが invalid?
であること(5 行目),bar
属性についてエラーとなること(6 行目)をアサーションしています.
データベースのテスト
次に UNIQUE 制約についてデータベースのテストを書きます.テストメソッド名は,"db can catch duplicate {UNIQUE 属性の属性名}" とします.
# test/units/foo_test.rb
test 'db can catch duplicate bars' do
create(:foo)
assert_record_not_unique do
build(:foo).save!(validate: false)
end
end
準備しておいた assert_record_not_unique
アサーションを活用します.
おわりに
この文書では,ActiveRecord モデルテストの書き方についてガイドラインを示し,例を使って具体的に解説しました.最後に,この文書で登場したガイドラインをまとめておきます.
- ActiveRecord モデルのガイドライン
- ActiveRecord モデルは物理モデル
- モデルの validation とデータベース操作を担当
- ビジネスロジックは別モジュールにして
include
= 論理モデル,MVC の M に相当
- どこをテストするかのガイドライン
- モデルの validation
- データベース制約・参照整合性
- 何をテストするかのガイドライン
- 正常値 → エラーにならない
- 異常値 → エラーになる
- テストデータ準備のガイドライン
- factory_girl = フィクスチャリプレースメント利用
もう一つ,ファクトリ名やテストメソッド名の命名規則もガイドラインとして登場しました.こちらもまとめておきます.
- 正常値ファクトリ名
:{モデル名}_with_boundary_value_attributes
←:{モデル名}
のエイリアス
- 異常値ファクトリ名
:{モデル名}_with_{異常な}_{属性名}
- Validation テストメソッド名
- "{正常値ファクトリ名} with boundary value attribute is valid"
- "{異常値ファクトリ名} is invalid"
- データベーステストメソッド名
- "db allows saving {正常値ファクトリ名}"
- "db can catch {異常な} {属性名}"
- "db can catch duplicate {UNIQUE 制約の属性名}"
大事なことなので二度言いますが,この文書は私的なものです.よって全ての Rails 開発に適用できるものではありません.ActiveRecord モデルの定義からも分かるように,このガイドラインはエンタープライズアプリケーション開発を主対象としています.このガイドラインに忠実であるためには,データベース設計は「まとも」でないといけないですし,RDBMS も SQL の「制約」をまともに扱えるものを採用する必要があります.データベースを NoSQL 的に使ったり NoSQL を使ったりする開発では何の役にも立ちません.そんな場合でも,どこの何をどのように,そして,それはなぜテストするのか考える上で参考になるかもしれません.もし何かの参考になれば幸いです.
それでは,世の中に ActiveRecord モデルテストが充実した Rails アプリケーションが増えますように.