Spring Boot + npm + Geb で入力フォームを作ってテストする ( 番外編 )( gradle-processes を利用して Geb のテスト前に Spring Boot の Web アプリを自動起動する )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- Geb のテストを実行する前に都度 IntelliJ IDEA から Tomcat を起動するのは手間なので自動で起動できないか調べてみたところ、gradle-processes という Gradle のプラグインを利用して実施している例を見かけました。今回番外編として試してみようと思います。
- 尚、gradle-processes は現時点では Gradle のバージョンが 4.5 以下であることが条件となっており(実際 4.6 以上だと動きません)、今は 4.8.1 までバージョンを上げていて戻すつもりはないので今回変更した内容は commit しません。
参照したサイト・書籍
gradle-processes
https://github.com/johnrengelman/gradle-processesmstine/microservices-pact/build.gradle
https://github.com/mstine/microservices-pact/blob/master/build.gradleHow to use Gradle and Gatling to automate the load tests of a Spring Boot web service
http://brokenrhythm.blog/gradle-gatling-springboot-automation
目次
- gradle のバージョンを 4.5 に変更する
- build.gradle に gradle-processes を追加する
- build.gradle に Web アプリの自動起動、自動停止のタスクを追加する
- 動作確認
手順
gradle のバージョンを 4.5 に変更する
コマンドプロンプトから gradlew wrapper --gradle-version=4.5
を実行して Gradle のバージョンを 4.5 に変更します。
build.gradle の以下の点を変更します。
.......... wrapper { gradleVersion = '4.5' distributionType = Wrapper.DistributionType.ALL } .......... dependencies { def spockVersion = "1.1-groovy-2.4" def domaVersion = "2.19.2" def lombokVersion = "1.18.0" def errorproneVersion = "2.3.1" def powermockVersion = "1.7.4" def seleniumVersion = "3.13.0" // dependency-management-plugin によりバージョン番号が自動で設定されるもの // Appendix F. Dependency versions ( https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/html/appendix-dependency-versions.html ) 参照 compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-thymeleaf") { exclude group: "org.codehaus.groovy", module: "groovy" } compile("org.springframework.boot:spring-boot-starter-data-jpa") compile("org.springframework.boot:spring-boot-starter-freemarker") compile("org.springframework.boot:spring-boot-starter-mail") compile("org.springframework.boot:spring-boot-starter-security") runtimeOnly("org.springframework.boot:spring-boot-devtools") compile("org.springframework.session:spring-session") compile("org.codehaus.janino:janino") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.security:spring-security-test") testImplementation("org.yaml:snakeyaml") testImplementation("org.mockito:mockito-core") // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの compile("com.integralblue:log4jdbc-spring-boot-starter:1.0.2") compile("org.flywaydb:flyway-core:5.1.4") compile("com.h2database:h2:1.4.192") compile("com.github.rozidan:modelmapper-spring-boot-starter:1.0.0") compile("com.google.guava:guava:25.1-jre") compile("org.apache.commons:commons-lang3:3.7") testImplementation("org.dbunit:dbunit:2.5.4") testImplementation("org.assertj:assertj-core:3.10.0") testImplementation("org.spockframework:spock-core:${spockVersion}") testImplementation("org.spockframework:spock-spring:${spockVersion}") testImplementation("com.google.code.findbugs:jsr305:3.0.2") testImplementation("org.jsoup:jsoup:1.11.3") testImplementation("com.icegreen:greenmail:1.5.7") // for lombok // annotationProcessor("org.projectlombok:lombok:${lombokVersion}") compileOnly("org.projectlombok:lombok:${lombokVersion}") // for Doma // annotationProcessor("org.seasar.doma:doma:${domaVersion}") compile("org.seasar.doma:doma:${domaVersion}") domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}") domaGenRuntime("com.h2database:h2:1.4.192") // for Error Prone ( http://errorprone.info/ ) errorprone("com.google.errorprone:error_prone_core:${errorproneVersion}") compileOnly("com.google.errorprone:error_prone_annotations:${errorproneVersion}") // PowerMock testImplementation("org.powermock:powermock-module-junit4:${powermockVersion}") testImplementation("org.powermock:powermock-api-mockito:${powermockVersion}") // for Geb + Spock testImplementation("org.gebish:geb-spock:2.1") testImplementation("org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}") testImplementation("org.seleniumhq.selenium:selenium-firefox-driver:${seleniumVersion}") testImplementation("org.seleniumhq.selenium:selenium-support:${seleniumVersion}") testImplementation("org.seleniumhq.selenium:selenium-api:${seleniumVersion}") testImplementation("org.seleniumhq.selenium:selenium-remote-driver:${seleniumVersion}") }
- wrapper block 内で
gradleVersion = '4.8.1'
→gradleVersion = '4.5'
に変更します。 - dependencies block 内で
annotationProcessor
の行をコメントアウトします。annotationProcessor
が入ったのは 4.6 からなので、4.5 では使用できません。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
build.gradle に gradle-processes を追加する
追加する方法が少し分かりづらかったです。。。
Maven Repository で "gradle-processes" で検索すると、以下の結果が表示されます。最初の2件がどちらも gradle-processes です。
1件目をクリックすると以下の画面が表示されます。
2件目をクリックすると以下の画面が表示されます。
また gradle-processes の GitHub のページ を見ると How To Use に以下の記述があります。
以上の内容から、利用するためには以下の設定が必要なことが分かります。
- gradle-processes を利用するにはレポジトリに Gradle Plugins repository(https://plugins.gradle.org/m2/)を追加する必要がある。
- 最新バージョンは 0.4.1。plugin block に
id "com.github.johnrengelman.processes" version "0.4.1"
の記述を追加する。
build.gradle の以下の点を変更します。
buildscript { ext { group "ksbysample" version "1.0.1-RELEASE" springBootVersion = "1.5.14.RELEASE" } repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } } plugins { id "java" id "eclipse" id "idea" // plugins {} block 内では ${springBootVersion} が使用できないので、バージョンを直接記述している id "org.springframework.boot" version "1.5.14.RELEASE" id "groovy" id "net.ltgt.errorprone" version "0.0.14" id "checkstyle" id "findbugs" id "pmd" id "com.moowork.node" version "1.2.0" id "com.github.johnrengelman.processes" version "0.4.1" } ..........
- buildscript block に
repositories { ... }
を追加します。この中でmaven { url "https://plugins.gradle.org/m2/" }
を記述します。 - plugins block に
id "com.github.johnrengelman.processes" version "0.4.1"
を追加します。version "0.4.1"
の記述がないとPlugin [id: 'com.github.johnrengelman.processes'] was not found in any of the following sources: ... - Plugin Repositories (plugin dependency must include a version number for this source)
というエラーが出ます。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
build.gradle に Web アプリの自動起動、自動停止のタスクを追加する
build.gradle の以下の点を変更します。
buildscript { ext { group "ksbysample" version "1.0.1-RELEASE" springBootVersion = "1.5.14.RELEASE" mainClass = "ksbysample.webapp.bootnpmgeb.Application" } repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } } .......... bootRepackage { mainClass = "${mainClass}" } .......... // for Geb + Spock Integration Test task startServer(type: com.github.jengelman.gradle.plugins.processes.tasks.JavaFork) { jvmArgs = [ '-Dspring.profiles.active=develop', '-Dlogging.level.root=OFF', '-Dlogging.level.org.springframework.web=OFF', '-Dlogging.level.jdbc.sqlonly=OFF', '-Dlogging.level.jdbc.sqltiming=OFF', '-Dlogging.level.jdbc.audit=OFF', '-Dlogging.level.jdbc.resultset=OFF', '-Dlogging.level.jdbc.resultsettable=OFF', '-Dlogging.level.jdbc.connection=OFF' ] classpath += sourceSets.main.runtimeClasspath main = "${mainClass}" doLast { Thread.sleep(15000) } } task stopServer { doLast { startServer.processHandle.abort() } } def drivers = ["chrome", "firefox"] drivers.each { driver -> task "${driver}Test"(type: Test) { // 前回実行時以降に何も更新されていなくても必ず実行する outputs.upToDateWhen { false } systemProperty "geb.env", driver exclude "ksbysample/**" dependsOn startServer finalizedBy stopServer } } task gebTest { dependsOn drivers.collect { tasks["${it}Test"] } enabled = false } ..........
- buildscript block 内の ext block 内に
mainClass = "ksbysample.webapp.bootnpmgeb.Application"
を追加します。メインクラスを記述する箇所が2箇所になるので、共通で使用する変数を定義します。 - bootRepackage block 内で
mainClass = '${ksbysample.webapp.bootnpmgeb.Application}'
→mainClass = "${mainClass}"
に変更します。 - 以下の2つの task を追加します。gradle-processes では
task startServer(type: Fork)
のように書かれていますが、なぜか動作しなかったのでcom.github.jengelman.gradle.plugins.processes.tasks.JavaFork
のようにパッケージも含めて記述しています。task startServer(type: com.github.jengelman.gradle.plugins.processes.tasks.JavaFork) { ... }
task stopServer { ... }
drivers.each { driver -> task "${driver}Test"(type: Test) { ... } }
内に以下の2行を追加します。dependsOn startServer
finalizedBy stopServer
動作確認
最初に clean タスク → Rebuild Project → build タスクを実行して BUILD SUCCESSFUL が表示されること、startServer と stopServer タスクが実行されないことを確認します。
なぜかこのタイミングで Chrome 68 が Twitter のトレンドにランクインしていたので、バージョンアップします。
次に gebTest タスクを実行します。startServer → chromeTest, firefoxTest → stopServer の順に実行されて、BUILD SUCCESSFUL が表示されました。問題なさそうです。
chromeTest タスクだけを実行してみます。startServer → chromeTest → stopServer の順に実行されて、テストは全て成功しました。
firefoxTest タスクだけを実行してみます。startServer → firefoxTest → stopServer の順に実行されて、テストは全て成功しました。
このプラグイン、便利ですね。GitHub の Issue を見たら現在 4.6 以降に対応中のようです。
履歴
2018/07/25
初版発行。