Slide 1

Slide 1 text

JUnit5の味見 2017.06.24 KANJAVA PARTY 2017 !!!

Slide 2

Slide 2 text

…のつもりが がっつり食べちゃった

Slide 3

Slide 3 text

提供は • 93年からずっとプログラマー • 主にというかほぼJavaプログラマー • たまにアジャイルコーチ的なこともしてる 山根 英次 e_yamane yamane.eiji

Slide 4

Slide 4 text

はじめに • JUnit5のUser Guideを元にJUnit5の説明をしまーす • ならべくちゃんと動かしながらやるよ • JUnit4は知ってる前提で喋ります

Slide 5

Slide 5 text

お詫び • JUnit5 Milestone 4をベースをベースとしています。正式リリース版とは振る舞いが異なる可能性がありま す • User Guideに無い事もたまにしゃべりまーす • 英訳はかなり適当なので怪しそうなら原典にあたってね • 私見が多分に含まれていますので怪しそうなら原典を当たってね • とても1時間じゃ終わりません • タイムマネジメントを放棄します • 私が付けた優先順位順に説明させていただきます • アップするスライドはちゃんとした順序で上げる予定です • 多分かなりハイスピードになるので詳しくはお家でゆっくり見てね

Slide 6

Slide 6 text

関連URL • JUnit5 Users Guide • http://junit.org/junit5/docs/current/user-guide/ • JUnit5 API Reference • http://junit.org/junit5/docs/current/api/ • 今日利用したコード • https://github.com/e-yamane/junit5-study

Slide 7

Slide 7 text

うんちく • JUnit5は一時開発終了の危機があった • クラウドファウンディングで資金調達を呼びかけてた • 日本の人も結構協力してまーす • http://junit.org/junit4/junit-lambda-contributors.html • ここに載ってる人達には感謝してもいいんじゃないかな

Slide 8

Slide 8 text

本編いくよ〜

Slide 9

Slide 9 text

1.Overview • 包括的に書いてるからコレさえ読んでればOKだよ • さすがにそうではなかったけどね • JUnit5は3つのサブプロジェクトで構成されてるよ • JUnit Platformはテストの実行するための基盤を提供するよ • JUnit Jupiterはテスト記述者やエンジン拡張用のAPIを提供してるよ • 一番意識するのはこのサブプロジェクト • JUnit Vintageは、JUnit3やJUnit4のテストをJUnit5のTest Engineで実行するためのTest Engineを提 供するよ • JUnit5はJava8でしか動かないよ。でもそれ以前のバージョンでコンパイルしたコードを テストすること自体はできるよ

Slide 10

Slide 10 text

2. Installation • 正式版とマイルストーン版はMaven Centralにあるよ • SnapshotはSonatypeにしかないからね

Slide 11

Slide 11 text

2.1. Dependency Metadata 2.1.1. JUnit Platform Group ID Version Artifact IDs org.junit.platform 1.0.0-M4 junit-platform-commons JUnit内部の共通ライブラリ。使用禁止 junit-platform-console JUnit5をコンソールから実行するためのランナー junit-platform-console-standalone めんどくさい人用。全部乗せ junit-platform-engine エンジンエンジン用のAPI junit-platform-gradle-plugin GradleでJUnit5を動作させるためのプラグイン junit-platform-launcher IDEや、ビルドツールがJUnitの設定や実行を行うためのAPI junit-platform-runner JUnit4の実行系でJUnit5のテストコードを実行できるようにするライブラリ junit-platform-suite-api テストの設定を記述するアノテーションを定義しているライブラリだよ。 junit-platform-surefire-provider Maven surefire用のライブラリ

Slide 12

Slide 12 text

2.1. Dependency Metadata 2.1.2. JUnit Jupiter Group ID Version Artifact IDs org.junit.jupiter 5.0.0-M4 junit-jupiter-api テストとテストを拡張するために利用するAPI junit-jupiter-engine Jupiterテストエンジンの本体。実行時だけあればいいよ junit-jupiter-params Parameterized Test用のAPI junit-jupiter-migration-support JUnit4のいくつかのRuleの移行用のライブラリ

Slide 13

Slide 13 text

2.1. Dependency Metadata 2.1.3. JUnit Vintage Group ID Version Artifact IDs org.junit.vintage 4.12.0-M4 junit-vintage-engine JUnit4またはJUnit3のテストをJunit Platformで実行できるテスト エンジン

Slide 14

Slide 14 text

2.2. Dependency Diagram junit-platform-console-standalone

