ざっくりで言うと
処理実行前後の差分テストを行う時は、以下のメソッドを使うって話です。
- assert_changes
- assert_difference
- assert_no_changes
- assert_no_difference
どれぐらいスマートに書けるか
以下二つのテストコードを比較してください。
上記のメソッドを使わなかった時
test 'ユーザーを作成' do
before_count = User.where('hoge').count
# ユーザー作成処理
post users_path, params: { name: 'hoge' }
after_count = User.where('hoge').count
assert_equal(1, after_count - before_count)
end
test 'ユーザーをプレミアム会員に変更' do
before_grade = User.find(1).gread
assert_equal before_grade, 'REGULAR'
# ユーザーをプレミアム会員に更新
patch users_path(1), params: { gread: 'PREMIUM' }
after_grade = User.find(1).gread
assert_equal after_grade, 'PREMIUM'
end
上記のメソッドを使った時
test 'ユーザーを作成' do
assert_difference -> { User.where(name: 'hoge').count } => 1 do
# ユーザー作成処理
post users_path, params: { name: 'hoge' }
end
end
test 'ユーザーをプレミアム会員に変更' do
assert_changes -> { User.find(1).gread }, from: 'REGULAR', to: 'PREMIUM' do
# ユーザーをプレミアム会員に更新
patch users_path(1), params: { gread: 'PREMIUM' }
end
end
どうでしょう?かなりスッキリしたと思います。
また、このメソッドを利用した方が仕様がわかりやすくなります。
assert_difference活用サンプル
予期したデータが作成されていることを確認
assert_difference -> { User.where(name: 'hoge').count } => 1 do
# ユーザー作成処理
post users_path, params: { name: 'hoge' }
end
予期したデータが削除されていることを確認
assert_difference -> { User.where(id: 1).count } => -1 do
# ユーザー削除処理
delete users_path(1)
end
2つ以上の値の変化を見る
# 名前がhogeの人が増えていることと、全体で1件足され、余計なデータが増えていないことが確認できる。
assert_difference -> { User.where(name: 'hoge').count } => -1,
-> { User.count } => -1 do
# ユーザー作成処理
post users_path, params: { name: 'hoge' }
end
assert_change活用サンプル
予期値に更新されてることを確認
assert_changes -> { User.find(1).gread }, from: 'REGULAR', to: 'PREMIUM' do
# ユーザーをプレミアム会員に更新
patch users_path(1), params: { gread: 'PREMIUM' }
end
2つの以上の値を確認する
公式ドキュメントを見た感じで、普通にはできなさそうなので、配列を利用します。
assert_changes -> { user = User.find(1)
[user.gread, user.name] },
from: ['REGULAR', 'hoge'],
to: ['PREMIUM', 'hogehoge'] do
patch users_path(1), params: { gread: 'PREMIUM', name: 'hogehoge' }
end
assert_no_difference活用サンプル
使い方はassert_differenceとほとんど同じです。差分がないので、その分の引数が不要になります。
assert_no_difference -> { User.count } do
# 不正な名前はデータ作成を行わない
post users_path, params: { name: '不正な名前' }
end
assert_no_changes活用サンプル
使い方はassert_changesとほとんど同じです。差分がないので、to:
のパラメータ引数が不要になります。
assert_no_changes -> { User.find(1).name }, from: 'hoge' do
# 不正な名前に更新しない
patch users_path(1), params: { name: '不正な名前' }
end
記述する時の注意点
各メソッドのラムダの部分は文字列で書くこともできます。
assert_difference 'User.where(name: "hoge").count', 1 do
# ユーザー作成
post users_path, params: { name: 'hoge' }
end
この書き方をするとIDEの名前変更機能がこの部分に適用されない恐れがあるので、ラムダで書くのがおすすめです。
参考