[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 メソッドはテスト毎に呼ばれる。

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

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




[Grails (グレイルズ)] integration テストで、Write operations are not allowed のようなエラー

Integration テストで以下のようなエラーが出た場合

原因は、テスト用に生成したドメインオブジェクトにエラーがあります。
生成したオブジェクトの errors を確認してみて下さい。
errors については以下を参考にして下さい。
[Grails (グレイルズ)] DB(ドメイン)にデータが入らないよ