Slide 15

Slide 15 text

2.3. JUnit Jupiter Sample Projects • 手っ取り早く動かしたいならここにサンプルがあるよ • Gradle • https://github.com/junit-team/junit5-samples/tree/r5.0.0-M4/junit5-gradle-consumer • Maven • https://github.com/junit-team/junit5-samples/tree/r5.0.0-M4/junit5-maven-consumer

Slide 16

Slide 16 text

3. Writing Tests

Slide 17

Slide 17 text

…の前に!! 動かないテストコードはただのゴミなので

Slide 18

Slide 18 text

4. Running Tests 4.1. IDE Support • IntelliJ IDEA • ここにやり方書いてるよ! • https://blog.jetbrains.com/idea/2016/08/using-junit-5-in-intellij-idea/ • 試してないから分かりません • Eclipse Beta Support • Oxygenからベータサポートしてるよ • ここにやり方書いてあるよ • https://wiki.eclipse.org/JDT_UI/JUnit_5 • かなり、面倒いそしてダメだった…orz • Other IDEs • 今はサポートしてないよ • Console LauncherかJUnit4ベースのRunnerで実行してね

Slide 19

Slide 19 text

4. Running Tests 4.2.1. Gradle Support(1) • ごちゃごちゃ書いてあるけど、最終リリースまでに変更される可能性が非 常に高いとのことでまじめに読まなくてもいいです • 必要最低限の部分をコードで説明しまーす • build.gradle

Slide 20

Slide 20 text

4. Running Tests 4.2.1. Gradle Support(2) • テスト実行は「junitPlatformTest」タスクで実行 • 「test」でも実行できるけどね • All OKならexit コードは0、それ以外は1 • 現時点では、テスト実行してテスト結果のXMLファイルを作成するだけで テストレポートは出力しません • Jenkinsで見れるよねだって • でも変!!

Slide 21

Slide 21 text

4. Running Tests 4.2.2. Maven • 興味が無いのでスキップ

Slide 22

Slide 22 text

4. Running Tests 4.3. Console Launcher • 興味が無いのでスキップ

Slide 23

Slide 23 text

4. Running Tests 4.4. Using JUnit 4 to Run the JUnit Platform • JUnit4のRunnerでJUnit5のテストを動かす方法 • 一番手っ取り早いので、以降は基本的にこの方法でやります • @RunWith(JUnitPlatform.class)と書けば良い • Junit Platformの全機能が使えるわけではないです • 「7. Advanced Topics」以外は問題ありません • 設定方法(内部参照ライブラリ省略) 1. junit(4x)をtestスコープで参照 2. junit-platform-runnerをtest スコープで参照 3. junit-jupiter-apiをtestスコープで参照(JUnit5の記述に必須) 4. junit-jupiter-engineをtestRuntimeスコープで参照

Slide 24

Slide 24 text

あらためて、3. Writing Tests

Slide 25

Slide 25 text

…の前に!! まだ、正式リリースではないので。。。

Slide 26

Slide 26 text

8.API Evolution • JUnit5のAPIには@APIアノテー ションでAPIの成熟度が表現され ているので成熟度が低い物につ いては変わるものだと思ってくだ さい • JUnitPlatformは「 Maintained」です Internal 内部での利用を前提。自己責任で Deprecated 非推奨。消えても知らんで Experimental 実験中。消えたり変わったりするかも Maintained 少なくとも現在のメジャーバージョンの次のマ イナーリリースまでは変わらない Stable 現在のメジャーバージョン中は変わらない

Slide 27

Slide 27 text

やっと、、、3. Writing Tests

Slide 28

Slide 28 text

3.Writing Tests • コード見ましょうか • FirstJUnit5Tests.java • テストクラスはpublicじゃなくていいです • テストメソッドもpublicじゃなくていいです • publicじゃなくても良くなったのはコード補完で助かるので良いことです • @Testはパッケージが違います • org.junit.jupiter.api

Slide 29

Slide 29 text

