from old JUnit to modern JUnit

Preview:

DESCRIPTION

関西Javaエンジニアの会'13 7月度の発表資料です。

Citation preview

from old JUnitto modern JUnit

関西Javaエンジニアの会'13 7月度@irof

@irof========* ふつうのプログラマ * TDD

* Java, Jenkins

* Groovy, Gradle, Git

関西Javaエンジニアの会, hoge駆動,

大阪Jenkins勉強会……とかの中の人。

タイトルの元ネタ(Java1.4から7へアップグレードするのいい資料なので是非)

JUnitの話をだらだらします

おしながき

JUnitを使うわけ

良いテストコードとは

JUnitの進化

JUnit4を使いこなす

JUnitを使うわけ

テスティングフレームワーク

テストを実行する

テスト結果を検証する

テストのフォーマットを提供する

実行方法、記述方法を統一することで、知っている人なら誰でも読めて実行できるようにするのが目的。

xUnitを使うわけ

みんな使ってるから。

テスト実行時に興味の無いことをやってくれるから。

他のツールと連携してくれるから。

IDE, ビルドツール, CI, カバレッジ, テストレポート, etc...

TestNGでないわけ

とくにない。

おしながき

JUnitを使うわけ

良いテストコードとは

JUnitの進化

JUnit4を使いこなす

良いテストコードとは

F.I.R.S.T.

Fast - 高速

Independent - 独立

Repeatable - 再現

Self-Validating - 自己検証

Timely - 適時

A-TRIP

Automatic - 自動

Thorough - 徹底

Repeatable - 再現

Independent - 独立

Professional - 専門的

以上は借りてきた言葉。

良いテストコードとは

失敗の扱いがうまい

読みやすい

失敗の扱いがうまい

失敗すること

すぐ失敗すること

何故失敗したかわかること

どうするべきかわかること

失敗時の振る舞いで良し悪しが決まる

テストの価値は

失敗にある

詳しくはSlideShareで

読みやすい

テストコードはプロダクトコードよりも可読性が求められる。

何故か?

テストのテストは困難。

テストのバグはレビューで潰す?

可読性が高いとバグが減る

“極限まで可読性の高いコードにバグが混入する可能性は限りなく低い”

ってブログに書いてた。私の。

可読性のための構造化

たとえば4フェーズテスト(xUTP)を使う

Four-Phase Test

@Test public void hoge() { Hoge sut = new Hoge(); String actual = sut.hoge(); assertThat(actual, is("fuga")); }

フェーズの間を1行空けるとかsetup

exercise

verify

構造がわかると読みやすくなる

おしながき

JUnitを使うわけ

良いテストコードとは

JUnitの進化

JUnit4を使いこなす

JUnitの進化

JUnit 3

public class JUnit3Test extends TestCase {  public void testHoge() {  assertEquals(2, 1); }}

JUnit 4

public class JUnit4Test {  @Test public void hoge() {  assertThat(1, is(2)); }}

TestCaseの継承が不要。

メソッド名のtest始まり制約が不要。

メソッドに@Testを付ける。

assertThatが標準(個人の趣味)

JUnit3 to JUnit4

何が嬉しい?

TestCaseの継承が不要。Javaの継承は1クラスのみ。

いざと言う時のカードが残せる。

何が嬉しい?

メソッド名のtest始まり制約が不要。

testのtypoが無くなる。

日本語テストメソッド名の違和感が軽減される。

何が嬉しい?

assertThatが標準。Matcherが使える。

あと引数の順番(ブログ参照)

※補足※

assertThatはJUnit4.4でAssertクラスに追加されたが、hamcrestを直接使用すればJUnit3でも使える。

所詮AssertionErrorを投げるだけだし。

JUnit4.4以降の主な機能

4.4 - assertThat, Theories

4.7 - Rule(MethodRule)

4.8 - Categories

4.9 - TestRule

4.10 - RuleChain

4.11 - FixMethodOrder

※個人の趣味で抜粋

おしながき

JUnitを使うわけ

良いテストコードとは

JUnitの進化

JUnit4を使いこなす

JUnit4を使いこなす

JUnit4の三本柱

MatcherRuleRunner

Matcher

ひとまとまりの検証に名前をつけてひとまとめにする。

テストコード自体の可読性の向上

失敗時メッセージの可読性の向上

describeTo/describeMismatchで失敗時のメッセージを編集可能。

describeMismatchはhamcrest1.2以降(最新は1.3)JUnit実践入門は1.1のため未掲載

Matcherの使い方

assertThat(today, is(dateOf(2013, 2, 3)));

java.lang.AssertionError: Expected: is "2013/02/03" but: "2013/07/31" at org.hamcrest.MatcherAssert.assertThat(MatcherAssert at org.junit.Assert.assertThat(Assert.java:865) at org.junit.Assert.assertThat(Assert.java:832) at JUnit4Test.hoge(JUnit4Test.java:24) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native

describeMismatchで編集可

describeToで編集可

メッセージがわかりやすい!

ステキ!!

Rule

とりあえずExpectedExceptionは覚える。

他はおいおいでも……

@Ruleと@ClassRuleがある。

基本は@Ruleを使う。

Ruleの活用例

例外を検証するRuleとか(後述)

Logを検証するRuleとか(作れる)

TestWatcherを拡張すると捗る。

starting/finished

succeeded/failed/skipped

例外のテスト

old Exception Test

@Test public void hoge() { try { sut.hoge(); fail(); } catch(NullPointerException e) { assertEquals("ぬるぽ", e.getMessage()); } }

modern Exception Test

@Test(expected = NullpointerException.class)public void hoge() { sut.hoge();}

例外の型だけで良いならこれでおk

modern Exception Test

@Rulepublic ExpectedException thrown = ExpectedException.none();

@Testpublic void hoge() { thrown.expect(NullPointerException.class); thrown.expectMessage("ぬるぽ"); sut.hoge();}

modern Exception Test

例外が発生しなかった場合の fail を書かなくて良い(忘れない)。

try-catchのような構造がテストコード内に出現しない。

(例外の検証にMatcherを使える)

Ruleを使えば継承無しで横断的なルールを適用できる!

しかも組み合わせ放題!(継承では難しい)

ステキ!!

Runner

JUnitの実行方法を制御する。

標準機能で以下が提供。

Enclosed

Parameterized

Theories

Suite

Categories

Runnerの活用例

Arquillian

WebコンテナでJUnitのテストを実行する。

SpringTest

ApplicationContextの初期化をしてくれたりする。

Runnerをいじる

「実行方法の制御」

その気になれば何でもできる。

TestNGのテストも実行できる。

ネタだけど

続きはWebで

JavaAdventCalendar2011で似たこと書いてます。

まとめ

まとめ

JUnitも進化してます。

昔の常識、今は?

最新を追うと色々見えて楽しい。

one more thing...

Groovy x JUnit

Groovy x JUnit

JUnitのテストをGroovyで書く。

Spockを使う。

JUnitを拡張したフレームワーク

@RunWith(Sputnik.class)

JUnitとして実行できる!

Spockの例

class HelloSpock extends spock.lang.Specification {    def "length of Spock's and his friends' names"() {        expect:        name.size() == length

        where:        name     | length        "Spock"  | 5        "Kirk"   | 4        "Scotty" | 6    }}

詳しくは別の機会に。

Recommended