Junit4

3,183 views
3,019 views

Published on

1 Comment
4 Likes
Statistics
Notes
No Downloads
Views
Total views
3,183
On SlideShare
0
From Embeds
0
Number of Embeds
58
Actions
Shares
0
Downloads
13
Comments
1
Likes
4
Embeds 0
No embeds

No notes for slide

Junit4

  1. 1. JUnit の使い方 assertThatとアノテーション CSG 市川0
  2. 2. JUnit とは  Java用の単体テストフレームワーク  入力に対する出力が正しいかチェック1  Eclipseにはじめからプラグインが入っている  なにもしなくても使える
  3. 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. 4. アサーション  実際に計算した結果が予想通りかをチェックする3  たくさんの種類があるけど assertThat 以外使わない  assertEquals はもう時代遅れ static import org.junit.Assert.*; static import org.hamcrest.CoreMatchers.*; ... @Test public void フィボナッチ10() { assertThat(fib(10), is(55)); } ...
  5. 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. 6. 万能 Matcher "is"  プリミティブ型でも配列でもObject型でも大丈夫  equals (とhashCode) さえあれば自作クラスもok5  ほかの Matcher を引数に取ることもできる  equalTo と is は同じものだと思われる String[] expected1 = { "foo", "bar", "baz" }; assertThat(array, is(expected1)); List<Integer> expected2 = Arrays.asList(1, 2); assertThat(list, is(expected2));
  7. 7. とりあえず使ってみよう  例題 : シャッフルプログラム  n枚のカード、下から順に 1 〜 n番6  上からp枚目からc枚抜き取り一番上に載せる  テスト例  n = 5, (p, c) = (2, 3) -> 一番上のカードは4番  n = 5, (3, 1) シャッフル2回 -> 一番上は4番
  8. 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. 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. 10. 色々な Matcher  簡単なものなら hamcrest のコアライブラリで十分  is などの基本的な Matcher が含まれる9  hamcrest ライブラリには高度な Matcher が多数存在  closeTo : double値が指定した範囲に入っているか  greaterThan : compareToによる比較  hasProperty : 指定した名前のプロパティがあるか  eventFrom : イベントの発生源をチェック  hasXPath : XMLの構造をチェック  equalToIgnoringWhiteSpace : 空白文字を無視して比較
  11. 11. 前半まとめ  テストは @Test と assertThat で書く10  hamcrest ライブラリの Matcher を使う  基本的には "is" を使えば ok  Matcher はたくさん用意されている  自分でも作れる
  12. 12. アノテーション  JUnit4 といえばアノテーション  @Test11  @Before, @After  @BeforeClass, @AfterClass  @Ignore  @RunWith  @Rule
  13. 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. 14. @Before, @After  各テストメソッドごとに呼ばれる13  @Beforeはテストの準備  コンストラクタで代用可能  @Afterはテストの後始末  共通のテストを書いたりしても良い @Before public void setUp() { errorQueue.clear(); } @After public void エラーキュー確認() { assertThat(errorQueue, is(empty())); }
  15. 15. @BeforeClass, @AfterClass  テストの最初or最後に一度だけ呼ばれる  static メソッドである必要14  @BeforeClass はstatic イニシャライザで代用可能 /** テスト対象プログラムの情報を収集して、 * 各自のプログラムの仕様の差を吸収 */ @BeforeClass public static void collectInfo() { // 原点の描画座標を特定 // 一点透視図法の方程式を特定 }
  16. 16. @Ignore  テストメソッドまたはテストクラスを無視する15  理由を指定することができる @Ignore("仕様変更のため") @Test public void legacyTest() { assertThat(legacyObj.run(), "success"); }
  17. 17. @RunWith  テストランナを指定して実行  Suite16  Categories  Parameterized  Theories  テストランナは自分でも作れる
  18. 18. @RunWith(Suite.class)  複数のテストクラスを一括で実行する17  再帰的に使うことも可能 @RunWith(Suite.class) @SuiteClasses( { FooTest.class, BarTest.class subpack.AllTests.class } ) public class AllTests { // クラスの実装は必要ない }
  19. 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. 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. 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. 22. @Rule  テストの振る舞いを変更する  AOPっぽいことができる21  テストランナの殆どを置き換えられるらしい  TestRuleを実装したクラスで振る舞いを定義  ExpectedException  TemporaryFolder  TestWatcher
  23. 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. 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. 25. TestWatcher  テストの前後に処理を挿入  before, after, around アドバイスっぽい感じ24 public class TestWatcherTest { @Rule public TestWatcher tw = new TestWatcher() { @Override protected void failed(Description desc) { // 失敗したときの処理 } }; ... }
  26. 26. 後半まとめ  もう try { fail() } catch (...) {} なんて書かない25  @Before や @After でテストを綺麗に  @Ignore でテストを無視  @RunWith や @Rule でテストをカスタマイズ
  27. 27. 結論26 JUnit は DSL である

×