3.1. Annotations @Test Stable テストメソッドに付けるJUnit4の@Testに有った属性は無くなった(別の方法で実現) @RepeatedTest Experimental 同じテストを複数回繰り返したい場合に付与するアノテーション @TestFactory Experimental 動的にテストを生成するファクトリとなるメソッドに付与するアノテーション @DisplayName Experimental テストレポート用に名前をつけられるよ(つけられるとは言ってないw) @BeforeEach Stable JUnit4の@Beforeと同じ @AfterEach Stable JUnit4の@Afterと同じ @BeforeAll Maintained JUnit4の@BeforeClassと同じ。staticメソッドとして記述すること @AfterAll Maintained JUnit4の@AfterClassと同じ。staticメソッドとして記述すること @Nested Experimental ネストされた非静的なテストクラスにつける。@Enclosedとはちょっと違う @Tag Maintained JUnit4の@Category的なもの。@Tagsと言うのもある @Disabled Stable JUnit4の@Ignore的なもの @ExtendWith Experimental @Rule/@ClassRuleに変わる拡張点の指定アノテーション

Slide 30

Slide 30 text

3.1.1. Meta-Annotations and Composed Annotations • Jupiterのアノテーションはメタ注釈として利用できるよ • JUnit5のアノテーションはアノテーションにアノテートすることができるよ • JUnit5のアノテーションをアノテートしたアノテーションをアノテートするとアノテー ションにアノテートしたJUnit5のアノテーションをアノテートしたことと同義と見なす • 訳わかんないよねwコード見ると簡単なんです。 • SlowTest.java • SlowTestTest.java • (JUnit5上で独自のテスティングフレームワーク作る人には)超重要!!

Slide 31

Slide 31 text

3.2. Standard Test Class • 単なるサンプルコードで読めば分かるのでスキップ!

Slide 32

Slide 32 text

3.3. Display Names(1) • メソッド名やクラス名じゃなくて独自に表示名を変えるためのアノテーション • 時代が俺に追いつきました! • 「Java Press Vol 43」(2005/7/15発売)で「テストレポート日本語化計画」とか書いてました • http://gihyo.jp/magazine/javapress/archive/2005/vol43 • …と思ったんだけど • DisplayNameTest.java • DisplayNameForJUnit4Test.java

Slide 33

Slide 33 text

3.3. Display Names(2) • Gradleでtestを実行してもテスト結果には反映されません!! • テストこかすと見えます • XMLのタグの中に出力されてるだけ • 当然Jenkinsのテストレポートにも表示されません • JUnitPlatform越しに実行するとちゃんと出る!!

Slide 34

Slide 34 text

3.4.Assertions(1) • org.junit.jupiter.api.Assertions(Maintained)配下にあるよ • JUnit4の代替のAPIはあるよ(全部ぢゃないよ)

Slide 35

Slide 35 text

3.4.Assertions(2) JUnit4にもあるAssertion • assertArrayEquals • assertEquals/assertNotEquals • assertFalse/assertTrue • BooleanSupplierもOK • assertNotNull/assertNull • assertNotSame/assertSame • fail • 浮動小数点のdeltaナシは何故かDeprecatedから通常に昇格(?) • エラーメッセージは第1引数から最終引数に変更。メッセージはラムダで渡せる • エラー発生まで遅延評価されるので正常時に高速にテストが行える • AssertEqualsTest.java

Slide 36

Slide 36 text

3.4.Assertions(3) 新API: assertAll • メッセージは第1引数ですw • 複数のテストを一気にやる! • 1つがこけても全部やってくれる • エラー報告も全部でる • 良い子 • ちなみに、parallelStream渡すと並列実行できます!! • AssertAllTest.java

Slide 37

Slide 37 text

3.4.Assertions(4) 新API: assertIterableEquals • Iterable同士の比較 • IterableだからStreamはできない...

Slide 38

Slide 38 text

3.4.Assertions(5) 新API: assertLinesMatch • 文字列のList同士の比較 • 第1引数側に正規表現を渡せば正規表現としてマッチしてるかどうかの 検証もしてくれる • 。。。ん〜Core APIレベルでいるか!?

Slide 39

Slide 39 text

3.4.Assertions(6) 新API: assertThrows • JUnit4の@Testのexpectedの代替 • assertionの戻り値として発生した例外を受け取れるので、発生した例外の 精査もできるよ • 良い子 • AssertThrowsTest.java

Slide 40

Slide 40 text

3.4.Assertions(7) 新API: assertTimeout/ assertTimeoutPreemptively • JUnit4の@Testのtimeoutの代替 • テストメソッド全体ではなく、検査対象を絞れるのでより厳密にチェックできる • assertTimeoutとassertTimeoutPreemptivelyの違い • assertTimeoutはタイムアウトしても検証処理自体は継続 • assertTimeoutPreemptivelyはタイムアウト検知で検証処理を中断(interruput) • assertTimeoutPreemptivelyは検査対象処理は別スレッドで実行するため、ThreadLocalを利用しているコードは要注意 • 戻り値も例外も受け取れます! • より検証範囲を局所化できるよ • 良い子 • AssertTimeoutTest.java

