Rails refute と assert_not を使ってみる

前回、refuteassert_notはエラーメッセージが違うことがわかった。

masuyama13.hatenablog.com

assert_not_equalなどは Minitest のrefute_notなどのエイリアス(別名)なので、assert_not_equalを呼び出すとrefute_notが実行される。つまり動作としては全く同じである。

一方、assert_notrefuteエイリアスではなく、調べた限りではオーバーライドもされていない。ということは、Minitest を継承している Rails のテスト(ActiveSupport)において、refuterefuteで使えるはずだ。

ということで、実際にやってみる。

エラーメッセージを比較

わざと失敗するテストを書いて、エラーメッセージを比べてみた。

blog.rb

class Blog
end

blog_test.rb

require "minitest/autorun"
require "active_support/all"
require "./blog"

class BlogTest < ActiveSupport::TestCase
  test "Blogクラスのオブジェクトを作れない(refute)" do
    refute Blog.new
  end

  test "Blogクラスのオブジェクトを作れない(assert_not)" do
    assert_not Blog.new
  end
end

refute A / assert_not A:Aが偽であればパスする。

Blog.newは真になるはずなので、テストは失敗する。

実行結果

$ ruby blog_test.rb 
Run options: --seed 13819

# Running:

F

Failure:
BlogTest#test_Blogクラスのオブジェクトを作れない(refute) [blog_test.rb:7]:
Expected #<Blog:0x00007f9da82c2a20> to not be truthy.


rails test blog_test.rb:6

F

Failure:
BlogTest#test_Blogクラスのオブジェクトを作れない(assert_not) [blog_test.rb:11]:
Expected #<Blog:0x00007f9da82c1440> to be nil or false


rails test blog_test.rb:10



Finished in 0.001397s, 1431.6393 runs/s, 1431.6393 assertions/s.
2 runs, 2 assertions, 2 failures, 0 errors, 0 skips

refuteのエラーメッセージ

BlogTest#test_Blogクラスのオブジェクトを作れない(refute) [blog_test.rb:7]:
Expected #<Blog:0x00007f9da82c2a20> to not be truthy.

assert_notのエラーメッセージ

BlogTest#test_Blogクラスのオブジェクトを作れない(assert_not) [blog_test.rb:11]:
Expected #<Blog:0x00007f9da82c1440> to be nil or false

予想通りだ!

それぞれのコードに書かれたエラーメッセージであることが確認できた。やっとrefuteassert_notを理解できた気がする。

refute メソッドのコード(Minitest)

  def refute test, msg = nil
    msg ||= message { "Expected #{mu_pp(test)} to not be truthy" }
    assert !test, msg
  end

minitest/assertions.rb at master · seattlerb/minitest · GitHub

assert_not メソッドのコード

  def assert_not(object, message = nil)
    message ||= "Expected #{mu_pp(object)} to be nil or false"
    assert !object, message
  end

rails/assertions.rb at 77932446895bd70f38a3aaa1ab288bf8a7b7142c · rails/rails · GitHub

すごい遠回りしてるかもしれないけどなんか楽しかった。

ちなみに、Rails では refute ではなくassert_not を使用した方がよさそう。

refuteではなくassert_notを使用すること。
Ruby on Rails に貢献する方法 - Railsガイド

さて、コードジャンプのやり方を調べよう…。