SlideShare a Scribd company logo
1 of 27
JUnit の使い方
    assertThatとアノテーション


                CSG 市川




0
JUnit とは

       Java用の単体テストフレームワーク

           入力に対する出力が正しいかチェック
1
       Eclipseにはじめからプラグインが入っている

           なにもしなくても使える
テストの書き方

       テストメソッドに @Test をつける

           org.junit.Test を import しておく
2
       Run as -> JUnit Test で実行


            import org.junit.*;
            public class TestHoge {
              @Test
              public void はじめのテスト() {
                System.out.println("Hello, JUnit!");
              }
            }
アサーション

       実際に計算した結果が予想通りかをチェックする


3
       たくさんの種類があるけど assertThat 以外使わない

           assertEquals はもう時代遅れ


            static import org.junit.Assert.*;
            static import org.hamcrest.CoreMatchers.*;
            ...
              @Test
              public void フィボナッチ10() {
                assertThat(fib(10), is(55));
              }
            ...
assertThat

       汎用的なアサーションメソッド

           hamcrest ライブラリの Matcher と合わせて使う
4
           英語っぽい書き方になる

           どっちが actual でどっちが expected か迷わない


    assertThat(a, is(not(10)));
    assertThat(lst, hasItem("hoge"));
    assertThat(o1, is(sameInstance(o2));
    assertThat(x, anyOf(nullValue(), equalTo("x"));
    assertThat(s, isA(String.class));
万能 Matcher "is"

       プリミティブ型でも配列でもObject型でも大丈夫

           equals (とhashCode) さえあれば自作クラスもok
5
           ほかの Matcher を引数に取ることもできる

           equalTo と is は同じものだと思われる


    String[] expected1 = { "foo", "bar", "baz" };
    assertThat(array, is(expected1));

    List<Integer> expected2 = Arrays.asList(1, 2);
    assertThat(list, is(expected2));
とりあえず使ってみよう

       例題 : シャッフルプログラム

           n枚のカード、下から順に 1 〜 n番
6
           上からp枚目からc枚抜き取り一番上に載せる

       テスト例

           n = 5, (p, c) = (2, 3) -> 一番上のカードは4番

           n = 5, (3, 1) シャッフル2回 -> 一番上は4番
テストコード例
    import org.junit.*;
    import static org.junit.Assert.*;
    import static org.hamcrest.CoreMatchers.*;

7   public class ShuffleTest {
      @Test public void test01() {
        Deck deck = new Deck(5);
        deck.shuffle(2, 3);
        assertThat(deck.getTop(), is(4));
      }
      @Test public void test02() {
        Deck deck = new Deck(5);
        deck.shuffle(3, 1);
        deck.shuffle(3, 1);
        assertThat(deck.getTop(), is(4));
      }
    }
Matcher の自作

       普通はTypeSafeMatcher を拡張して作る

           describeTo と matchesSafely を実装する
8
           static なファクトリメソッドを作るとより良い

    class DeckMatcher extends TypeSafeMatcher<Deck> {
      public DeckMatcher(int... ns) { this.ns = ns; }
      public void describeTo(Description desc) {
        desc.appendText("Deck:").appendValue(ns);
      }
      public boolean matchesSafely(Deck deck) {
        return ns[0] == deck.getTop() && ...;
      }
      private int[] ns;
    }
色々な Matcher

       簡単なものなら hamcrest のコアライブラリで十分

           is などの基本的な Matcher が含まれる
9
       hamcrest ライブラリには高度な Matcher が多数存在

           closeTo : double値が指定した範囲に入っているか

           greaterThan : compareToによる比較

           hasProperty : 指定した名前のプロパティがあるか

           eventFrom : イベントの発生源をチェック

           hasXPath : XMLの構造をチェック

           equalToIgnoringWhiteSpace : 空白文字を無視して比較
前半まとめ

        テストは @Test と assertThat で書く


10
        hamcrest ライブラリの Matcher を使う

        基本的には "is" を使えば ok

        Matcher はたくさん用意されている

        自分でも作れる
アノテーション

        JUnit4 といえばアノテーション

            @Test
11
            @Before, @After

            @BeforeClass, @AfterClass

            @Ignore

            @RunWith

            @Rule
@Test

        テストメソッドであることを示すアノテーション


12
        例外チェックやタイムアウト設定もできる


         @Test(expected = ArithmeticException.class)
         public void ゼロ除算() {
           System.out.println(10 / 0);
         }

         @Test(timeout = 1000)
         public void たらいまわし() {
           assertThat(tarai(12, 6, 0), is(12));
         }
@Before, @After

        各テストメソッドごとに呼ばれる


13
        @Beforeはテストの準備

            コンストラクタで代用可能

        @Afterはテストの後始末

            共通のテストを書いたりしても良い

     @Before public void setUp() {
       errorQueue.clear();
     }
     @After public void エラーキュー確認() {
       assertThat(errorQueue, is(empty()));
     }
@BeforeClass, @AfterClass

        テストの最初or最後に一度だけ呼ばれる

            static メソッドである必要
14
        @BeforeClass はstatic イニシャライザで代用可能


     /** テスト対象プログラムの情報を収集して、
       * 各自のプログラムの仕様の差を吸収
       */
     @BeforeClass
     public static void collectInfo() {
       // 原点の描画座標を特定
       // 一点透視図法の方程式を特定
     }
@Ignore

        テストメソッドまたはテストクラスを無視する


15
        理由を指定することができる


     @Ignore("仕様変更のため")
     @Test
     public void legacyTest() {
       assertThat(legacyObj.run(), "success");
     }
@RunWith

        テストランナを指定して実行

            Suite
16
            Categories

            Parameterized

            Theories

        テストランナは自分でも作れる
@RunWith(Suite.class)

        複数のテストクラスを一括で実行する


17
        再帰的に使うことも可能



         @RunWith(Suite.class)
         @SuiteClasses( { FooTest.class, BarTest.class
                          subpack.AllTests.class } )
         public class AllTests {
           // クラスの実装は必要ない
         }
@RunWith(Categories.class)

        Suite のサブクラス


18
        指定したカテゴリのテストのみ実行

     @RunWith(Categories.class)
     @SuiteClasses({ FooTest.class, BarTest.class })
     @IncludeCategory(FastTests.class)
     public class FastTestSuite {}
     public class FooTest {
       @Category(FastTests.class)
       @Test public void test01() { ... }
     }
     @Category({ FastTests.class, SlowTests.class })
     public class BarTest { ... }
@RunWith(Parameterized.class)
  @RunWith(Parameterized.class)
  public class ShuffleTest {
    public ShuffleTest(int n, int[] p, int[] c, int a) {
      deck = new Deck(n);
      this.p = p; this.c = c; this.a = a;
19
    }
    @Parameters public static List<Object[]> params() {
      List<Object[]> params = new ArrayList<Object[]>();
      params.add(new Object[]{5, new int[]{3, 3},
                                  new int[]{1, 1}, 4});
      return params;
    }
    @Test public void test() {
      for(int i = 0; i < p.length; i++)
        deck.shuffle(p[i], c[i]);
      assertThat(deck.getTop(), is(a));
    }
  }
@RunWith(Theories.class)

         与えられた入力の組み合わせを網羅してテスト

     @RunWith(Theories.class)
20   public class FermatTest {
       @Theory public void フェルマーの最終定理
                 (int n, int a, int b, int c)
       {
         assumeThat(n, is(greaterThan(1)));
         BigInteger an = valueOf(a).pow(n),
                    bn = valueOf(b).pow(n),
                    cn = valueOf(c).pow(n);
         assertThat(an.add(bn), is(not(cn)));
       }
       @DataPoints public static final int[] data =
                        { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
     }
@Rule

        テストの振る舞いを変更する

            AOPっぽいことができる
21
            テストランナの殆どを置き換えられるらしい

        TestRuleを実装したクラスで振る舞いを定義

            ExpectedException

            TemporaryFolder

            TestWatcher
ExpectedException

        @Test(expected=...) で満足できない人に

         public class BarbatosTest {
22         @Rule
           public ExpectedException ee =
                          ExpectedException.none();

             @Test
             public void useItem() {
               ee.expect(RuntimeException.class);
               ee.expectMessage(
                     "アイテムなんぞ使ってんじゃねぇ!");
               player.useItem();
             }
         }
TemporaryFolder

        テスト終了時に自動的に削除されるフォルダ


23       public class TmpFileTest {
           @Rule
           public TemporaryFolder tmp =
                           new TemporaryFolder();

             @Test
             public void test() {
               File f = tmp.newFile("tmpfile");
               Data d = download("data.dat");
               d.save(f);
               assertThat(load(f), is(d));
             }
         }
TestWatcher

        テストの前後に処理を挿入

            before, after, around アドバイスっぽい感じ
24
     public class TestWatcherTest {
       @Rule
       public TestWatcher tw = new TestWatcher() {
         @Override
         protected void failed(Description desc) {
           // 失敗したときの処理
         }
       };
       ...
     }
後半まとめ

        もう try { fail() } catch (...) {} なんて書かない


25
        @Before や @After でテストを綺麗に

        @Ignore でテストを無視

        @RunWith や @Rule でテストをカスタマイズ
結論



26

          JUnit は DSL である

More Related Content

What's hot

Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
Effective java 勉強会
Effective java 勉強会Effective java 勉強会
Effective java 勉強会Takinami Kei
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときShintarou Okada
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義JPCERT Coordination Center
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説JPCERT Coordination Center
 
Java8 Lambda chapter5
Java8 Lambda chapter5Java8 Lambda chapter5
Java8 Lambda chapter5Takinami Kei
 
xUnit Test Patterns - Chapter19
xUnit Test Patterns - Chapter19xUnit Test Patterns - Chapter19
xUnit Test Patterns - Chapter19Takuto Wada
 
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」Mr. Vengineer
 
DBFlute2017フェスLT資料
DBFlute2017フェスLT資料DBFlute2017フェスLT資料
DBFlute2017フェスLT資料shogokataoka
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?Shinichi Hirauchi
 
xUnit Test Patterns - Chapter16
xUnit Test Patterns - Chapter16xUnit Test Patterns - Chapter16
xUnit Test Patterns - Chapter16Takuto Wada
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java心 谷本
 
Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説JPCERT Coordination Center
 
Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418Uehara Junji
 
関西Php勉強会のlimeの話
関西Php勉強会のlimeの話関西Php勉強会のlimeの話
関西Php勉強会のlimeの話Hisateru Tanaka
 
C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~Fujio Kojima
 

What's hot (20)

Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
Effective java 勉強会
Effective java 勉強会Effective java 勉強会
Effective java 勉強会
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるとき
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
 
Akka Unit Testing
Akka Unit TestingAkka Unit Testing
Akka Unit Testing
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説
 
Java8 Lambda chapter5
Java8 Lambda chapter5Java8 Lambda chapter5
Java8 Lambda chapter5
 
xUnit Test Patterns - Chapter19
xUnit Test Patterns - Chapter19xUnit Test Patterns - Chapter19
xUnit Test Patterns - Chapter19
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
 
C++14 Overview
C++14 OverviewC++14 Overview
C++14 Overview
 
More C++11
More C++11More C++11
More C++11
 
DBFlute2017フェスLT資料
DBFlute2017フェスLT資料DBFlute2017フェスLT資料
DBFlute2017フェスLT資料
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
 
xUnit Test Patterns - Chapter16
xUnit Test Patterns - Chapter16xUnit Test Patterns - Chapter16
xUnit Test Patterns - Chapter16
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java
 
Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説
 
Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418
 
関西Php勉強会のlimeの話
関西Php勉強会のlimeの話関西Php勉強会のlimeの話
関西Php勉強会のlimeの話
 
C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~
 

Similar to Junit4

Sencha ug3 siesta_share
Sencha ug3 siesta_shareSencha ug3 siesta_share
Sencha ug3 siesta_share久司 中村
 
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_cccJEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_cccYujiSoftware
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!bitter_fox
 
ありえるえりあ勉強会@五反田~テスト編~ Part3
ありえるえりあ勉強会@五反田~テスト編~ Part3ありえるえりあ勉強会@五反田~テスト編~ Part3
ありえるえりあ勉強会@五反田~テスト編~ Part3Tomoyuki Sato
 
Qunit再入門 (Version 1.10.0 編)
Qunit再入門 (Version 1.10.0 編)Qunit再入門 (Version 1.10.0 編)
Qunit再入門 (Version 1.10.0 編)Koji Nakamura
 
Androidでテストってどないすんねん!
Androidでテストってどないすんねん!Androidでテストってどないすんねん!
Androidでテストってどないすんねん!akimichi Yamada
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?Kenji Nakamura
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストYohei Sato
 
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方Satoshi Nagayasu
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」yoshiaki iwanaga
 
Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義JPCERT Coordination Center
 
xUTP Chapter19 (2). Testcase Class
xUTP Chapter19 (2). Testcase ClassxUTP Chapter19 (2). Testcase Class
xUTP Chapter19 (2). Testcase ClassTakuto Wada
 
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要Toshihiro Kamishima
 
Layout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用についてLayout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用についてkimukou_26 Kimukou
 
Xtend30分クッキング やきに駆動
Xtend30分クッキング   やきに駆動Xtend30分クッキング   やきに駆動
Xtend30分クッキング やきに駆動Shinichi Kozake
 

Similar to Junit4 (20)

Enshu8
Enshu8Enshu8
Enshu8
 
Sencha ug3 siesta_share
Sencha ug3 siesta_shareSencha ug3 siesta_share
Sencha ug3 siesta_share
 
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_cccJEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
 
Java7再入門講座
Java7再入門講座Java7再入門講座
Java7再入門講座
 
tdd4cpp demo
tdd4cpp demotdd4cpp demo
tdd4cpp demo
 
ありえるえりあ勉強会@五反田~テスト編~ Part3
ありえるえりあ勉強会@五反田~テスト編~ Part3ありえるえりあ勉強会@五反田~テスト編~ Part3
ありえるえりあ勉強会@五反田~テスト編~ Part3
 
Qunit再入門 (Version 1.10.0 編)
Qunit再入門 (Version 1.10.0 編)Qunit再入門 (Version 1.10.0 編)
Qunit再入門 (Version 1.10.0 編)
 
Androidでテストってどないすんねん!
Androidでテストってどないすんねん!Androidでテストってどないすんねん!
Androidでテストってどないすんねん!
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテスト
 
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 
Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義
 
Project lambda
Project lambdaProject lambda
Project lambda
 
xUTP Chapter19 (2). Testcase Class
xUTP Chapter19 (2). Testcase ClassxUTP Chapter19 (2). Testcase Class
xUTP Chapter19 (2). Testcase Class
 
Spock's world
Spock's worldSpock's world
Spock's world
 
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要
 
Layout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用についてLayout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用について
 
Xtend30分クッキング やきに駆動
Xtend30分クッキング   やきに駆動Xtend30分クッキング   やきに駆動
Xtend30分クッキング やきに駆動
 

Junit4

  • 1. JUnit の使い方 assertThatとアノテーション CSG 市川 0
  • 2. JUnit とは  Java用の単体テストフレームワーク  入力に対する出力が正しいかチェック 1  Eclipseにはじめからプラグインが入っている  なにもしなくても使える
  • 3. テストの書き方  テストメソッドに @Test をつける  org.junit.Test を import しておく 2  Run as -> JUnit Test で実行 import org.junit.*; public class TestHoge { @Test public void はじめのテスト() { System.out.println("Hello, JUnit!"); } }
  • 4. アサーション  実際に計算した結果が予想通りかをチェックする 3  たくさんの種類があるけど assertThat 以外使わない  assertEquals はもう時代遅れ static import org.junit.Assert.*; static import org.hamcrest.CoreMatchers.*; ... @Test public void フィボナッチ10() { assertThat(fib(10), is(55)); } ...
  • 5. assertThat  汎用的なアサーションメソッド  hamcrest ライブラリの Matcher と合わせて使う 4  英語っぽい書き方になる  どっちが actual でどっちが expected か迷わない assertThat(a, is(not(10))); assertThat(lst, hasItem("hoge")); assertThat(o1, is(sameInstance(o2)); assertThat(x, anyOf(nullValue(), equalTo("x")); assertThat(s, isA(String.class));
  • 6. 万能 Matcher "is"  プリミティブ型でも配列でもObject型でも大丈夫  equals (とhashCode) さえあれば自作クラスもok 5  ほかの Matcher を引数に取ることもできる  equalTo と is は同じものだと思われる String[] expected1 = { "foo", "bar", "baz" }; assertThat(array, is(expected1)); List<Integer> expected2 = Arrays.asList(1, 2); assertThat(list, is(expected2));
  • 7. とりあえず使ってみよう  例題 : シャッフルプログラム  n枚のカード、下から順に 1 〜 n番 6  上からp枚目からc枚抜き取り一番上に載せる  テスト例  n = 5, (p, c) = (2, 3) -> 一番上のカードは4番  n = 5, (3, 1) シャッフル2回 -> 一番上は4番
  • 8. テストコード例 import org.junit.*; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; 7 public class ShuffleTest { @Test public void test01() { Deck deck = new Deck(5); deck.shuffle(2, 3); assertThat(deck.getTop(), is(4)); } @Test public void test02() { Deck deck = new Deck(5); deck.shuffle(3, 1); deck.shuffle(3, 1); assertThat(deck.getTop(), is(4)); } }
  • 9. Matcher の自作  普通はTypeSafeMatcher を拡張して作る  describeTo と matchesSafely を実装する 8  static なファクトリメソッドを作るとより良い class DeckMatcher extends TypeSafeMatcher<Deck> { public DeckMatcher(int... ns) { this.ns = ns; } public void describeTo(Description desc) { desc.appendText("Deck:").appendValue(ns); } public boolean matchesSafely(Deck deck) { return ns[0] == deck.getTop() && ...; } private int[] ns; }
  • 10. 色々な Matcher  簡単なものなら hamcrest のコアライブラリで十分  is などの基本的な Matcher が含まれる 9  hamcrest ライブラリには高度な Matcher が多数存在  closeTo : double値が指定した範囲に入っているか  greaterThan : compareToによる比較  hasProperty : 指定した名前のプロパティがあるか  eventFrom : イベントの発生源をチェック  hasXPath : XMLの構造をチェック  equalToIgnoringWhiteSpace : 空白文字を無視して比較
  • 11. 前半まとめ  テストは @Test と assertThat で書く 10  hamcrest ライブラリの Matcher を使う  基本的には "is" を使えば ok  Matcher はたくさん用意されている  自分でも作れる
  • 12. アノテーション  JUnit4 といえばアノテーション  @Test 11  @Before, @After  @BeforeClass, @AfterClass  @Ignore  @RunWith  @Rule
  • 13. @Test  テストメソッドであることを示すアノテーション 12  例外チェックやタイムアウト設定もできる @Test(expected = ArithmeticException.class) public void ゼロ除算() { System.out.println(10 / 0); } @Test(timeout = 1000) public void たらいまわし() { assertThat(tarai(12, 6, 0), is(12)); }
  • 14. @Before, @After  各テストメソッドごとに呼ばれる 13  @Beforeはテストの準備  コンストラクタで代用可能  @Afterはテストの後始末  共通のテストを書いたりしても良い @Before public void setUp() { errorQueue.clear(); } @After public void エラーキュー確認() { assertThat(errorQueue, is(empty())); }
  • 15. @BeforeClass, @AfterClass  テストの最初or最後に一度だけ呼ばれる  static メソッドである必要 14  @BeforeClass はstatic イニシャライザで代用可能 /** テスト対象プログラムの情報を収集して、 * 各自のプログラムの仕様の差を吸収 */ @BeforeClass public static void collectInfo() { // 原点の描画座標を特定 // 一点透視図法の方程式を特定 }
  • 16. @Ignore  テストメソッドまたはテストクラスを無視する 15  理由を指定することができる @Ignore("仕様変更のため") @Test public void legacyTest() { assertThat(legacyObj.run(), "success"); }
  • 17. @RunWith  テストランナを指定して実行  Suite 16  Categories  Parameterized  Theories  テストランナは自分でも作れる
  • 18. @RunWith(Suite.class)  複数のテストクラスを一括で実行する 17  再帰的に使うことも可能 @RunWith(Suite.class) @SuiteClasses( { FooTest.class, BarTest.class subpack.AllTests.class } ) public class AllTests { // クラスの実装は必要ない }
  • 19. @RunWith(Categories.class)  Suite のサブクラス 18  指定したカテゴリのテストのみ実行 @RunWith(Categories.class) @SuiteClasses({ FooTest.class, BarTest.class }) @IncludeCategory(FastTests.class) public class FastTestSuite {} public class FooTest { @Category(FastTests.class) @Test public void test01() { ... } } @Category({ FastTests.class, SlowTests.class }) public class BarTest { ... }
  • 20. @RunWith(Parameterized.class) @RunWith(Parameterized.class) public class ShuffleTest { public ShuffleTest(int n, int[] p, int[] c, int a) { deck = new Deck(n); this.p = p; this.c = c; this.a = a; 19 } @Parameters public static List<Object[]> params() { List<Object[]> params = new ArrayList<Object[]>(); params.add(new Object[]{5, new int[]{3, 3}, new int[]{1, 1}, 4}); return params; } @Test public void test() { for(int i = 0; i < p.length; i++) deck.shuffle(p[i], c[i]); assertThat(deck.getTop(), is(a)); } }
  • 21. @RunWith(Theories.class)  与えられた入力の組み合わせを網羅してテスト @RunWith(Theories.class) 20 public class FermatTest { @Theory public void フェルマーの最終定理 (int n, int a, int b, int c) { assumeThat(n, is(greaterThan(1))); BigInteger an = valueOf(a).pow(n), bn = valueOf(b).pow(n), cn = valueOf(c).pow(n); assertThat(an.add(bn), is(not(cn))); } @DataPoints public static final int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; }
  • 22. @Rule  テストの振る舞いを変更する  AOPっぽいことができる 21  テストランナの殆どを置き換えられるらしい  TestRuleを実装したクラスで振る舞いを定義  ExpectedException  TemporaryFolder  TestWatcher
  • 23. ExpectedException  @Test(expected=...) で満足できない人に public class BarbatosTest { 22 @Rule public ExpectedException ee = ExpectedException.none(); @Test public void useItem() { ee.expect(RuntimeException.class); ee.expectMessage( "アイテムなんぞ使ってんじゃねぇ!"); player.useItem(); } }
  • 24. TemporaryFolder  テスト終了時に自動的に削除されるフォルダ 23 public class TmpFileTest { @Rule public TemporaryFolder tmp = new TemporaryFolder(); @Test public void test() { File f = tmp.newFile("tmpfile"); Data d = download("data.dat"); d.save(f); assertThat(load(f), is(d)); } }
  • 25. TestWatcher  テストの前後に処理を挿入  before, after, around アドバイスっぽい感じ 24 public class TestWatcherTest { @Rule public TestWatcher tw = new TestWatcher() { @Override protected void failed(Description desc) { // 失敗したときの処理 } }; ... }
  • 26. 後半まとめ  もう try { fail() } catch (...) {} なんて書かない 25  @Before や @After でテストを綺麗に  @Ignore でテストを無視  @RunWith や @Rule でテストをカスタマイズ
  • 27. 結論 26 JUnit は DSL である