Slide 41

Slide 41 text

3.4.Assertions(8) 無くなったAssertion assertThat!!

Slide 42

Slide 42 text

3.4.1.Third-party Assertion Libraries • assertThatが無いとか「xxxが無い」とか文句言わない • 使えるようにしといたから勝手にすればいいじゃ無い • HamcrestAssertionTest.java

Slide 43

Slide 43 text

3.5.Assumptions(1) • org.junit.jupiter.Assumptions (Maintained)にあるよ • JUnit 4.4から導入 • 思い入れはない • 事前条件チェックの表明 • 事前条件違反をエラーにしない(skip扱い)

Slide 44

Slide 44 text

3.5.Assumptions(2) • JUnit4にもあるAssumptions • assumeFalse/assumeTrue • JUnit5で無くなったAssumptions • assumeNoException/assumeNotNull/assumeThat • 新規に追加Assumptions • assumingThat • 第1引数がtrueの場合のみ第2引数のExecutableを評価 • AssumptionsTest.java

Slide 45

Slide 45 text

3.6. Disabling Tests • @Disabledを付けたテストクラスやメソッドはテストを行いません(skip扱い) • JUnit4の@Ignoreと同じ • DisabledClassTest.java • DisabledMethodTest.java

Slide 46

Slide 46 text

3.7. Tagging and Filtering • テストエンジンの実装によってフィルタリングするのに用いる • JUnit4の@Categoryと似たもの • フレームワーク上で何らかのマークしたい場合も使えば良いんじゃな い? • @Tagsってのもあるけど忘れていい(JavaDocにもそう書いてある) • TaggingTest.java

Slide 47

Slide 47 text

3.8. Nested Tests • テストメソッドを意味ある形でグルーピングする場合に内部クラス側に @Nestedと付ける • JUnit4のEnclosedに相当、RunWithで実現している方法と比較すると便利 • ネストは何段階でもOK! • ネストクラスは静的クラスじゃダメ。JUnit4とは違うので注意 • 静的じゃないからBeforeAllとAfterAllは使えないよ • TestingAStackTest.java

Slide 48

Slide 48 text

3.9. Dependency Injection for Constructors and Methods(1) • テストクラスのコンストラクタ、@Test、@TestFactory、@BeforeEach、 @AfterEach、@BeforeAll、@AfterAllが付与されたメソッドはパラメタを持 つことができるよ • パラメタの解決は登録されたParameterResolver(Experimental)が行うよ(説 明はあとで) • Jupiterは3つのParameterResolverがBuild-inされてるいよ

Slide 49

Slide 49 text

3.9. Dependency Injection for Constructors and Methods(2) TestInfoParameterResolverとTestInfo • TestInfoParameterResolverはTestInfo(Experimental)型の引数にInjectionする ParameterResolverです • JUnit4のTestNameの代替として利用可能 • TestInfoは以下のプロパティを持つ • displayName:@DisplayNameのvalue。省略時はメソッド名 • tags:付与されたタグのSet • testClass:テストクラス • testMethod:テストメソッド • TestInfoTest.java

Slide 50

Slide 50 text

3.9. Dependency Injection for Constructors and Methods(3) RepetitionInfoParameterResolverとRepetitionInfo • RepetitionInfoParameterResolverはRepetitionInfo(Experimental)型の引数 にInjectionするParameterResolverです • @RepeatedTest, @BeforeEach, @AfterEachが付いているメソッドに対して のみインジェクション可能 • 詳細はRepeated Tests(3.11)で

Slide 51

Slide 51 text

3.9. Dependency Injection for Constructors and Methods(4) TestReporterParameterResolverとTestReporter • TestReporterParameterResolverはTestReporter (Experimental)型の引数に InjectionするParameterResolverです • テストの動向を独自に記憶させてテストエンジン側で拾ったりできるらし い • テストエンジン側では、TestExecutionListener.reportingEntryPublished()を 介してアクセスできるらしい • テストエンジンに手をることに興味はないのでちゃんと調べてません • TestReporterTest.java

Slide 52

Slide 52 text

3.9. Dependency Injection for Constructors and Methods(5) 独自のParameterResolver • 独自にParameterResolverを必要とする場合 • ParameterResolverを実装したクラスを作成する • 作成したクラスを@ExtendWithに記述 • 具体的には後(ExtensionModel) • MockitoExtension.java • MyMockitoTest.java

