LoginSignup
17

More than 5 years have passed since last update.

JUnit 5 M1 をやってみよう

Last updated at Posted at 2016-07-23
1 / 31

本資料について


自己紹介

  • 福原和朗 @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 という名前の由来


JUnit5で何が変わったか?

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

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


サンプル

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

//こんなボイラープレートコードは大変かも!
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の例

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

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
      • テストでログを吐きたい時の委譲先

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:

  • テスト名を個別につけられるようになった。
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が組み合わせて実行してくれます。動的です。


// 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のテストを実行するとができる。

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:

参考文献


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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17