Test::Unit
Ruby の Test::Unit で具体的なデータを入れてテストをする方法です。いわゆるデータドリブンなテストってやつです。
解説ページ
とはいえ、すでに素晴らしい記事があります。以下のページを読むとだいたい分かってしまいます。
Ruby用単体テストフレームワークtest-unitでのデータ駆動テストの紹介 - 2013-01-23 - ククログ
具体例
しかしながら、試行錯誤をして手を動かさないと小一時間悩んでしまうかもしれません*1ので、具体例を挙げて補足してみます。上記ページと一緒に読むとよいです。
書くコードのまとめ
以下の点を踏まえてコードを書きます。
data
メソッド(特異メソッド)にブロックを渡すことでテストデータを定義するdata
メソッドはそのテストデータを利用する直前に実行されなければいけないdata
メソッドに渡すブロックは、「テストデータ」を「値」、そのテストデータに対して名付けた名前を「キー」とする
具体的なコード
コードを見た方が早いので載せます。このコードは以下のようにテストをしようとしています。
test_remove_linefeed
というテストメソッドのために直前でdata
メソッドを実行しテストデータを生成しているtest_remove_linefeed
メソッドにはdata
という引数を渡す(引数名はdata
でなければいけない)
data do linefeed_data = {} linefeed_data["cr_and_lf"] = [ "<br>", { linefeed: "\r\n", }, ] linefeed_data["lf"] = [ "<br>", { linefeed: "\r", }, ] linefeed_data["cr"] = [ "<br>", { linefeed: "\n", }, ] linefeed_data end def test_remove_linefeed(data) expected, test_linefeed = data assert_equal expected, test_linefeed[:linefeed].gsub(/(\r\n|\r|\n)/, "<br>") end
上記のテストデータでは、3種類のテストデータを定義しています。cr_and_lf
とlf
とcr
です。そして3つの種類のテストデータそれぞれで、「期待される結果(一つ目の要素)」と「テストに実際に投入するデータ(二つ目の要素)」を取っています。
「cr_and_lf
のテストデータ」の場合では、「期待される結果」は"<br>"
です。「テストに実際に投入するデータ」は{ linefeed: "\r\b" }
です。
3つの種類のテストデータをlinefeed_data
というハッシュにおさめています。この3つの種類のテストデータをひとつのパックにしています(data
メソッドにおいてブロックで渡している)。そのパックをtest_remove_linefeed
メソッドに引数で渡しています。
テストメソッド内での挙動
test_remove_linefeed
メソッドないでの挙動です。
まず1行目で引数のdata
を、「期待される結果」と「テストに実際に投入するデータ」の配列に分割しています。この分割により、それぞれの配列は次のような値を取ります。
expected
は["<br>", "<br>", "<br>"]
test_linefeed
は[{ linefeed: "\r\n" }, { linefeed: "\r" }, { linefeed: "\n" }]
となると二行目のassert_equal
の内容については自明かと思います。テストデータとして投入された"\r\n"
、"\r"
、"\n"
の3つの値がそれぞれ全て"<br>"
に置換されているかどうかをテストしています。上記のテストはパスすることが確認できます。
補足
テストデータの構成
上記の例では「3種類のテストデータ」を定義する際に「期待される結果」と「テストデータ」を代入していました。しかし、「期待される結果」は省略することが可能です。
テストデータの「名前」
上記の例におけるcr_and_lf
、lf
、cr
という名前はコード上で扱うことはありません*2。テストデータはdata
にパックされ、コード上で扱う場合は「配列」になるためです。
ではどのような場面でこの命名が現れるのかというと、テストのログが出力されるときです。たとえばエラーで以下のような形で表示されます。
======================================================================================================= Error: test_remove_linefeed[cr_and_lf](TestMyClass): TypeError: no implicit conversion of String into Integer ...... ...... ...... =======================================================================================================