Slide 53

Slide 53 text

3.10. Test Interfaces and Default Methods • @Test,@TestFactory,@BeforeEach,@AfterEachをインタフェースのデフォルトメソッドで定 義できるよ • @BeforeAllや、@AfterAllもインタフェースのstaticメソッドで記述しておけば参照されるよ • @Tagや、@ExtendWithも引き継がれるよ • 再利用性とか考えるとこの形式で共通処理を作るよりはExtendWithによる拡張の方がい い気がする • TestLifecycleLogger.java/TestInterfaceDynamicTestsDemo.java/TimeExecutionLogger.java/TestInterf aceDemo.java • Testable.java/EqualsContract.java/ComparableContract.java/StringTests.java

Slide 54

Slide 54 text

3.11. Repeated Tests (1) • @ RepeatedTestアノテーションを付与したメソッドは指定回実行される • 例えば乱数が想定の範囲内であることとかリークの検出とか。。。に使うかなぁ • 個々のテスト毎に@Testと同様の@BeforeEachや@AfterEachは呼び出されます • @RepeatedTestや@BeforeEach等が付いてるメソッドがRepetitionInfo型のパラメタを持つ場合は自動でインジェクショ ンされる • RepetitionInfoは以下のプロパティを持つ • currentRepetition:実行回数(1相対) • totalRepetitions:最大実行回数(1相対) • RepetitionInfoを@BeforeEachや@AfterEachでRepetitionInfoを受ける場合、同一テストクラスで@RepeatedTestと@Test の混在はできない • SimpleRepeartedTest.java

Slide 55

Slide 55 text

3.11. Repeated Tests (2) 表示名の変更 • @RepeatedTestにname属性を付けることで表示名を変更できます • {displayName}とつけるとTestInfoのdisplayNameに置き換わる • {currentRepetition}と付けると現在の実行回数に置き換わる • {totalRepetitions}と付けるとそう実行総数に置き換わる • 省略時は” repetition {currentRepetition} of {totalRepetitions}”という文字列が適用 される • RepeatedTestsDemoTest.java

Slide 56

Slide 56 text

3.12. Parameterized Tests(1) • @ParameterizedTest(Experimental)を付けることでテストデータとテストコードを分離することが できます • JUnit4でもランナーの切り替えである程度可能だったが不便 • junit-jupiter-paramsが別途必要 • ParameterizedTestを書くには • 対象テストメソッドに@ParameterizedTestアノテーションをアノテートする • @XXXSourceを合わせてアノテートする • アノテートしないとそのテストはテストとして認識されない • 引数を受ける(引数受けなくても指定引数分テストは繰り返すだけでエラーにはならない) • Jupiterは6つのXXXSourceはbuild-inされてます

Slide 57

Slide 57 text

3.12. Parameterized Tests(2) @ValueSource, @EnumSource • @ValueSource(Experimental)は引数にString、int,long,doubleのいづれか1つの配列を指 定することで実現する • 複数の指定はできない • あんまり便利じゃないと思われ • @EnumSource(Experimental)は引数に指定したEnumをパラメタとして扱う • namesを指定するとその名前のEnumだけをパラメタとする • typoはエラーになります • あんまり便利じゃないと思われ • SimplePerameterizedTest.java

Slide 58

Slide 58 text

3.12. Parameterized Tests(3) @MethodSource • @MethodSource(Experimental)はnamesに指定したメソッドからの返却値をパラメタとして用いる • 複数パラメタの埋め込みもOK • nameじゃなくてnamesなのは複数メソッドを指定してもいいから • 指定するメソッドは、staticメソッドで引数なし • 戻り値はStream,Iterable,Iterator,または配列 • ParallelStream渡してもテストは並列には流れない orz • 複数引数をパラメタ化する場合はArguments(Experimental)を返すメソッドを用意する • Argumentsオブジェクトを生成するにはObjectArrayArguments(Experimental)を用いると良いらしい • MethodSourceParameterizedTest.java

Slide 59

Slide 59 text

3.12. Parameterized Tests(4) @CsvSource/CsvFileSource • @CSVSource(Experimental)はvalueの値をCSVの1行と捉えてパラメタに渡す • delimiterをデータに加える場合はシングルクォートで囲む • delimiterは変更可能 • 改行をデータに加える場合もシングルクォートで囲む • @CsvFileSource(Experimental)はCSVファイルとしてデータを読み込む • resourcesにファイル名をクラスパスで指定、複数形なので複数して可能 • テストクラスからの相対パスで記述可能 • encoding(UTF-8),delimiter, lineSeparator(¥n)は変更可能 • パラメタは許容できるものは暗黙型変換が走る • カラム数<引数の場合はエラー、カラム数>引数の場合は無視 • カラム省略時はnull、Primitive型へは変換できないのでエラーとなる • 空文字のテストはできないかな? • CsvSourceParameterizedTest.java

