Ruby
Rails
unittest
minitest

minitestのオススメ設定調べてみた(アサーション編)

More than 3 years have passed since last update.

前回minitestのオススメ設定を紹介させていただきましたが

アサーションをどう記述するかに関しては、関連するgemが多すぎて記事としてまとめられませんでしたので

別記事として紹介させていただきます

どの様にテストを記述したいのか、という用途別で敢えて分類を行うならば

下の4択のいずれかなのではないかな、と思います


  1. assert_equalを拡張していく、power assertを取り込んでいく

  2. rspecに近づける

  3. must_equalに寄せていく

  4. shouldaに近づける

以前からshouldaを使ってテストを記述してきた人じゃないなら、shouldaの書式に近づける意味は無いので、実質三択ですがそれぞれの用途別にインストールするgemを紹介させていただきましょう

今回は、動作確認は、以下の環境でチェックしています


  • rails 4.1.8

  • minitest 5.4.0


assert_equalで拡張を続ける

test/unitから脈々と受け継がれているassert_equalでテストを記述したいという場合は、こちらを使うべきでしょう

利点としては、次のようなものが挙げられるでしょうか


  • 他の言語でも、スタンダードで使われている書式なので文化的にも学習コストが低い

  • minitestの標準の書式の一つ

実際の書式としては、条件が真であるかというのを調べるassert、条件が偽であるかを調べるrefute関数と、その派生関数を使ってテストを行います

  assert true              # 実行結果が真なのかをチェック

assert_equal true, true # 2つの値が同じかどうかをチェック
assert_empty [] # 中身が空かどうかをチェック
refute false # 実行結果が偽なのかをチェック
refute_equal true, false # 実行結果が同じ値にならないのをチェック

インストールするときは以下をコピペが楽でしょうか

group :test do

gem 'minitest-ar-assertions', "0.1.1", :require => 'minitest_activerecord_assertions'
gem "minitest-power_assert", "0.0.3"
end


minitest-ar-assertions

https://github.com/steventux/minitest-ar-assertions

assert_association Comment, :has_many, :likes, :as => :likeable

assert_association Post, :has_many, :likes => :as => :likeable
assert_association Like :belongs_to, :likeable

active_recordのhas_oneやhas_many、belongs_to等の関連を簡潔に書ける拡張です。

rspecでも同様の機能がありますね


minitest-power_assert

https://github.com/hsbt/minitest-power_assert

it "金額が指定通り" do

assert { @amount == 100 }
end

書式は 「assert { テスト書式 }」という感じで、テストを記述していくだけでいいです。

ブロックの実行結果の真偽でテストの実行結果をチェックします

テストに失敗をすると、下の様に実行結果の内部の変数それぞれを分解して表示してくれるので、失敗したテストの中身を見るためにブレークポイントを貼ったりinspectメソッドで各変数を表示して原因を探さなくて良くなります

    assert { @amount == 100 }

| |
| false
55

オブジェクトの場合も、inspectメソッドを使った時の様に内部を表示してくれます

さらに詳しくはテスト用ライブラリ power-assertを参照していただくと分かりやすいのですが

Groovy から出てきたpower assertと同等の機能を実現するgemですね。


  1. 既存のassertの文法にかなり自然に融和して

  2. 書式が簡潔で覚えやすい

  3. エラーを今までよりも詳細に表示してくれる

という感じなので、基本power assertの書式に従って「minitest-ar-assertions」の様に、power assertの力を借りない方が簡潔に書ける場合のみ、その力を借りるというスタイルが良いと思います


must_equalに寄せていく

minitestには下の書式のように、shouldではなく、mustでオブジェクト間をつないでいくメソッドが標準で備わっています

true.must_equal true  # 2つの値が同じかどうかをチェック

true.wont_equal false # 2つの値が同じでないかをチェック

下の2つのgemはそれに対して書式の拡張を行っていくものですね


minitest-great_expectations

書式に、配列やハッシュのパターンマッチ機能を追加します

下の書式の様に記述しますが、一目で実用性が実感できます

    [1, 2, 3].must_equal_contents [3, 2, 1]

[1, 2, 3].must_include_all [1, 2]
{ :a => 1, :b => 2 }.must_equal_hash( { :b => 2, :a => 1 } )


rspecに近づける

今まで慣れ親しんだrspecに出来るだけ書式を近づけたい、という場合にはこちらの書式を使うのが一番よいでしょう

※ 本当はminitest-should_syntaxの方が便利なのですが、最新のrails環境に追随できていないまま2年更新が止まっていました


minitest-shouldify

rspecのshouldに似たshould_equalなどのメソッドを生やします

"bar".should_equal "bar"

"bar".should_not_equal "baz"


minitest-spec-expect

rspecのexpect関数に類似した仕様のexpect関数を追加します

expect(1 + 1).to_equal 2     # 値が一致しているかどうかをチェック

expect(1 + 1).to_not_equal 3 # 一致していないかをチェック


おまけ: context関数の作成

describeの替わりにcontextが使いたい場合には

これ動かなかったので、test_helper.rbに

自前でモンキーパッチングを行って、contextメソッドは追加しました

minitest-spec-contextというgemもあるのですが、2年ほど更新もされておらず、現在の環境では動かなくなっていました

module Kernel

alias_method :context, :describe
end


shouldaに近づける

これはshouldaに記法を寄せるためのgemですね

一応、簡単にサンプルを出させていただきますが

実際のコードはこんな感じになります

  context "Something else" do

setup do
@something = "nothing"
end

should "be nothing" do
assert_equal "nothing", @something
end

end

rspecの場合は次の3つの関数で文脈を作りますが


  • describe

  • before

  • it

同じものを次の3つで行っている感じですね


  • context

  • setup

  • should

正直、既にshouldaに慣れている人以外には

このスタイルの使い道は見当たらないのではないでしょうか


まとめ

さて、4種類、書式を紹介しましたが

私の方では、現状はassert equalとpower assertを併用しながら、簡潔に書ける方をケースバイケースで使い分けています

どれを選ぶかは本当に好みで決まるので、パッと見て気に入ったものから順番に試していくのがいいでしょう