しおしお

IntelliJのあれやこれや

Gradle4.6-rc1からのBOMサポート

Gradle 5.0のfeature previewでGradle5.0からはデフォルトで有効になるかもしれないやつらしいです。
Gradle4.6 RC1で使う場合には、enableFeaturePreview('IMPROVED_POM_SUPPORT')をsettings.gradleに追加してこの機能を有効化する必要がある。

settings.gradle

enableFeaturePreview('IMPROVED_POM_SUPPORT')

build.gradle

dependencies {
  // bom
  compile 'com.nablarch.profile:nablarch-bom:5u12'
  // bomにバージョン番号が定義されているのでバージョン番号は不要
  compile 'com.nablarch.framework:nablarch-fw-web' 
}

Gradle4.6-rc1からのJUnit5サポートを試してみた

Gradle4.6からのJUnit5サポートをお試ししてみた。

これより古いバージョンはGradleからJUnit5のテストを実行する - しおしおのエントリのようにする必要があると。

build.gradleの内容

test.useJUnitPlatformでJUnit5を有効化してあげる。
これだけでよくて、昔のバージョンのようにJUnit Platform Gradle Pluginは不要になる。

buildscript {
  ext.junit_version = '5.0.3'
}

test {
  useJUnitPlatform()

  // ログを出力したい場合…
  testLogging {
    events "passed", "skipped", "failed", "standardOut", "standardError"
  }
}

dependencies {
  
  testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version"
 
  testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version"
}

実行

./gradlew clean testで実行する。
ログを有効かしていると、こんな感じのものが出力される。

:test
sample.ParameterizedSampleTest > [1] 1 PASSED
sample.ParameterizedSampleTest > [2] 2 PASSED
sample.JUnit5Sample > test() PASSED
sample.ParamTest > [1] hoge, 4 PASSED
sample.ParamTest > [2] 1, 1 PASSED
sample.ParamTest > [1] (hoge, 4) PASSED
sample.ParamTest > [2] (abcdefg, 7) PASSED
BUILD SUCCESSFUL in 2s

テストのレポートはhtmlファイルでbuild/reports/testsに出力される。
JUnit Platform Gradle Pluginのようにxmlのテスト結果だけじゃないので良い感じ。

JaCoCoプラグイン

下を追加して、./gradlew clean test jacocoTestReportカバレッジが取れるようになる。

apply plugin: 'jacoco'

Gradle&JUnit5でJaCoCoを使う - しおしおみたいなことも要らなくなる。


おわり。

Gradle&JUnit5でJaCoCoを使う

Gradle&JUnit5の組み合わせでJaCoCoを使用した場合、デフォルトだとテスト実行時のカバレッジを取得することができない。*1
なので、この組み合わせでJaCoCoでカバレッジをとりたい場合は、JaCoCoプラグインの設定を変更する必要がある。

JaCoCoプラグインへの設定

  • JUnit5のテストを実行するjunitPlatformTestタスクをカバレッジ対象にする。
  • レポートを出力するタスクを追加して、junitPlatformTestの結果からレポートを出力できるようにする。
jacoco {
  applyTo junitPlatformTest
}

task junitPlatformJacocoReport(type: JacocoReport) {
  sourceSets sourceSets.main
  executionData junitPlatformTest
}

これで、gradle junitPlatformTest junitPlatformJacocoReportカバレッジ取得とhtmlレポートが生成できるようになると。

*1:GradleのJaCoCoプラグインのデフォルト動作だとjunitPlatformTestタスクはカバレッジ対象にならない。

JaCoCo0.8.0を試してみる

Release 0.8.0 · jacoco/jacoco · GitHubのtry-with-resources対応などなど良さげそうに見えたので試してみた。

try-with-resourcesを使った実装を作成

雑にこんな感じで…

public void test() throws IOException {

    try (InputStream stream = new ByteArrayInputStream(new byte[0])) {
        stream.read();
    }
}

0.7.9までの動きを確認と

build.gradleはこんな感じに

jacoco {
  toolVersion = "0.7.9"
}

JaCoCoのレポートを確認すると、分岐網羅されていないとなる。
f:id:sioiri:20180105210857p:plain

0.8.0にすると

build.gradleはこんな感じに

jacoco {
  toolVersion = "0.8.0"
}

分岐網羅されてていい感じ。
f:id:sioiri:20180105210958p:plain

他にもprivateコンストラクタの除外とかもしてくれたりするみたいなのがよい。

IntelliJ IDEA 2017.3 EAPからのeditor-based REST clientを試す

IntelliJ IDEA 2017.3(今はEAP)から追加されたeditor-based REST clientを試してみたよ。
詳しくは、What’s New in IntelliJ IDEA 2017.3 EAP? | IntelliJ IDEA BlogToolsに書かれてるよ。

試すために作ったサーバ側のコード

GETとPOSTを確認するためだけの簡単な実装で・・・

@RestController
@RequestMapping("/api")
class Api {

    data class Data(val value: String)

    @GetMapping
    fun get(@RequestHeader("X-Hoge") hoge: String): Data = Data("X-Hogeは $hoge でした")

    @PostMapping
    fun post(@RequestBody data: Data): ResponseEntity<Unit> {
        val httpHeaders = HttpHeaders()
        httpHeaders["x-hoge"] = listOf(data.toString())
        return ResponseEntity(httpHeaders, HttpStatus.OK)
    }
}

getを試す

