テスト技法やキーワードなど

  • ホワイトボックス/ブラックボックス/同値クラス/境界値
  • 実測値(actual value)/期待値(expected value)
  • C0(命令網羅)/C1(分岐網羅)/C2(条件網羅)

JUnit

テストケースの粒度

  • 1つのケースで複数の実測値、期待値が必要になるということは、テスト対象が大きすぎる可能性あり。

4フェーズテスト

  • ひとつのテストケースメソッド内で、次の4つの処理に分けて、テストを記述する。
  • 1.初期化、2.テストの実行、3.アサーション、4.(必要ならば)終了処理。

テスタビリティを高めるリファクタリング

  • プロダクトコードでテスト困難な箇所をメソッドに抽出する。テストコードでは、プロダクトコードを無名クラスで継承し、テスト困難なメソッドをオーバーライドする。
  • プロダクトコードでテスト困難な箇所をオブジェクトに抽出する。テストコードで、テスト用オブジェクトをDIする。

バージョン

  • JUnit3 - Java4以下でも動作。
  • JUnit4 - Java5以上。アノテーションベース。

JUnit4

アノテーション

  • @Test - テストケース
  • @Ignore - テストの実行を除外
  • @Before - 初期化
  • @After - 後処理
  • @BeforeClass - クラスごとの初期化
  • @AfterClass - クラスごとの後処理
  • @RunWith - テストランナー

アサーション

assertThat(actual, is(expected));
fail("未実装");

Matchers

  • CoreMatchers#is, nullValue, not, notNullValue, sameInstance, instanceOf
  • JUnitMatchers#hasItem, hasItems

ルール

public class RuleTest {
    @Rule
    public TestRule rule = new SomeRule();
    @ClassRule
    public static TestRule RULE = new SomeRule();
}

例外送出のテスト

@Test(expected=Exception.class)
public void testCase() {
}

タイムアウト

@Test(timeout=1000L)
public void testCase() {
}

構造化テスト

@RunWith(Enclosed.class)
public class EnclosedTest {
    public static class XXの場合 {
        @Before
        public void setUp() {
        }
    }
    public static class YYの場合 {
        @Before
        public void setUp() {
        }
    }
}

内部クラスのまとめ方

  • 共通データでまとめる。
  • 共通の状態でまとめる。
  • コンストラクタのテストを分ける。

パラメータ化リスト

@RunWith(Theories.class)
public class ParameteriedTest {
    @DataPoints
    public static int[] PARAMS = {1, 2, 3, 4};
    @Theory
    public void test(int x) {
    }
}
@RunWith(Theories.class)
public class ParameteriedTest {
    public static class Fixture {
        public int input;
        public int expected;
        public Fixture(int input, int expected) {
            this.input = input;
            this.expected = expected;
        }
    }
    @DataPoints
    public static Fixture[] fixtures = {new Fixture(1, 10), new Fixture(2, 20)};
    @Theory
    public void test(Fixture x) {
    }
}

@DataPointsはメソッドに定義することも可能

    @DataPoints
    public static Fixture[] getPrams() {
        外部リソース読み込みなど
    }

カテゴリ化テスト

@Category(DbTests.class)
public class CategoriedTest {
    @Test
    @Category(SlowTests.class)
    public void testCase() {
    }
}