JUnit 5 M1 をやってみよう

# 本資料について

- 本資料は、[第十六回 #渋谷java](http://shibuya-java.connpass.com/event/34034/) にて発表された資料です。

---

# 自己紹介

- 福原和朗　@kazurof 
    - Qiita, twitter, Facebook とかやってます。
- 所属
    - GMOリサーチ
        - アンケートシステムの開発保守

---

# 本日のお題
- JUnit 5.0.0-M1 が、2016/7/7にリリースされました
	- 七夕さま :tanabata_tree: 
- いじってみた感触など並べてみます。
- 注意：Milestoneなので今後変更入るかもしれません。

---
# そもそもの大前提

- 元となるパッケージ名が変わった。
    - `org.junit.jupiter`
    - `org.junit.platform`　など
    - JUnit4 とのAPI互換性はありません。
- Java8以降をサポート。
    - Java7以前はさようなら。

---
# JUnit5 のサブモジュール

- JUnit Platform
    - テストの実行の全体枠組み
- JUnit Jupiter 
    - テスト開発者・拡張の開発者向けAPI
- JUnit Vintage
    - JUnit3, 4 の実行API

---
# Jupiter という名前の由来

- 太陽系の５番目の惑星からとったそうです。
- "Jupiter is the fifth planet from the sun."
- 参考
    - https://github.com/junit-team/junit5/issues/286
 
---
# JUnit5で何が変わったか？

- 基本的なやり方は変わっていない。

 `@Test`       テストメソッド
 `@BeforeEach` 事前処理
 `@AfterEach`  事後処理

---
# サンプル

```java
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class FirstJUnit5Tests {
    @Test
    void myFirstTest() {
        assertEquals(2, 1 + 1);
    }
}
```
---
# 無くなった(?)もの

- assertThat

アサーション系の機能は好きなもの使ってね、というスタンスらしい。

---
# 無くなった(?)もの :two: 

- TestSuite
    - 複数のテストを木構造のようにグループ化
    - テストメソッドに"タグ"をつけるやり方に移行
        -  `@Tag("nantoka")` 
    - 従前、`Categories`と呼ばれていた機能。
        -  以前はexperimentalだった。

---
# JUnit4 のTestSuite

```java
//こんなボイラープレートコードは大変かも!
package tryjunit4.suite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; 
@RunWith(Suite.class)
@SuiteClasses( { SampleTest.class, AnotherTest.class,
        tryjunit4.subpack.AllTests.class })
public class AllTests {
}
```
---
# JUnit5 の`@Tag`の例

```java
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
//"fast"タグを指定してテスト実行などできる
@Tag("fast")
class TaggingDemo {
    @Test
    @Tag("taxes")
    void testingTaxCalculation() {
    }
}
```

---
# 無くなった(?)もの :three: 

- `@Rule`による拡張
	- なくなる見込み。多分。
	- そもそも、フィールドを使う形なので大仰になりがちだった。
	- 新たに設計された拡張が導入される。
	- `@ExtendWith`

---
```java
import org.junit.rules.TestName;
public class TestNameTest {
    //Ruleはフィールドを使うので
    //別のテストで使ってないか注意必要
    @Rule　
    public TestName name = new TestName();
    @Test
    public void testA() {
        assertEquals("testA", name.getMethodName());
    }
    @Test
    public void testB() {
        assertEquals("testB", name.getMethodName());
    }
}
```

---
# `TestName`はどうなった？

- テスト名をとれる`@Rule`のAPI
- 消えます。
- 代わりに、テストメソッドのパラメータから取れます。
    - テスト名含む各種情報も取れます。
    - `TestInfo`

---
# テストにパラメータを渡せる

- どんなパラメータを渡すかもカスタマイズ可能
    - `ParameterResolver` によるしくみ
- 組み込みのResolver
    - `TestInfoParameterResolver`
    - `TestReporterParameterResolver`
        - テストでログを吐きたい時の委譲先

---
```java
import org.junit.jupiter.api.TestInfo;
// importは適当に省略してます。
class TestInfoDemo {
  @Test
  @Tag("my tag")
  void test1(TestInfo testInfo) {
    assertTrue(testInfo.getTags().contains("my tag"));
  }
  @Test
  void test2() {   }
}
```

---
# できるようになったこと :one: 

- テスト名を個別につけられるようになった。

```java
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
class DisplayNameDemo {
  @Test
  @DisplayName("なんとかてすと")
  void testWithDisplayNameContainingSpaces() {
  }
}
```

---
# できるようになったこと　:two:

- テストクラスを内部クラスとする機能が標準になりました。
    - experimental　ではなくなりました。
    - `@Nested`

---
# できるようになったこと　:three:

- `DynamicTest`
    - テストを作る処理を書くことができる。
        - 動的にテストが作られる。

---
# `parameterized` の代替

テスト対象メソッドに、テストデータを多数渡してテストしたい。

- テストしたい処理
- テストデータを作る処理

以上をラムダで書いておくと、JUnit5が組み合わせて実行してくれます。動的です。


---
```java
// JUnit4 だとやっぱりフィールドを使うので、つかいにくい
@RunWith(Parameterized.class)
public class NoConstructorTest {
  @Parameters
  public static Iterable<Object[]> data() {
      return Arrays.asList(new Object[][] { { 1, 1 }, { -2, 2 } });
  }
  @Parameter
  public int fInput;
  @Parameter(1)
  public int fExpected;
  @Test
  public void testNantoka() {
    assertEquals(fExpected, Math.abs(fInput));
  }
}
```

---
# JUnit5 M1 の個人的な感想

- 普通の機能はそのまま。
- experimentalで便利な機能を標準機能に昇格させる。
- テストメソッドだけで機能が完結するような設計にする。
    - `Rule` の廃止。`ExtendWith`による新設計

---
# 興味を持ったら。

- https://github.com/junit-team/junit5-samples
    - サンプルプロジェクト
    - gradleのJUnit5プラグインとか試せます。
    - コードに絵文字が普通に入っているので環境によっては修正必要かも

---
# IDE
- IntelliJ IDEA 2016.2 がおすすめ。
    - テストクラス右クリックからテスト実行できます。
    - テストメソッドだと実行はできるが謎のエラーが出る。:disappointed_relieved: 

---
# JUnit4なプロジェクトの場合

-  `@RunWith(JUnitPlatform.class)`で、ツール側にはJUnit4のテストだとみせかけつつ、中身はJUnit5のテストを実行するとができる。

---

```java
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

@RunWith(JUnitPlatform.class)
public class JUnit4ClassDemo {
    @Test
    void succeedingTest() {
    }
    @Test
    void failingTest() {
        fail("Failing for failing's sake.");
    }
}
```
---
# 今回触れてないこと

- 例外を想定するテスト
    - 簡潔に書けるようになりました。
    - `ExpectedException`というRuleは消えます。
- Interface の `default`メソッドのテスト
- 他にも色々あるとおもいます。多分。 :sweat_smile: 

---
# 参考文献

- http://junit.org/junit5/docs/5.0.0-M1/user-guide/
- http://blog.codefx.org/libraries/junit-5-dynamic-tests/

---

# ご清聴ありがとうございました！ :bowtie: