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

前回[minitestのオススメ設定](http://qiita.com/baban@github/items/88e18a784eaf39efb6e0
)を紹介させていただきましたが
アサーションをどう記述するかに関しては、関連する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関数と、その派生関数を使ってテストを行います

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


* [minitest-ar-assertions](https://github.com/steventux/minitest-ar-assertions)
* [minitest-power_assert](https://github.com/hsbt/minitest-power_assert)

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

```rb
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

```rb
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

```rb
it "金額が指定通り" do
  assert { @amount == 100 }
end
```

書式は 「assert { テスト書式 }」という感じで、テストを記述していくだけでいいです。
ブロックの実行結果の真偽でテストの実行結果をチェックします

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

        assert { @amount == 100 }
                 |       |
                 |       false
                 55


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

さらに詳しくは[テスト用ライブラリ power-assert](http://www.slideshare.net/t_wada/power-assert-jsojisan2)を参照していただくと分かりやすいのですが
Groovy から出てきたpower assertと同等の機能を実現するgemですね。

1. 既存のassertの文法にかなり自然に融和して
2. 書式が簡潔で覚えやすい
3. エラーを今までよりも詳細に表示してくれる

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

## must_equalに寄せていく

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

```rb
true.must_equal true  # ２つの値が同じかどうかをチェック
true.wont_equal false # ２つの値が同じでないかをチェック
```

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

* [minitest-great_expectations](https://github.com/mceachen/minitest-great_expectations)

### minitest-great_expectations

書式に、配列やハッシュのパターンマッチ機能を追加します
下の書式の様に記述しますが、一目で実用性が実感できます

```rb
    [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-shouldify](https://github.com/blowmage/minitest-shouldify)
* [minitest-spec-expect](https://github.com/davejachimiak/minitest-spec-expect)
* [rspec2minitest](https://github.com/cschramm/rspec2minitest)

※ 本当は[minitest-should_syntax](https://github.com/rstacruz/minitest-should_syntax)の方が便利なのですが、最新のrails環境に追随できていないまま２年更新が止まっていました

### minitest-shouldify

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

```rb
"bar".should_equal "bar"
"bar".should_not_equal "baz"
```

### minitest-spec-expect

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

```rb
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年ほど更新もされておらず、現在の環境では動かなくなっていました

```rb
module Kernel
  alias_method :context, :describe
end
```

## shouldaに近づける

これは[shoulda](https://github.com/thoughtbot/shoulda)に記法を寄せるためのgemですね

* [minitest_should](https://github.com/citrus/minitest_should)

一応、簡単にサンプルを出させていただきますが
実際のコードはこんな感じになります

```rb
  context "Something else" do

    setup do
      @something = "nothing"
    end

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

  end
```

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

* describe
* before
* it

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

* context
* setup
* should

正直、既にshouldaに慣れている人以外には
このスタイルの使い道は見当たらないのではないでしょうか

## まとめ

さて、4種類、書式を紹介しましたが
私の方では、現状はassert equalとpower assertを併用しながら、簡潔に書ける方をケースバイケースで使い分けています
どれを選ぶかは本当に好みで決まるので、パッと見て気に入ったものから順番に試していくのがいいでしょう