Elixirのex_parameteriedでパラメタライズテストを行なう

はじめに

JavaJunitでもパラメタライズテストを行なうための機能が色々と用意されていますが、Elixirのでもex_parameterizedというライブラリがあり、このライブラリを用いると便利にパラメタライズドテストを行なうことができます。
ちょっと便利そうだったので使ってみたいと思います。

ex_parameterizedを使ってみる

ex_parameterizedはExUnitでパラメタライズドテストを行なうために作成されたライブラリです。
このライブラリを用いてパラメタライズドテストを記述してみます。

環境

動作環境は以下の通り

$ elixir --version
Erlang/OTP 22 [erts-10.7.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Elixir 1.10.3 (compiled with Erlang/OTP 21)

テスト用のアプリを用意する

まずは、mix newでプロジェクトを作成し、テスト用のモジュールを用意用意します。

defmodule ParameterizedTest.Calc do
  def sum(a, b) do
    a + b
  end
end

2つのintを受け取り計算結果を返すだけの簡単なモジュールです。
このモジュールに対してパラメタライズドテストを行います。

テストを記述する

まずは普通にテストを書いていきます。
(モジュール名をParameterizedTestにしてしまったのでテストモジュールがParameterizedTestTestになってしまった....)

defmodule ParameterizedTestTest do
  use ExUnit.Case
  alias ParameterizedTest

  test "greets the world" do
    assert ParameterizedTest.Calc.sum(1, 2) == 3
  end
end

ここまでは普通のテストです。ここにパラメタライズドテストを追加してみます。

ex_parameterizedの依存を追加する。

まずは、mix.exsに以下のように依存を追加してください。

  defp deps do
    [
      {:ex_parameterized, "~> 1.3.7"}
    ]
  end

パラメタライズドテストをかく

ex_parameterizedテストを行なうためには、test_with_paramsマクロを用います。

defmodule ParameterizedTestTest do
  use ExUnit.Case, async: true
  use ExUnit.Parameterized

  alias ParameterizedTest

  test "greets the world" do
    assert ParameterizedTest.Calc.sum(1, 2) == 3
  end

  test_with_params "param test",
                   fn a, b, expected ->
                     assert ParameterizedTest.Calc.sum(a, b) == expected
                   end do
    [
      {1, 2, 3},
      {3, 3, 6},
      {1, 2, 3}
    ]
  end
end

use ExUnit.Parameterizedでマクロを使えるようにします。
test_with_paramsは第一引数にテスト名、第二引数に実行するテストの関数を受け取ります。
そして、その後、doの後ろにタプルのリストを渡しているとことがありますが、これが実際にテストを行なう際のパラメータとなります。
パラメータはその順番通りに第二引数に渡した関数の引数として入力されます。つまり、 {a, b, expected}にそれぞれ対応するようになります。

それでは、テストを実行してみます。

$ mix test

Finished in 0.03 seconds
4 tests, 0 failures

Randomized with seed 425223

追加したのは一つのtest_with_paramsですが、テストが4回実行されているのがわかります。 今度は、わざと失敗させてみましょう。

 [
   {1, 2, 3},
   # 6 -> 7に変えたので、こいつは失敗する
   {3, 3, 7},
   {1, 2, 3}
 ]

mix testを叩いてみます。

$ mix test
...

  1) test 'param test': number of 1 (ParameterizedTestTest)
     test/parameterized_test_test.exs:11
     Assertion with == failed
     code:  assert ParameterizedTest.Calc.sum(a, b) == expected
     left:  6
     right: 7
     stacktrace:
       test/parameterized_test_test.exs:11: (test)



Finished in 0.03 seconds
4 tests, 1 failure

Randomized with seed 407811

何回目のパラメタライズドテストでどのように失敗したのかも教えてくれていますね。
なかなか便利そうです。

感想

はじめ、ExUnitというマクロの名前だったので、特に依存を追加しなくても良いのかなと勘違いしていました。