かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その27 )( 入力画面2を作成する6 )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その26 )( 入力画面2を作成する5 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 入力画面2の作成
    • サーバ側のテストを作成します。前回からの続きです。

参照したサイト・書籍

目次

  1. InquiryInputController クラスのテストを変更する
  2. build タスクを実行したら PMD でエラーが出たので pmd-project-rulesets.xml と InquiryInput02FormValidator.java を修正する
  3. 次回は。。。

手順

InquiryInputController クラスのテストを変更する

src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryInputControllerTest.groovy の以下の点を変更します。groovy だと SnakeYAML を使わなくてもテストデータを分かりやすく書けることに今更ながら気付いたので、今回は SnakeYAML は使用せずテストデータはテストクラス内に直接記述します。

@RunWith(Enclosed)
class InquiryInputControllerTest {

    ..........

    @RunWith(SpringRunner)
    @SpringBootTest
    static class 入力画面2のテスト {
        private InquiryInput01Form inquiryInput01Form_001 =
                (InquiryInput01Form) new Yaml().load(getClass().getResourceAsStream("InquiryInput01Form_001.yaml"))
        private InquiryInput02Form inquiryInput02Form_001 = new InquiryInput02Form(
                zipcode1: "102"
                , zipcode2: "0072"
                , address: "東京都千代田区飯田橋1-1"
                , tel1: "03"
                , tel2: "1234"
                , tel3: "5678"
                , email: "taro.tanaka@sample.co.jp")

        @Autowired
        private WebApplicationContext context

        MockMvc mockMvc

        @Before
        void setup() {
            mockMvc = MockMvcBuilders.webAppContextSetup(context)
                    .build()
        }

        @Test
        void "初期表示時は画面の項目には何もセットされない"() {
            expect:
            mockMvc.perform(get("/inquiry/input/02"))
                    .andExpect(status().isOk())
                    .andExpect(html("#zipcode1").val(""))
                    .andExpect(html("#zipcode2").val(""))
                    .andExpect(html("#address").val(""))
                    .andExpect(html("#tel1").val(""))
                    .andExpect(html("#tel2").val(""))
                    .andExpect(html("#tel3").val(""))
                    .andExpect(html("#email").val(""))
        }

        @Test
        void "項目全てに入力して前の画面へ戻るボタンをクリックすると入力画面1へ戻り、次へ戻るボタンを押して入力画面2へ戻ると以前入力したデータがセットされて表示される"() {
            when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする"
            MvcResult result = mockMvc.perform(
                    TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrlPattern("**/inquiry/input/02"))
                    .andReturn()
            MockHttpSession session = result.getRequest().getSession()

            and: "入力画面2で項目全てに入力して「前の画面へ戻る」ボタンをクリックする"
            mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=back", inquiryInput02Form_001)
                    .session(session))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrlPattern("**/inquiry/input/01"))

            and: "入力画面1で「次へ」ボタンをクリックする"
            mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001)
                    .session(session))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrlPattern("**/inquiry/input/02"))

            then: "入力画面2が以前入力したデータがセットされて表示される"
            mockMvc.perform(get("/inquiry/input/02").session(session))
                    .andExpect(status().isOk())
                    .andExpect(html("#zipcode1").val(inquiryInput02Form_001.zipcode1))
                    .andExpect(html("#zipcode2").val(inquiryInput02Form_001.zipcode2))
                    .andExpect(html("#address").val(inquiryInput02Form_001.address))
                    .andExpect(html("#tel1").val(inquiryInput02Form_001.tel1))
                    .andExpect(html("#tel2").val(inquiryInput02Form_001.tel2))
                    .andExpect(html("#tel3").val(inquiryInput02Form_001.tel3))
                    .andExpect(html("#email").val(inquiryInput02Form_001.email))
        }

        @Test
        void "項目全てに入力して次へボタンをクリックすると入力画面3へ遷移し、前の画面へ戻るボタンを押して入力画面2へ戻ると以前入力したデータがセットされて表示される"() {
            when: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする"
            MvcResult result = mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrlPattern("**/inquiry/input/03"))
                    .andReturn()
            MockHttpSession session = result.getRequest().getSession()

            and: "入力画面3で「前の画面へ戻る」ボタンをクリックする"
            mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=back", inquiryInput01Form_001)
                    .session(session))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrlPattern("**/inquiry/input/02"))

            then: "入力画面2が以前入力したデータがセットされて表示される"
            mockMvc.perform(get("/inquiry/input/02").session(session))
                    .andExpect(status().isOk())
                    .andExpect(html("#zipcode1").val(inquiryInput02Form_001.zipcode1))
                    .andExpect(html("#zipcode2").val(inquiryInput02Form_001.zipcode2))
                    .andExpect(html("#address").val(inquiryInput02Form_001.address))
                    .andExpect(html("#tel1").val(inquiryInput02Form_001.tel1))
                    .andExpect(html("#tel2").val(inquiryInput02Form_001.tel2))
                    .andExpect(html("#tel3").val(inquiryInput02Form_001.tel3))
                    .andExpect(html("#email").val(inquiryInput02Form_001.email))
        }

        @Test
        void "入力チェックエラーのあるデータで「前の画面へ戻る」ボタンをクリックするとIllegalArgumentExceptionが発生する"() {
            setup: "入力チェックエラーになるデータを用意する"
            inquiryInput02Form_001.zipcode1 = "1"

            expect: "入力画面2の「前の画面へ戻る」ボタンをクリックする"
            Throwable thrown = catchThrowable({
                mockMvc.perform(
                        TestHelper.postForm("/inquiry/input/02?move=back", inquiryInput02Form_001))
                        .andExpect(status().isOk())
            })
            assertThat(thrown.cause).isInstanceOf(IllegalArgumentException)
        }

        @Test
        void "入力チェックエラーのあるデータで「次へ」ボタンをクリックするとIllegalArgumentExceptionが発生する"() {
            setup: "入力チェックエラーになるデータを用意する"
            inquiryInput02Form_001.zipcode1 = "1"

            expect: "入力画面2の「次へ」ボタンをクリックする"
            Throwable thrown = catchThrowable({
                mockMvc.perform(
                        TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001))
                        .andExpect(status().isOk())
            })
            assertThat(thrown.cause).isInstanceOf(IllegalArgumentException)
        }

    }

}
  • 入力画面2のテスト クラスを追加します。

