「状態」のテストと「振る舞い」のテスト
#8 に関連して。
あんまり良い例じゃない気がするんですけど、例えば User モデルで、重複する username のユーザーを登録できないという spec を書く場合、
- shoulda-matchers の validate_uniqueness_of を使って DB のテーブルにユニーク制約がはってあることをテストする
- User.save! が ActiveRecord::RecordNotUnique を吐くことをテストする
- save! の前後で users テーブルの件数に変化がないことをテストする(
.not_to change的なやつ)
みたいな感じで、何通りも spec の書き方がある気がするんですけど、どの書き方が良い spec なのか、という話です。
なんとなく 1 は「状態」のテストになっている気がして、「振る舞い」をテストしてる 2 の方が良い気がするんですけど、実際に DB のテーブルに insert されないことをテストしている 3 のほうが良いような気もするんですよね。
なんていうか僕がテスト技法について無知なだけな気がしてきた
(遅レスすいません。今気づいた)確かに、テストしたいことに対していろんなやりかたがありますね。
今自分がどうやってテストを書いているか考えてみました。
Userモデルの例だと、「重複が登録できないこと」をそのままチェックするのは3なので、まずは3でいこうかと考えます。もし「例外を発生すること」もチェックしたい内容なのであれば2と3両方書いている気がします。
validate_uniquenes_of的なものを自前で実装していたらこれで 🙆 なのですが、Railsのモデルの場合は、validate_uniquness_ofがちゃんと設定されていれば重複が登録できないのはまあ間違いないと考えて良さそう&&簡潔に意図を伝えることができるので、最終的には1を採用しそうです。
つまり自分はおそらく
- このテストで一体何をチェックしたいのかを突き詰めて考える
- そこからテストの質を落とさず簡潔に書ける方法を探す
という手順を踏んでやり方を決めているのではないかと。ただしすべてのテストでこういう思考かはちょっと自信ないので他にも例があると嬉しいですね ;-)
なるほど。まあそうですよね 良い具体例がいくつかあると指針になるかもしれないですね