1
1

【Rails】assertとassert_predicateの違い

Last updated at Posted at 2023-12-24

1. はじめに

現在、RailsチュートリアルでRuby on Railsを学習しています。

第6章で紹介されるテストコードに対してRubocopで解析をかけたところ、assert @user.valid?ではなくassert_predicate(@user, :valid?)の使用を推奨されました。

今回はこれら2つの違いについてまとめていきます。

2. assert・assert_predicateとは

assertメソッドもassert_predicateメソッドもMinitestで使えるアサーションの1つです。
Rails テスティングガイドの説明を引用してまとめると以下の通りです。

■ assert
指定した式(test)がtrueである場合、テスト成功。

assert( test, [msg] )

  • testはtrueであると主張する。

■ asset_predicate
オブジェクト(obj)の述語メソッド(predicate)の結果がtrueである場合、テスト成功。

assert_predicate ( obj, predicate, [msg] )

  • obj.predicateはtrueであると主張する (例:assert_predicate str, :empty?)。

assert_predicate(@user, :valid?)@user.valid?がtrueの場合に成功とも言い換えることができます。そのため、assert @user.valid?assert_predicate(@user, :valid?)は同じ内容をテストしていると言えます。

3. assert・assert_predicateの比較

次に、テストコードを実際に実行させ、それぞれのアサーションで出力結果にどのような違いがあるのかを比較していきます。

3.1 実行内容

name属性が空白の場合にエラーとなるバリデーションを設定し、実行結果を比較します。

user.rb
class User < ApplicationRecord
  validates :name, presence: true
end

3.2 実行結果(成功)

作成するインスタンスのname属性に対し、"Example User”を与えテストを成功させます。

user_test.rb
require "test_helper"

class UserTest < ActiveSupport::TestCase

	# name属性に"Example User"を与え、テストを成功させる。
  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "should be vaild with assert" do
    assert @user.valid?
  end

  test "should be vaild with assert predicate" do
    assert_predicate(@user, :valid?)
  end
end

rails test test/models/user_test.rbの実行結果です。

terminal
$ rails test test/models/user_test.rb 
Running 2 tests in a single process (parallelization threshold is 50)
Started with run options --seed 9459

  2/2: [=================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.05677s
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips

想定通り、どちらのテストも成功し上記の出力結果が得られました。

3.3 実行結果(失敗)

作成するインスタンスのname属性に対し、空白を与えテストを失敗させます。

user_test.rb
require "test_helper"

class UserTest < ActiveSupport::TestCase

	# name属性に空白を与え、テストを失敗させる。
  def setup
    @user = User.new(name: " ", email: "user@example.com")
  end

  test "should be vaild with assert" do
    assert @user.valid?
  end

  test "should be vaild with assert predicate" do
    assert_predicate(@user, :valid?)
  end
end

rails test test/models/user_test.rbの実行結果です。

terminal
$ rails test test/models/user_test.rb 
Running 2 tests in a single process (parallelization threshold is 50)
Started with run options --seed 40102

 FAIL UserTest#test_should_be_vaild_with_assert_predicate (0.10s)
        Expected #<User id: nil, name: " ", email: "user@example.com", created_at: nil, updated_at: nil> to be valid?.
        test/models/user_test.rb:13:in `block in <class:UserTest>'

 FAIL UserTest#test_should_be_vaild_with_assert (0.10s)
        Expected false to be truthy.
        test/models/user_test.rb:9:in `block in <class:UserTest>'

  2/2: [================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.10406s
2 tests, 2 assertions, 2 failures, 0 errors, 0 skips

想定通りどちらのテストも失敗となりましたが、異なるエラーメッセージが表示されました。エラーメッセージの箇所を抜粋すると、以下の通りです。

■ assert

Expected false to be truthy.

■ assert_predicate

Expected #<User id: nil, name: " ", email: "user@example.com", created_at: nil, updated_at: nil> to be valid?.

assertの場合、trueを期待しているのに対し、falseであるという決められたエラーメッセージが出力される。

assert_predicateの場合、指定したオブジェクトの属性情報と、to be valid?のようにテスト内容(述語メソッド)が出力される。

4. まとめ

assert_predicateメソッドの方が、テストが失敗したときにより具体的なエラーメッセージが提供されるため、何が間違っていたのかを理解しやすくなると感じました。

テスト結果は変わらないため、個人の好みやチームのコーディングルールによって決めるぐらいで良いかと思います。

5. 参考文献

1
1
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
1
1