テストを実行して全て成功することを確認します。

f:id:ksby:20171015190914p:plain

build タスクを実行したら PMD でエラーが出たので pmd-project-rulesets.xml と InquiryInput02FormValidator.java を修正する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、PMD で何件かメッセージが出ました。

f:id:ksby:20171015194130p:plain

build/reports/pmd/main.xml を見ると以下の3種類の Rule が原因でした。

ただし https://pmd.github.io/pmd-5.8.1/pmd-java/rules/java/codesize.html#ModifiedCyclomaticComplexity を見ると Deprecated の表示がありますね。前に PMD の設定ファイルを作成していた時には気づきませんでした。Code Size の Rules にいくつか Deprecated が表示されていますが pmd-project-rulesets.xml で除外していなかったので、pmd-project-rulesets.xml を修正して除外するようにします。

config/pmd/pmd-project-rulesets.xml の以下の点を変更します。

    <rule ref="rulesets/java/codesize.xml">
        <exclude name="CyclomaticComplexity"/>
        <exclude name="StdCyclomaticComplexity"/>
        <exclude name="ModifiedCyclomaticComplexity"/>
        <exclude name="TooManyMethods"/>
    </rule>
  • 以下の行を追加します。
    • <exclude name="CyclomaticComplexity"/>
    • <exclude name="StdCyclomaticComplexity"/>
    • <exclude name="ModifiedCyclomaticComplexity"/>

また https://pmd.github.io/pmd-5.8.1/pmd-java/rules/java/basic.html#CollapsibleIfStatements の方は src/main/java/ksbysample.webapp.bootnpmgeb/web/inquiry/form/InquiryInput02FormValidator.java の以下の箇所でエラーが出ていたのですが(if 文をネストさせずに && でつなげて1行で書くようにという内容でした)、

            // メールアドレスが入力されていたら入力チェックする
            if (StringUtils.isNotEmpty(email)) {
                if (!EmailValidator.validate(email)) {
                    errors.reject("InquiryInput02Form.email.Invalid");
                }
            }

ここは今の実装のままにしたいので、@SuppressWarnings を指定してメッセージが出ないようにします。

    @SuppressWarnings({"PMD.CollapsibleIfStatements", "PMD.ConfusingTernary"})
    private void checkTelAndEmail(boolean ignoreCheckRequired, String tel1, String tel2, String tel3, String email
            , Errors errors) {
  • @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ConfusingTernary"})@SuppressWarnings({"PMD.CollapsibleIfStatements", "PMD.ConfusingTernary"}) に変更します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、今度は "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20171015200528p:plain

次回は。。。

入力画面3の実装に進む前に1~2件書きたいことができたのでそれを書きます(たぶん)。

その後に入力画面1のテストを Geb で作成します。元々今回の記事を書いている理由が Geb のテストの書き方を知りたかったからなんですよね。。。(もうその27ですが)

その後で入力画面3の実装に進みます。

履歴

2017/10/15
初版発行。