Slide 60

Slide 60 text

3.12. Parameterized Tests(5) @ArgumentsSource • 上記以外の方法でパラメタを提供したい場合は@ArgumentsSource(Experimental)を利用 • 引数には、ArgumentsProvider(Experimental)を実装したクラスを指定する • ArgumentsProviderにあるargumentsメソッドの引数ContainerExtensionContextの説明は後で(やらないかも。。。) • パラメタは許容できるものは暗黙型変換が走る(後で) • UserGuideの例はArgumentsProviderの実装とデータが分離してないので再利用しにくいです • 汎用性を高めるためには… • ArgumentsSourceをアノテートしたアノテーションを定義する • 定義したアノテーションにパラメタを用意しデータを任意に取り込めるようにする • ArgumentsProviderと共にAnnotationConsumer(Experimental)を実装したクラスを用意する • acceptメソッドでアノテートされた情報を引き寄せる • 引き寄せた情報からパラメタを生成する • ArgumentsSourceParameterizedTest.java • MoreGenericPerameterizedTest.java

Slide 61

Slide 61 text

3.12. Parameterized Tests(6) 暗黙型変換 • User Guideはごちゃごちゃ書いててわかりにくいので • valueOf(String)メソッドを呼び出して変換してるもの • boolean/Boolean/byte/Byte/int/Integer/long/Long/float/Float/double/Double/Enum • parse(String)メソッドを呼び出して変換してるもの • Instant/LocalDate/LocalDateTime/LocalTime/OffsetDateTime/OffsetTime/Year/YearM onth/ZonedDateTime • ImplicitConversionTest.java

Slide 62

Slide 62 text

3.12. Parameterized Tests(7) 明示的型変換 • 引数毎に@ConvertWith(Experimental) を付与して個別に好き勝手な変換ができるよ • 引数にはArgumentConverter(Experimental)を実装したクラスを指定する • SimpleArgumentConverter(Experimental)を利用すると若干楽に実装できるかな • 引数毎にってところが使い勝手悪いよねぇとは個人的には思う • 別アノテーション作成すれば多少緩和されますが。。。 • JupiterにはJavaTimeArgumentConverterという明示的型変換をおこなているクラスがある ので参考にしたらいいよ • 利用するときは@ JavaTimeConversionPattern(Experimental)経由で • ExplicitConversionTest.java

Slide 63

Slide 63 text

3.12. Parameterized Tests(8) 表示名の拡張 • @ParameterizedTestのname属性で出力内容を変更できます • {index}:テスト実行回数(1相対) • {arguments}:全テストパラメータ • {0},{1}…:指定された引数 • やっぱり、結果XMLには反映されない。。。 • CustomizingDisplayNamesTest.java

Slide 64

Slide 64 text

3.12. Parameterized Tests(9) 3.12.5. Lifecycle and Interoperability • ParameterizedTestの個々のテストは@Testと同様のライフサイクルだよ • @BeforeEach、@AfterEachは個々のテスト前後で呼び出される • ParameterizedTestもTestと同様ParameterResolverで解決されたパラメタを 渡せますが、パラメタは最後の付与ししないとダメ • LifecycleAndInteroperabilityTest.java

Slide 65

Slide 65 text

3.13. Dynamic Tests • テストを動的に作れるよ • テストを作るメソッドは、@TestFactoryをアノテートしたメソッドで供給するよ • @TestFactoryは、DynamicTest(Experimental)のCollection,Iterable,Iterater、配列を返却しない といけないよ • DyamicTest以外を返すとランナーはエラーを検知するがXML結果ファイルにはエラーが記録されない? • DynamicTestは通常のテストケースと違い個々のテスト毎には@BerefoEach等のコールバック は行われません • @TestFactory毎にコールバックされる • DynamicTestはファクトリメソッド(DynamicTest.dynamicTest/stream)経由で作って欲しいとの事 • DynamicTestsDemoTest.java

Slide 66

Slide 66 text

