9
2

RailsのMinitestで処理実行前後の差分テストをスマートに書きたい

Last updated at Posted at 2024-09-02

ざっくりで言うと

処理実行前後の差分テストを行う時は、以下のメソッドを使うって話です。

  • 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の名前変更機能がこの部分に適用されない恐れがあるので、ラムダで書くのがおすすめです。

参考

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2