[Grails (グレイルズ)] spock の where を使いパラメタ化してテストの冗長化を無くす

単体テストは、同じコードをコピペして数十もしくは、数百ケースといったテストを書く場合がある。
こんなとき、
「インターフェース変わったらどうしよう」
と心配になると思う。
単体テストでも、コードを少なくしてインターフェースに変更があっても軽微の修正ですませるようにしたい。

そんな時は、spockを使って単体テストでありがちな、コードの冗長化は where を使って無くすことにする。

javaからも使えるので、Grailsに限らず単体テストの冗長化に頭を悩ませている人は spock を使って欲しい。

単純な値の場合

「|」 で パラメタ化

のように、渡す値と結果を書いておく。

これを使って以下のように定義する

このテストを実行すると、4個のテストが行われる。
where: で定義した1行単位に処理が行わる。
コード中はそれぞれ、 address,name,age,testfor が変数として参照できる。

where: 無しだと、4つのテスト分それぞれメソッドを分けてかく必要がある。冗長化してメンテナンスが面倒になる。巨大なテストソースにありがちな構造。

コード中のキーワードの説明

  • @Unroll
  • このアノテーションがないと、テスト実行時に1つのテストとして扱われる。その場合失敗時にどのケースで失敗したか確認できない。
    @Unrollを付けることを推奨。また、 #testfor のようにメソッド名にパラメタが使用できる。

  • setup:
  • ここに、試験に必要なデータをセットする。例えば、予め数件のレコードを入れておいて、正しく取得できるかのテストをしたい時用などデータを用意する場合に使う。

  • when:
  • 実際にテストを行う。

  • then:
  • テストの結果を確認。

単純なデータではなく、オブジェクトなどを渡したい場合

オブジェクトを渡す場合は、配列にして渡してあげるとよい。

テストソースはこのようになる。

dataServcie.list の結果としては
[list : データのリスト, total : 全件数]
が入っている。

このテストは、 Usersystem, admin, user の 3パターンでテストして結果としてリストの件数と、データの全件数を取得できるかチェックしている。

where: では、それぞれ行うテストのデータ(user)と結果(listsize, totla)、そして表示用(testfor)を用意している。

where: でオブジェクトを共有して使いまわす

where: で、ひとつのデータを共有して他のテストでも使いまわす場合は、クラスメンバとして宣言して
@Shared
を付ける。
「|」でパラメタ化も出来る。
クラスメンバとして宣言

setupSpec で初期化。 ちなみに、setupSpec はテスト中の初期化で一度だけ呼ばれる。 setup メソッドはテスト毎に呼ばれる。

そして、パラメタ化で使う

「|」と配列のパラメタ化がごっちゃ混ぜになってもよい。




[Spring Batch] java.lang.IllegalStateException: If a skip limit is provided then skippable exceptions must also be specified というエラー

以下のようなエラー。そのまま指示通りに従えばOK。

chunkskip-limit を付け加えたらどのような例外時にスキップするか指定する必要がある。 以下の例は、java.lang.Exception を継承する例外全てスキップ対象とする