Spring Boot + npm + Geb で入力フォームを作ってテストする ( その64 )( 入力画面3を作成する6、@SpringBootTest のテストは Spock+Groovy より JUnit4+Groovy の方が速い? )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- InquiryInputControllerTest で1件だけ確認画面の実装待ちで未実装だったテストを実装します。
- @SpringBootTest がクラスに付加されているテストは Spock+Groovy で書くより JUnit4+Groovy で書いた方が速いように見えたので、その検証をしてみます。
参照したサイト・書籍
- Spock Framework Reference Documentation - Interaction Based Testing
http://spockframework.org/spock/docs/1.1/interaction_based_testing.html
目次
- InquiryInputControllerTest クラスで未実装のテストを実装する
@SpringBootTest
を付けるテストの場合 Spock+Groovy より JUnit4+Groovy の構成の方がテストの実行は速いのか?- 次回は。。。
手順
InquiryInputControllerTest クラスで未実装のテストを実装する
src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryInputControllerTest.groovy を以下のように変更します。
@Test void "項目全てに入力して前の画面へ戻るボタンをクリックすると入力画面2へ戻り、次へ戻るボタンを押して入力画面3へ戻ると以前入力したデータがセットされて表示される"() { .......... } @Test void "項目全てに入力して次へボタンをクリックすると確認画面へ遷移し、修正するボタンを押して入力画面3へ戻ると以前入力したデータがセットされて表示される"() { // JUit4+Groovy でテストを必ず失敗させるには以下のように書く // expect: // assert false, "確認画面を実装してからテストを作成する" when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする" MvcResult result = mockMvc.perform( TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/03")) and: "入力画面3で項目全てに入力して「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=next", inquiryInput03Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/confirm")) then: "確認画面で「修正する」ボタンをクリックすると、入力画面3に戻り以前入力したデータがセットされて表示される" mockMvc.perform(get("/inquiry/input/03").session(session)) .andExpect(status().isOk()) .andExpect(html("select[name='type1'] option[selected]").val(inquiryInput03Form_001.type1)) .andExpect(html("input[name='type2'][checked='checked']").count(3)) .andExpect(html("#inquiry").val(inquiryInput03Form_001.inquiry)) .andExpect(html("input[name='survey'][checked='checked']").count(8)) } @Test void "入力チェックエラーのあるデータで「次へ」ボタンをクリックするとIllegalArgumentExceptionが発生する"() { .......... }
void "項目全てに入力して次へボタンをクリックすると確認画面へ遷移し、修正するボタンを押して入力画面3へ戻ると以前入力したデータがセットされて表示される"() { ... }
のテストを実装します。
InquiryInputControllerTest クラスのテストを全て実行して成功することを確認します。
InquiryConfirmControllerTest クラスと比較するとテストの実行が速かったです。比較してみます。
InquiryInputControllerTest クラスのテストを3回実行すると以下の結果ですが、
回数 | かかった時間 |
---|---|
1回目 | 3s 991ms |
2回目 | 4s 500ms |
3回目 | 4s 142ms |
InquiryConfirmControllerTest クラスのテストを3回実行すると以下の結果でした。
回数 | かかった時間 |
---|---|
1回目 | 23s 558ms |
2回目 | 23s 543ms |
3回目 | 23s 649ms |
JUnit4+Groovy の方が速そうですね。
@SpringBootTest
を付けるテストの場合 Spock+Groovy より JUnit4+Groovy の構成の方がテストの実行は速いのか?
SurveyOptionsHelperTest クラスのテストで検証してみます。SurveyOptionsHelperTest クラスのテストは、
- Spock+Groovy で書いている。
@SpringBootTest
が付いている。
という内容で、3回実行してみると以下の結果でした。
回数 | かかった時間 |
---|---|
1回目 | 20s 117ms |
2回目 | 18s 941ms |
3回目 | 19s 423ms |
SurveyOptionsHelperTest クラスを JUnit4+Groovy で書き直します。
package ksbysample.webapp.bootnpmgeb.helper.db import ksbysample.webapp.bootnpmgeb.entity.SurveyOptions import org.junit.Test import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.junit4.SpringRunner import static org.assertj.core.api.Assertions.catchThrowable @RunWith(SpringRunner) @SpringBootTest class SurveyOptionsHelperTest { @Autowired private SurveyOptionsHelper soh @Test void "登録されているグループ名を指定してselectItemListメソッドを呼ぶとリストが取得できる"() { setup: List<SurveyOptions> surveyOptionsList = soh.selectItemList("survey") expect: assert surveyOptionsList.size() == 8 assert surveyOptionsList[0].itemValue == "1" assert surveyOptionsList[0].itemName == "選択肢1だけ長くしてみる" assert surveyOptionsList[7].itemValue == "8" assert surveyOptionsList[7].itemName == "8" } @Test void "登録されていないグループ名を指定してselectItemListメソッドを呼ぶとIllegalArgumentExceptionがthrowされる"() { setup: Throwable thrown = catchThrowable({ List<SurveyOptions> surveyOptionsList = soh.selectItemList("notexists") }) expect: assert thrown instanceof IllegalArgumentException assert thrown.message == "指定されたグループ名のデータは登録されていません" } }
- クラスに
@RunWith(SpringRunner)
アノテーションを付加します。 extends Specification
を削除します。- 各テストメソッドに
@Test
アノテーションを付加し、def
→void
に変更します。 expect:
の下で結果を検証している処理にassert
を付けます。void "登録されていないグループ名を指定してselectItemListメソッドを呼ぶとIllegalArgumentExceptionがthrowされる"() { ... }
テストメソッド内でsoh.selectItemList("notexists")
を呼び出している部分をThrowable thrown = catchThrowable({ ... })
で囲みます。結果の検証方法も groovy の形式に書き直します。
変更後に3回実行してみると以下の結果でした。やっぱり速いですね。
回数 | かかった時間 |
---|---|
1回目 | 458ms |
2回目 | 475ms |
3回目 | 504ms |
今度は Spock+Groovy に戻してから、@SpringBootTest
は外して適宜 Stub を使う方法で書き直してみます。
package ksbysample.webapp.bootnpmgeb.helper.db import ksbysample.webapp.bootnpmgeb.dao.SurveyOptionsDao import ksbysample.webapp.bootnpmgeb.entity.SurveyOptions import spock.lang.Specification class SurveyOptionsHelperTest extends Specification { SurveyOptionsDao surveyOptionsDao SurveyOptionsHelper soh def setup() { surveyOptionsDao = Stub(SurveyOptionsDao) { selectByGroupName("survey") >> [ [groupName: "survey", itemValue: "1", itemName: "選択肢1だけ長くしてみる", itemOrder: 1], [groupName: "survey", itemValue: "2", itemName: "選択肢2", itemOrder: 2], [groupName: "survey", itemValue: "3", itemName: "選択肢3", itemOrder: 3], [groupName: "survey", itemValue: "4", itemName: "選択肢4", itemOrder: 4], [groupName: "survey", itemValue: "5", itemName: "選択肢5が少し長い", itemOrder: 5], [groupName: "survey", itemValue: "6", itemName: "選択肢6", itemOrder: 6], [groupName: "survey", itemValue: "7", itemName: "選択肢7", itemOrder: 7], [groupName: "survey", itemValue: "8", itemName: "8", itemOrder: 8] ] selectByGroupName("notexists") >> [] } soh = new SurveyOptionsHelper(surveyOptionsDao) } def "登録されているグループ名を指定してselectItemListメソッドを呼ぶとリストが取得できる"() { setup: List<SurveyOptions> surveyOptionsList = soh.selectItemList("survey") expect: surveyOptionsList.size() == 8 surveyOptionsList[0].itemValue == "1" surveyOptionsList[0].itemName == "選択肢1だけ長くしてみる" surveyOptionsList[7].itemValue == "8" surveyOptionsList[7].itemName == "8" } def "登録されていないグループ名を指定してselectItemListメソッドを呼ぶとIllegalArgumentExceptionがthrowされる"() { when: List<SurveyOptions> surveyOptionsList = soh.selectItemList("notexists") then: def e = thrown(IllegalArgumentException) e.getMessage() == "指定されたグループ名のデータは登録されていません" } }
- クラスに付けている
@SpringBootTest
、及びフィールドに付けている@Autowired
を削除します。 SurveyOptionsDao surveyOptionsDao
を追加します。def setup() { ... }
を追加し、surveyOptionsDao の Stub を生成してから soh のインスタンスを生成する処理を記述します。
変更後に3回実行してみると以下の結果でした。JUnit4+Groovy より時間がかかっているように表示されましたが、実際にテストが終了する速度はこちらの方が速いです。IntelliJ IDEA は何の時間を表示しているのだろうという疑問が。。。
回数 | かかった時間 |
---|---|
1回目 | 768ms |
2回目 | 840ms |
3回目 | 970ms |
次回は。。。
利用しているライブラリを一通りバージョンアップしてから Geb を利用したテストを作成します。
履歴
2018/07/11
初版発行。