5. Extension Model 5.1 Overview • JUnit4の時のRunWithによるランナー拡張/@Rule/@ClassRuleのような機 能はJUnit5ではExtention APIに統一されたよ • Extention(Experimental)自体はただのマーカーインタフェースなので機 能拡張したい場合は目的に応じたインタフェースを適時実装してね

Slide 67

Slide 67 text

5.2. Registering Extensions • Extensionを登録するには以下の2つの方法があるよ • @ExtendWithによる宣言的登録 • JavaのServiceLoaderを利用した自動的登録

Slide 68

Slide 68 text

5.2.1. Declarative Extension Registration • @ExtendWtihはクラス、インタフェース、メソッド、アノテーションに付与で きる • Extensionは1つ@ExtendWithに複数書くこともできるし、複数の @ExtendWithを定義してもいいよ • ExtendWithTest.java

Slide 69

Slide 69 text

5.2.2. Automatic Extension Registration • @ExtendWithっていちいち書かなくてもJavaのServiceLoader機構使えば 自動でExtensionの登録ができます 1. META-INF/services/org.junit.jupiter.api.extension.Extensionと言うファイルを作っ てその中に自動登録したいExtensionを実装しているクラスのFQCNを記述する 2. システムプロパティ「junit.extensions.autodetection.enabled」にtrueをセットする • AutomaticExtensionRegistrationTest.java

Slide 70

Slide 70 text

5.2.3.Extension Inheritance • 親クラスやインタフェースに記述したExtensionは継承される • クラスに記述したExtensionは各テストメソッドにも適用される • 同一Extensionを複数適用することはできない • エラーにはならず無視される • ExtensionInheritanceTest.java

Slide 71

Slide 71 text

5.3. Conditional Test Execution(1) • ある条件が満たすor満たさない場合にテストの実行を取りやめるExtension • ContainerExecutionCondition:テストクラス全体を取り止めたい場合に作成 • TestExecutionCondition:テストメソッドの実行を取りやめたい場合に作成 • ともにExperimental • それぞれevaluatedと言うAPIを持つ(引数が違う) • 戻り値は • テストをスキップしたい場合はConditionEvaluationResult#disable(String)の戻り値 • テストを実行していい場合はConditionEvaluationResult#enable(String)の戻り値 • のいずれかを返却。ConditionEvaluationResultはExperimental • @Disableでスキップできるのはこの拡張機能の実装であるDisabledConditionがbuild-inされてるから • 複数のConditionが適用されている場合1つでもスキップと判断するConditionがあればそのテストはスキップされる • Assumption使うよりはいい気がする • ConditionCheckTest.java • CapriciousConditionTest.java

Slide 72

Slide 72 text

5.3. Conditional Test Execution(2) • システムプロパティ「junit.conditions.deactivate」に無効化するConditionのクラス 名を書くと、その対象となるConditionは無効となります • 「*」と書くと全てのConditionが無効になります • 「org.junit.*」と書くとorg.junitパッケージとそのサブパッケージ内にある全てのCondition が無効になります • 「 *.MyCondition」と書くとMyConditionと言う名のConditionが全て無効になります • 「 *System*」と書くとクラス名の一部に「System」とあるConditionが全て無効になります • 「 org.example.MyCondition」と書くとorg.example.MyConditionと言う名のConditionだけが 無効になります • ワイルドカードを書かない場合は全てFQCNと認識します

Slide 73

Slide 73 text

5.4. Test Instance Post-processing • TestInstancePostProcessor(Experimental)を実装したクラスをExtensionとし て登録するとテストクラスが実体化された後にコールバックを受けることが できます • DI的な動きさせるようなExtensionで使う • SpringExtensionや3.9で紹介したMockitoExtension.javaなどこのインタフェースの実 装例です • https://github.com/spring-projects/spring-framework/blob/master/spring- test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java

Slide 74

Slide 74 text

5.5. Parameter Resolution • ParameterResolver(Experimental)を実装したクラスをExtensionとして登録すると @BeforeAll, @AfterAll, @BeforeEach, @AfterEach, @Test, @TestFactoryがアノテートさ れてるメソッドに定義されているパラメタを解決することができます • 書いてないけど@RepeatedTestと@ParameterizedTestにも行けるよ • 同一メソッド、同一タイプの引数に対して複数のParameterResolverがインジェクション可 能(supportsメソッドがtrue)と返す場合はエラー • パラメタが定義されてるのに適切なParameterResolverが見つからない場合はエラーとな る • ParameterResolverTest.java • StringResolver.java/StringResolver2.java

Slide 75

Slide 75 text