拡張子がhttpだと、editor-based REST clientとして認識されるので、適当なところに拡張子がhttpのファイルを作ってあげる。
プロジェクト配下に置く必要がなければ、blogにあるようにScratch Fileとして作ってあげればよいのかなと。

ファイルの中身はこんな感じにする。

### get
# GETのあとにスペースを開けてURLを指定する。
# HTTP Headerは次の行から列挙する。
GET http://localhost:8080/api
X-Hoge: aaaa

こんな感じに補完もできるので割と良い感じ。
f:id:sioiri:20170916171909g:plain

実行はエディタの横に表示されている実行アイコンから行うと。
f:id:sioiri:20170916170331p:plain

実行結果は、Run Windowに表示されると。
レスポンスボディの内容は、プロジェクトの.idea/httpRequestsの下に自動的に保存されるから、あとから参照もできる。
繰り返し実行した場合、大量に保存されそうだから自分で消さないとダメなのかなー。。。
f:id:sioiri:20170916170603p:plain

postを試す

getと同じように拡張子がhttpなファイルを作る。

こんな感じにヘッダーの後に空行いれて送信するボディを定義すると

POST http://localhost:8080/api
Content-Type: application/json

{
  "value": "fuga"
}

こんな感じにファイルに定義した内容をボディを送るれるみたい。
指定するファイルのパスは相対パスの場合はプロジェクト直下から。

POST http://localhost:8080/api
Content-Type: application/json

< ./input/input.json

実行方法や、結果の参照はgetと同じ感じ。
GUIのREST Clientより繰り返し実行するのは便利かも?

おわり。

GradleからJUnit5のテストを実行する

junit5-gradle-consumerを参考にするとさくっとGradleで実行できるようになる。

build.gradle

JUnit Platform Gradle Pluginを設定して、testRuntimeにjunit-jupiter-engineを追加してあげる必要がる。

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
  }
}

apply plugin: 'org.junit.platform.gradle.plugin'

dependencies {
  testCompile 'org.junit.jupiter:junit-jupiter-api:5.0.0'
  testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.0.0'
}

テストの実行

テストを実行するとこんな感じに結果が表示される。
残念ながらGradleさんのtest reportには対応していないみたいでhtmlは保存されないみたい。
なお、テスト結果のxmlは出力されるので、JUnit4の時と同じようにCIでは結果を集計できる。

➜  junit5-sample ./gradlew clean test

> Task :compileTestKotlin
Using kotlin incremental compilation

> Task :junitPlatformTest

Test run finished after 139 ms
[         5 containers found      ]
[         0 containers skipped    ]
[         5 containers started    ]
[         0 containers aborted    ]
[         5 containers successful ]
[         0 containers failed     ]
[         4 tests found           ]
[         0 tests skipped         ]
[         4 tests started         ]
[         0 tests aborted         ]
[         4 tests successful      ]
[         0 tests failed          ]



BUILD SUCCESSFUL in 1s

おわり。

JUnit5のParameterized Testを試してみる

実験的機能っぽいけど、JUnit5でもParameterized Testsができるみたいなので、お試ししてみたよ。

必要なライブラリを追加

junit-jupiter-apiとParameterized Testをするために必要なjunit-jupiter-paramsを追加してあげる。

testCompile 'org.junit.jupiter:junit-jupiter-api:5.0.0'
testCompile 'org.junit.jupiter:junit-jupiter-params:5.0.0'

テストコードを書いてみる

ドキュメントを参考に書いてみた。
Testアノテーションは不要で、ParameterizedTestアノテーションを設定してあげるみたい。
テストデータはValueSourceアノテーションに設定する。ValueSourceアノテーションでは一部の型だけが使えるっぽい。
データはメソッドの引数で受け取ってあげると。

@ParameterizedTest
@ValueSource(strings = {"1", "2"})
void sample(final String value) {
  assertEquals(1, value.length());
}

IntelliJ IDEA(2017.3系)で実行

実行できた!IntelliJさんParameterizedTestに対応していい感じに表示してくれてすげー
f:id:sioiri:20170914200518p:plain

ValueSourceで指定できないデータの場合

MethodSourceを使うパターン

MethodSourceアノテーションで指定した名前のstaticなメソッドを作り、そこでデータを作ってコレクションで返してあげる感じみたいです。

companion object {
    @JvmStatic
    fun data() = listOf(
            arrayOf("hoge", 4),
            arrayOf("1", 1)
    )
}

@ParameterizedTest
@MethodSource("data")
fun sample2(input: String, expected: Int) {
    assertEquals(expected, input.length)
}

Kotlinだけどちゃんと動いてていい感じです。
f:id:sioiri:20170914202239p:plain

ArgumentsSourceを使うパターン

ArgumentsSourceアノテーションで指定したクラス(ArgumentsProviderの実装クラス)でパラメータを生成してあげます。

@ParameterizedTest
@ArgumentsSource(MyArgumentsProvider::class)
fun sample3(value: Pair<String, Int>) {
    assertEquals(value.second, value.first.length)
}

// このクラスでパラメータを生成する。
// この例だと、2つのパラメータをが作られます。
class MyArgumentsProvider : ArgumentsProvider {
    override fun provideArguments(context: ExtensionContext?): Stream<out Arguments> =
            Stream.of(Pair("hoge", 4), Pair("abcdefg", 7))
                    .map { Arguments.of(it) }
}

ちゃんと2回実行されてますね。
f:id:sioiri:20170915214102p:plain
おわり。