Spock概要
Groovy言語で書くことが出来る単体テストのテスティングフレームワーク。
私が約1,5年間単体テストでSpockとJUnitを使用してきたため備忘録的に残す。
単体テストのテスティングフレームワークで有名なJUnitと比べて個人的には使いやすい。
Spockの基本的なルール
下記のブロックごとにテストコードを記述していく。
ブロック | フェーズ | 概要 |
---|---|---|
setup/given | セットアップ | 最初に記述するブロックで「前提対象を記述」 |
when | シミュレート | 「テスト対象の振る舞いを記述」thenと併用 |
then | アサーション | whenの振る舞いの「アサーションを記述」 |
expect | シミュレートアサーション | when/thenをまとめたもの※あまり使わない |
cleanup | クリーンアップ | フィーチャー内でリソース解放などの「クリーンアップが必要な場合に記述」 |
where | - | データドリブンテストを行うためのブロック(パラメタライズテスト) |
参考コードを実際に書いてみる
前提:
下記のDTOクラスの各フィールド項目が取得できるかテストを行う。
◆DTOクラス
public class dogDto {
private Long dogId;
private String DogName;
private String DogBreed;
}
◆テストコード
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification
import spock.lang.Unroll
@SpringBootTest
class dogDaoImplSTest extends Specification {
@Autowired
DogDaoImpl dao
def selector = new DogDtoSelector()
def setup() {
selector.ownerId = 101L // setupで設定した項目は全てのテストに適用される
}
@Unroll
// パラメタライズテストを行う際には@Unrollアノテーションを付与
def "複数件取得 #testCase"() { // #の後にwhere区のパラメータを設定することでテスト名を動的に変化させることが出来る
given: //spockSTestのみに反映される前提条件を記述
selector.dogId = pDogId
when: //テスト対象の振る舞いを記述、今回はdao層からselectメソッドを叩く
def actual = dao.select(selector)
then: // 上記のwhenで指定した振る舞いに対する結果をアサーション
assert actual.size() == 2
actual[pSize].with {
assert dogId == eDogId
assert dogName == eDogName
assert dogBreed == eDogBreed
}
where: //ここでパラメタライズの設定を行う、今回は2テストパターンが実行される
testCase | pSize | pDogId || eDogId | eDogName | eDogBreed
"ドッグIDが101の犬情報" | 0 | 1L || 1L | "moku" | "pomeranian"
"ドッグIDが102の犬情報" | 1 | 2L || 2L | "mugi" | "pekingese"
}
}
メリット
・直感的でとても分かりやすい
・javaコードを書くことが出来る
・Assert機能が強力でエラー箇所の特定が容易
・Mock機能が標準搭載されており、記述方法が分かりやすい
デメリット
・privateにもアクセスできてしまう
まとめ
個人的にはJUnitよりも直感的で分かりやすいテストが書けると思っています。
分かりやすいほど撃ち漏らしが発生しにくいと考えているので今後自分でテスティングフレームワークを選定する際にはSpockを使用したい。
ですが、JUnitの方がSpringとの親和性が高いみたいなので要検討になりそうです。
他にもMockの方法等も記述したいですが今回はこれで閉じさせていただきます。
初めての投稿で、エンジニアとしても未熟なため未熟なため誤りがあればご指摘いただけますと幸いです。
今後ともよろしくお願いします。