MPのご利用は計画的に

だいたい自分用のメモ

JUnit5のTagアノテーションは便利そう だけど…

概要

JUnit5には@Tagというアノテーションがあって、テストをグルーピングして実行できると知った時のメモです。

環境

  • Kotlin 1.2.51
  • JUnit 5.2.0

JUnit4にもグルーピングはあった

JUnit4では@Categoryだったものが@Tagに変わったようですね。

https://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4-tips

@Category no longer exists; use @Tag instead.

準備

KotlinとJUnit5の構成 をベースにして追記していきます。

準備ができたら

動かすテストクラスを作ります。今回は3つ用意してみました。
develop productionがそれぞれ指定されたクラスと、その両方が指定されたクラスです。

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

class DevelopTest {
    @Test
    @Tag("develop")
    fun develop() {
        Assertions.assertTrue(true, "Executed Develop test.")
    }
}
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

class ProductionTest {
    @Test
    @Tag("production")
    fun production() {
        Assertions.assertTrue(true, "Executed production test.")
    }
}
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Tags
import org.junit.jupiter.api.Test

class AlwaysTest {
    @Test
    @Tags(Tag("develop"), Tag("production"))
    fun always() {
        Assertions.assertTrue(true, "Executed always.")
    }
}

@Tagsアノテーションを使うと複数の@Tagをまとめられます。

クラスができたら

pom.xmlに設定を追加します。
maven-surefire-pluginconfigurationに追加です。
ここではアノテーションdevelopを指定しているテストのみ動かす設定です。

<build>
...
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.0</version>
            <configuration>
                <properties>
                    <includeTags>develop</includeTags>
                </properties>
            </configuration>
        </plugin>
    </plugins>
...
</build>

ここで問題が

Referenceにある通り includeTags を指定するも、なぜかすべてのテストが動いてしまうという現象が発生。
なんでだろうと悩んで試しにタグを groups に変えると動きました…。

<properties>
    <groups>develop</groups>
</properties>

バグ…なのかな?

実行してみた

$ mvn test
...
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.panage.junit5.AlwaysTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.019 s - in com.example.panage.junit5.AlwaysTest
[INFO] Running com.example.panage.junit5.DevelopTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 s - in com.example.panage.junit5.DevelopTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.767 s
[INFO] Finished at: 2018-07-22T12:02:19+09:00
[INFO] ------------------------------------------------------------------------

ためしに設定を書き換えてみると

<properties>
    <groups>production</groups>
</properties>
$ mvn test
...
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.panage.junit5.AlwaysTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.019 s - in com.example.panage.junit5.AlwaysTest
[INFO] Running com.example.panage.junit5.ProductionTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 s - in com.example.panage.junit5.ProductionTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.767 s
[INFO] Finished at: 2018-07-22T12:02:19+09:00
[INFO] ------------------------------------------------------------------------

うまく切り替わるようになりました。

設定を毎回書き換えるのは面倒です

ということで、こちらを参考にprofileを作って、実行時のprofileに応じて変わるようにしました。

stackoverflow.com

<profiles>
    <profile>
        <id>develop</id>
        <properties>
            <include.tags>develop</include.tags>
        </properties>
    </profile>
    <profile>
        <id>production</id>
        <properties>
            <include.tags>production</include.tags>
        </properties>
    </profile>
</profiles>
...

<build>
...
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.0</version>
            <configuration>
                <properties>
                    <groups>${include.tags}</groups>
                </properties>
            </configuration>
        </plugin>
    </plugins>
...
</build>
# developの場合
$ mvn -P develop test

# productionの場合
$ mvn -P production test

雑感

うまく使えば便利そうだなと思う半面、使いすぎると収拾つかなくなってカオスになりそうにも感じます。
「Production」「Develop」「外部通信が必要」程度にしておくのが良いかもしれないという気持ちです。

KotlinでJUnit5を使う

概要

KotlinとJUnit5を使うためのできるだけシンプルな構成を作ったときのメモです。

環境

まずはKotlinの準備

KotlinのReferenceに沿って設定すればOK。 今回はMavenを使っています。 https://kotlinlang.org/docs/reference/using-maven.html

Kotlinを使うために追加するのはこんな感じ。

<properties>
    <kotlin.version>1.2.51</kotlin.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-stdlib</artifactId>
        <version>${kotlin.version}</version>
    </dependency>
</dependencies>

<build>
    <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
    <plugins>
        <plugin>
            <artifactId>kotlin-maven-plugin</artifactId>
            <groupId>org.jetbrains.kotlin</groupId>
            <version>${kotlin.version}</version>

            <executions>
                <execution>
                    <id>compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>

                <execution>
                    <id>test-compile</id>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    <plugins>
</build>

次はJUnit5の設定

ここにJUnit5を追加していきます。 こちらもReferenceに沿って依存を追加すれば大丈夫。 JUnit5を使うには最低限junit-jupiter-engineを依存関係に含めることと、 Mavenから実行するにはmaven-surefire-pluginが必要。

<properties>
    ...
    <junit.jupiter.version>5.2.0</junit.jupiter.version>
    ...
</properties>

<dependencies>
    ...
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>${junit.jupiter.version}</version>
        <scope>test</scope>
    </dependency>
    ...
</dependencies>

<build>
    ...
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.0</version>
        </plugin>
    </plugins>
</build>

このブログの公開時にはmaven-surefire-pluginのバージョンが2.21.0を使うように書かれていますが、 2.22.0を使っても問題ないようです。

適当なクラスを作成

テストを実行するために適当なクラスを作ります。 今回はただhogeという文字列を返すだけの関数を作りました。

package com.example.panage.junit5

class Hoge {
    fun say(): String = "hoge"
}

テストクラスを作成

テストクラスを作成します。 テストを実行したい関数に@org.junit.jupiter.api.Testアノテーションを付与すればOK。

package com.example.panage.junit5

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

internal class HogeTest {

    @Test
    fun sayのテスト() {
        // setup
        val hoge = Hoge()

        // expect
        Assertions.assertEquals("hoge", hoge.say())
    }
}

hogeという文字列が返ってくるはずなので、Assertions.assertEqualsで比較しています。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.panage.junit5.HogeTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.013 s - in com.example.panage.junit5.HogeTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

雑感

KotlinもJUnitも公式のReferenceが整っているので、手順通りに進めれば問題ありませんでした。
テストクラスもいままでと同じように書けるので違和感もなさそうです。

参考

kotlinlang.org

https://junit.org/junit5/docs/current/user-guide/junit.org