Spring Boot + npm + Geb で入力フォームを作ってテストする ( その83 )( Checkstyle を 8.11 → 8.19 へ、PMD を 6.6.0 → 6.13.0 へバージョンアップ+JUnit 5 の導入+ Oracle JDK 8u202 → AdoptOpenJDK 11.0.2+9 へ、error-prone を 2.3.1 → 2.3.3 へバージョンアップする)
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
参照したサイト・書籍
https://github.com/apache/groovy/commit/92bd96fcdfe35e502987e1846715a08a45620db1
- Groovy で
--add-opens
オプションを付ける時に参照しました。
- Groovy で
目次
- Checkstyle を 8.11 → 8.19 へ、PMD を 6.6.0 → 6.13.0 へバージョンアップする
- JUnit 5 を導入する
- Oracle JDK 8u202 → AdoptOpenJDK 11.0.2+9 へ、error-prone を 2.3.1 → 2.3.3 へバージョンアップする
- testJUnit4AndSpock タスクで出る警告を解消する
- 失敗するテストの原因を調査・解消する
- compileTestGroovy タスクで出る警告を解消する。。。ことは出来ませんでした
- gebTest タスクが成功するようにする
手順
Checkstyle を 8.11 → 8.19 へ、PMD を 6.6.0 → 6.13.0 へバージョンアップする
build.gradle の以下の点を変更します。
checkstyle { configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml") toolVersion = "8.19" sourceSets = [project.sourceSets.main] } .......... pmd { toolVersion = "6.13.0" sourceSets = [project.sourceSets.main] ignoreFailures = true consoleOutput = true ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml") ruleSets = [] }
- checkstyle block で
toolVersion = "8.11"
→toolVersion = "8.19"
に変更します。 - pmd block で
toolVersion = "6.6.0"
→toolVersion = "6.13.0"
に変更します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
clean タスク実行 → Rebuild Project 実行 → build タスク実行を行うと、PMD で何件か警告が出ました。
D:\project-springboot\ksbysample-boot-miscellaneous\boot-npm-geb-sample\src\main\java\ksbysample\webapp\bootnpmgeb\Application.java:26: The constant name 'springProfiles' doesn't match '[A-Z][A-Z_0-9]*'
- 定数名を SPRING_PROFILES に変更します。
D:\project-springboot\ksbysample-boot-miscellaneous\boot-npm-geb-sample\src\main\java\ksbysample\webapp\bootnpmgeb\aspect\logging\ControllerAndEventNameLogger.java:17: The constant name 'logger' doesn't match '[A-Z][A-Z_0-9]*'
D:\project-springboot\ksbysample-boot-miscellaneous\boot-npm-geb-sample\src\main\java\ksbysample\webapp\bootnpmgeb\aspect\logging\MethodLogger.java:20: The constant name 'logger' doesn't match '[A-Z][A-Z_0-9]*'
D:\project-springboot\ksbysample-boot-miscellaneous\boot-npm-geb-sample\src\main\java\ksbysample\webapp\bootnpmgeb\aspect\logging\RequestAndResponseLogger.java:34: The constant name 'logger' doesn't match '[A-Z][A-Z_0-9]*'
再度 clean タスク実行 → Rebuild Project 実行 → build タスク実行を行うと、今度は BUILD SUCCESSFUL のメッセージが出力されました。
JUnit 5 を導入する
build.gradle の以下の点を変更します。
dependencyManagement { imports { // mavenBom は以下の URL のものを使用する // https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.1.4.RELEASE/ // bomProperty に指定可能な property は以下の URL の BOM に記述がある // https://repo.spring.io/release/org/springframework/boot/spring-boot-dependencies/2.1.4.RELEASE/spring-boot-dependencies-2.1.4.RELEASE.pom mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES mavenBom("org.junit:junit-bom:5.4.2") } } dependencies { .......... // for JUnit 5 // junit-jupiter で junit-jupiter-api, junit-jupiter-params, junit-jupiter-engine の3つが依存関係に追加される testCompile("org.junit.jupiter:junit-jupiter") testRuntime("org.junit.platform:junit-platform-launcher") } def jvmArgsForTask = [ "-ea", "-Dfile.encoding=UTF-8", "-Dsun.nio.cs.map=x-windows-iso2022jp/ISO-2022-JP" ] def printTestCount = { desc, result -> if (!desc.parent) { // will match the outermost suite println "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" } } bootRun { jvmArgs = jvmArgsForTask + ["-Dspring.profiles.active=develop"] } tasks.withType(Test) { jvmArgs = jvmArgsForTask + ["-Dspring.profiles.active=unittest"] } task testJUnit4AndSpock(type: Test) { // testJUnit4AndSpock タスクの jvmArgs は tasks.withType(Test) { ... } で定義している exclude "geb/**" testLogging { afterSuite printTestCount } } test.dependsOn testJUnit4AndSpock test { // test タスクの jvmArgs は tasks.withType(Test) { ... } で定義している // for JUnit 5 useJUnitPlatform() testLogging { afterSuite printTestCount } } .......... webdriverBinaries { chromedriver "73.0.3683.68" geckodriver "0.24.0" } def drivers = ["chrome", "firefox"] drivers.each { driver -> task "${driver}Test"(type: Test) { // 前回実行時以降に何も更新されていなくても必ず実行する outputs.upToDateWhen { false } systemProperty "geb.env", driver exclude "ksbysample/**" // Gradle 5.3 で internal API が変更されて gradle-processes が動かなくなったのでコメントアウトする // dependsOn startServer // finalizedBy stopServer testLogging { afterSuite printTestCount } } } task gebTest { dependsOn drivers.collect { tasks["${it}Test"] } enabled = false }
- dependencyManagement block の import block 内に
mavenBom("org.junit:junit-bom:5.4.2")
を追加します。 - dependencies block に以下の2行を追加します。
testCompile("org.junit.jupiter:junit-jupiter")
testRuntime("org.junit.platform:junit-platform-launcher")
def jvmArgsForTask = [ ... ]
を追加します。def printTestCount = { ... }
を追加します。- bootRun タスクの jvmArgs の設定を jvmArgsForTask 変数を利用したものに変更します。
tasks.withType(Test) { ... }
の jvmArgs の設定を jvmArgsForTask 変数を利用したものに変更します。task testJUnit4AndSpock(type: Test) { ... }
を追加します。test.dependsOn testJUnit4AndSpock
を追加します。- test タスク内に以下の記述を追加します。
useJUnitPlatform()
testLogging { afterSuite printTestCount }
exclude "geb/**"
の記述は test タスクから testJUnit4AndSpock タスクへ移動します。drivers.each { driver -> task "${driver}Test"(type: Test) { ... } }
内にtestLogging { afterSuite printTestCount }
を追加します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
clean タスク実行 → Rebuild Project 実行 → build タスク実行をすると、テストは問題なく成功し BUILD SUCCESSFUL のメッセージが出力されました。
gebTest タスクも BUILD SUCCESSFUL のメッセージが出力されました。
Oracle JDK 8u202 → AdoptOpenJDK 11.0.2+9 へ、error-prone を 2.3.1 → 2.3.3 へバージョンアップする
IntelliJ IDEA のメインメニューから「File」-「Project Structure...」を選択して「Project Structure」ダイアログを開き、「Project SDK」で「11.0.2+9」を選択してから「OK」ボタンをクリックしてダイアログを閉じます。
build.gradle の以下の点を変更します。
plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.1.4.RELEASE" id "io.spring.dependency-management" version "1.0.7.RELEASE" id "groovy" id "net.ltgt.errorprone" version "0.7.1" id "checkstyle" id "com.github.spotbugs" version "1.6.9" id "pmd" id "com.moowork.node" version "1.3.1" id "com.gorylenko.gradle-git-properties" version "2.0.0" // Gradle 5.3 で internal API が変更されて gradle-processes が動かなくなったのでコメントアウトする // id "com.github.johnrengelman.processes" version "0.5.0" id "com.energizedwork.webdriver-binaries" version "1.4" } sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 .......... [compileJava, compileTestGroovy, compileTestJava]*.options*.encoding = "UTF-8" [compileJava, compileTestGroovy, compileTestJava]*.options*.compilerArgs = ["-Xlint:all,-options,-processing,-path"] tasks.named("compileTestJava").configure { options.errorprone.enabled = false } .......... dependencies { def spockVersion = "1.3-groovy-2.5" def domaVersion = "2.24.0" def lombokVersion = "1.18.6" def errorproneVersion = "2.3.3" def powermockVersion = "2.0.0" def seleniumVersion = "3.13.0" def spotbugsVersion = "3.1.11" .......... // for Geb + Spock testImplementation("org.gebish:geb-spock:2.3.1") { exclude group: "org.codehaus.groovy", module: "groovy-all" } .......... } def jvmArgsForTask = [ "-ea", "-Dfile.encoding=UTF-8", "-Dsun.nio.cs.map=x-windows-iso2022jp/ISO-2022-JP" ] // JDK 11 に変更後、test タスク実行時に groovy と powermock が JDKの内部部分にアクセスするためにコードでリフレクションを使用 // していて WARNING が出るため、JVM の起動時オプションの --add-opens を指定して WARNING が出ないようにする def jvmArgsAddOpens = [ "--add-opens=java.base/java.io=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.lang.invoke=ALL-UNNAMED", "--add-opens=java.base/java.lang.ref=ALL-UNNAMED", "--add-opens=java.base/java.lang.reflect=ALL-UNNAMED", "--add-opens=java.base/java.net=ALL-UNNAMED", "--add-opens=java.base/java.security=ALL-UNNAMED", "--add-opens=java.base/java.util=ALL-UNNAMED", "--add-opens=java.base/java.util.stream=ALL-UNNAMED" ] def printTestCount = { desc, result -> if (!desc.parent) { // will match the outermost suite println "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" } } bootRun { jvmArgs = jvmArgsForTask + jvmArgsAddOpens + ["-Dspring.profiles.active=develop"] } tasks.withType(Test) { jvmArgs = jvmArgsForTask + jvmArgsAddOpens + ["-Dspring.profiles.active=unittest"] }
- plugins block の以下の点を変更します。
id "net.ltgt.errorprone" version "0.0.14"
→id "net.ltgt.errorprone" version "0.7.1"
- sourceCompatibility、targetCompatibility に指定する値を
1.8
→JavaVersion.VERSION_11
に変更します。 compileJava.options.compilerArgs += [ ... ]
を削除します。tasks.named("compileTestJava").configure { options.errorprone.enabled = false }
を追加します。- dependencies block の以下の点を変更します。
def errorproneVersion = "2.3.1"
→def errorproneVersion = "2.3.3"
def jvmArgsAddOpens = [ ... ]
を追加します。Spring Boot 2.0.x の Web アプリを 2.1.x へバージョンアップする ( その15 )( JDK を 8u202 → 11.0.2+9 に変更する ) で指定したものと同じものを指定しておきます。bootRun { ... }
とtasks.withType(Test) { ... }
内の jvmArgs の設定にjvmArgsAddOpens +
を追加します。- groovy も 2.5 にバージョンアップします。
- dependencies block 内で
def spockVersion = "1.3-groovy-2.4"
→def spockVersion = "1.3-groovy-2.5"
に変更します。 testImplementation("org.gebish:geb-spock:2.3.1")
→testImplementation("org.gebish:geb-spock:2.3.1") { exclude group: "org.codehaus.groovy", module: "groovy-all" }
に変更します。
- dependencies block 内で
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
IntelliJ IDEA のメインメニューから「Run」-「Edit Configurations...」を選択して「Run/Debug Configurations」ダイアログを開き、画面左側のツリーから「Templates」-「JUnit」を選択後、画面右側の「VM options」に build.gradle の def jvmArgsAddOpens = [ ... ]
に記述したオプションを追加します。
また追加した結果 IntelliJ IDEA からテストを実行しようとすると Command line is too long.
のエラーメッセージが表示されて実行できなくなるので、画面右側の「Shorten command line」で「JAR manifest」を選択します。
clean タスク実行 → Rebuild Project 実行 → build タスク実行して出力される以下のエラーメッセージを取り除きます。
エラー: An unhandled exception was thrown by the Error Prone static analysis plugin.
- このエラーメッセージが出る箇所は PMD の @SuppressWarnings が付与されているので、
@SuppressWarnings({"PMD.UnusedPrivateMethod"})
→@SuppressWarnings({"PMD.UnusedPrivateMethod", "UnusedMethod"})
に変更します。
- このエラーメッセージが出る箇所は PMD の @SuppressWarnings が付与されているので、
警告:[JavaTimeDefaultTimeZone] LocalDateTime.now() is not allowed because it silently uses the system default time-zone. You must pass an explicit time-zone (e.g., ZoneId.of("America/Los_Angeles")) to this method.
LocalDateTime.now()
→LocalDateTime.now(ZoneId.of("Asia/Tokyo"))
に変更します。
ここまでやると以下の状態になります。
- compileTestGroovy タスクで警告が出る。
- testJUnit4AndSpock タスクで警告が出る。
- テストが1件失敗する。
testJUnit4AndSpock タスクで出る警告を解消する
出たのは以下3件のメッセージでした。
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedConstructor$1 (file:/C:/Users/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.6/6936e700f0fb1b50bac0698ada4347a769d40199/groovy-2.5.6.jar) to constructor java.util.stream.Collectors()
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedConstructor$1 (file:/C:/Users/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.6/6936e700f0fb1b50bac0698ada4347a769d40199/groovy-2.5.6.jar) to constructor java.nio.charset.StandardCharsets()
WARNING: Illegal reflective access by org.powermock.reflect.internal.WhiteboxImpl (file:/C:/Users/root/.gradle/caches/modules-2/files-2.1/org.powermock/powermock-reflect/2.0.0/cd452bc345ec9f88ec5efecd41139de0cb1d4265/powermock-reflect-2.0.0.jar) to method java.util.regex.Pattern.clazz(boolean)
build.gradle と IntelliJ IDEA の「Edit Configurations...」-「JUnit」の設定に以下のオプションを追加します。
--add-opens=java.base/java.util.stream=ALL-UNNAMED
--add-opens=java.base/java.nio.charset=ALL-UNNAMED
--add-opens=java.base/java.util.regex=ALL-UNNAMED
失敗するテストの原因を調査・解消する
エラーの原因を調べるために Project Tool Window で src/test/groovy/ksbysample でコンテキストメニューを表示して「Run 'Tests in 'ksbysample''」を選択してテストを実行してみると、
テストが失敗したのは src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/form/InquiryInput02FormValidatorTest.groovy で、以下のように実装されていました。
@RunWith(PowerMockRunner) @PowerMockRunnerDelegate(SpringRunner) @SpringBootTest @PrepareForTest(EmailValidator) @PowerMockIgnore("javax.management.*") static class InquiryInput02FormValidator_メールアドレス { @Autowired private InquiryInput02FormValidator input02FormValidator ..........
@PowerMockIgnore("javax.management.*")
を変更し忘れていただけでした。。。 @PowerMockIgnore("javax.management.*")
→ @PowerMockIgnore(["javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*"])
に変更します。ksbysample-webapp-lending と同じ変更だと Caused by: java.lang.IllegalAccessError: class com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl (in unnamed module @0x12e035a8) cannot access class jdk.xml.internal.JdkXmlUtils (in module java.xml) because module java.xml does not export jdk.xml.internal to unnamed module @0x12e035a8
というエラーメッセージが表示されたので、, "com.sun.org.apache.xalan.*"
を追加しています。
compileTestGroovy タスクで出る警告を解消する。。。ことは出来ませんでした
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/C:/Users/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.6/6936e700f0fb1b50bac0698ada4347a769d40199/groovy-2.5.6.jar) to method java.util.AbstractCollection.hugeCapacity(int)
というエラーメッセージが出ているので compileTestGroovy タスクの jvmArgs にも --add-opens
オプションを設定しようと思い設定方法を調べたところ、gradle/gradle に Unable to add multiple --add-opens
args to forked Groovy compiler #7045 という Issue を見つけました。
試してみたところ "--add-opens"
を1行だけ書いた時は問題ないのですが、以下のように2行記述すると、
[compileJava, compileTestGroovy, compileTestJava]*.options*.encoding = "UTF-8" [compileJava, compileTestGroovy, compileTestJava]*.options*.compilerArgs = ["-Xlint:all,-options,-processing,-path"] tasks.named("compileTestJava").configure { options.errorprone.enabled = false } compileTestGroovy { options.forkOptions.jvmArgs += [ "--add-opens", "java.base/java.util=ALL-UNNAMED", "--add-opens", "java.base/java.lang.annotation=ALL-UNNAMED" ] }
下の画像のエラーメッセージが表示されます。
他にも調べてみましたがさっぱり解決方法が分かりませんでした。Issue のクローズ待ちでしょうか。。。 今回は compileTestGroovy の警告メッセージは解消するのは諦めます。
ここまでの対応で clean タスク実行 → Rebuild Project 実行 → build タスク実行を行うと compileTestGroovy タスクで警告のメッセージが出ますが、BUILD SUCCESSFUL のメッセージが表示されるようになりました。
gebTest タスクが成功するようにする
gebTest タスクを実行すると1件警告が出ます。
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedConstructor$1 (file:/C:/Users/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.6/6936e700f0fb1b50bac0698ada4347a769d40199/groovy-2.5.6.jar) to constructor java.beans.Introspector(java.lang.Class,java.lang.Class,int)
java.beans は https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/beans/package-summary.html を見ると Module java.desktop
と書かれていたので、
build.gradle と IntelliJ IDEA の「Edit Configurations...」-「JUnit」の設定に "--add-opens=java.desktop/java.beans=ALL-UNNAMED"
を追加します。
def jvmArgsAddOpens = [ "--add-opens=java.base/java.io=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.lang.invoke=ALL-UNNAMED", "--add-opens=java.base/java.lang.ref=ALL-UNNAMED", "--add-opens=java.base/java.lang.reflect=ALL-UNNAMED", "--add-opens=java.base/java.net=ALL-UNNAMED", "--add-opens=java.base/java.nio.charset=ALL-UNNAMED", "--add-opens=java.base/java.security=ALL-UNNAMED", "--add-opens=java.base/java.util=ALL-UNNAMED", "--add-opens=java.base/java.util.regex=ALL-UNNAMED", "--add-opens=java.base/java.util.stream=ALL-UNNAMED", "--add-opens=java.desktop/java.beans=ALL-UNNAMED" ]
これで gebTest タスクは正常に終了するようになりました。
以上で今回の boot-npm-geb-sample プロジェクトのバージョンアップ作業は完了です。
履歴
2019/04/16
初版発行。