5.6. Test Lifecycle Callbacks • テストの各種ライフサイクルに対するコールバックを受け取りたい場合は以下のいづれかの インタフェースの実装したクラスをExtensionとして登録する • BeforeAllCallback • BeforeEachCallback • BeforeTestExecutionCallback • AfterTestExecutionCallback • AfterEachCallback • AfterAllCallback • 全てExperimental • サンプルは5.10で

Slide 76

Slide 76 text

5.7. Exception Handling • TestExecutionExceptionHandler(Experimental)を実装したクラスを Extensionとして登録するとテストメソッドで発生した例外をハンドリングす ることができます • テストメソッドの例外ハンドリングだけなので@BeforeEach等で発生した例外のハン ドリングはできません • TestFactoryが返したDynamicTestの例外もハンドリングできません • ExceptionHandlerTest.java • ExceptionHandler.java

Slide 77

Slide 77 text

5.8. Keeping State in Extensions • Extensionで状態を保持したいならStoreを使ってね • Store自体に@APIはついてないけどOuterクラスのExtensionContextがExperimentalなので多分Storeも Experimental扱い • Store自体のライフサイクルはUserGuideに書いてない • Store自体は呼び出すたびに実体は変わるっぽい • ContainerExtensionContext経由で取得したStoreは同一テストクラスでテストしてる間有効っぽい • TestExtensionContext経由で取得したStoreは同一テストメソッドのライフサイクル終演まで有効っぽい • ちょっと追いきれてないので自信がありません • StoreTest.java • StoreExtension.java

Slide 78

Slide 78 text

5.9. Supported Utilities in Extensions • org.junit.platform.commons.supportパッケージにExtensionを作成する上 で有用なユーティリティがあります • AnnotationSupport:アノテーションを操作用のAPIなど • Maintained • ReflectionSupport:クラスやメソッドの検索用のAPIなど • Maintained • HierarchyTraversalMode:アノテーションの走査モードを表す列挙型 • Maintained

Slide 79

Slide 79 text

5.10. Relative Execution Order of User Code and Extensions • CallBackOrderTest.java • AllCallbacker.java • @BeforeEachとかの有無は関係なく コールバックされる • @NestedはBeforeAllの定義はでき ないのになぜかコールバックされる ContainerExecutionCondition TestInstancePostProcessor TestExecutionCondition

Slide 80

Slide 80 text

6. Migrating from Junit 6.1.Running JUnit 4 Tests on the JUnit Platform • junit-vintage-engineを使えばJUnit4やJUnit3のテストは実行できるよ • LegacyTest.java

Slide 81

Slide 81 text

6.2.Migration Tips • 既存のJUnit4のコードをJupiterに移行する際の注意点 • いろいろ書いてますが、vintage-engineもあるし書き換えなくていいと思います • どーしても書き換えたい人は以下を読めばいいんじゃ無いかな? • http://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4-tips

Slide 82

Slide 82 text

6.3. Limited JUnit 4 Rule Support • junit-jupiter-migration-supportを利用すれば以下のRuleはJupiterでも利用 できます • Verifier(VerifierSupportを登録する) • ExternalResource(ExternalResourceSupportを登録する) • ExpectedException(ExpectedExceptionSupportを登録する) • 3つともExperimental • VerifyTest.java

Slide 83

Slide 83 text

7.Advanced Topics • 力尽きた興味が無いのでスキップ • ここってIDEのプラグイン作ったりする人用っぽいし

Slide 84

Slide 84 text

User Guideに詳しく書いてないけど調査が必要なこと • 各種Context • ExtensionContext • TestExtensionContext • ContainerExtensionContext • ParameterContext • JUnit5で言うところのContainerってなに? • 「例えばテストクラス」という記述はあったけど。。。(5.3)

Slide 85

Slide 85 text

で、結局ありなん? • テストを書くという行為に関してはかなり良い • assertAll、assertThrows、assertTimeout、 assertTimeoutPreemptively、ParameterizedTest、Nested等は すぐにでも使いたい! • テスティング環境を整えるという点でも@Ruleや@RunWithで整えるよりはやるやすく感じ る • 個人的にはもぅJUnit5で行こうかとも思ってます • でも現時点では仕事では利用できないと思ってます • レポーティングがひどい • これが改善しないと辛いんじゃ無いかなぁ • 後ほとんどのAPIがまだExperimentalなのも怖いなぁ。。。

Slide 86

Slide 86 text

残念なお知らせ… • https://github.com/junit-team/junit5/milestones/ • 明日M5が出るようです…orz