SE情報技術研究会’s blog

http://se-info-tech.connpass.com

2015-12-20 『JUnit実践入門』読書会の振り返り (第3章)

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

第3章 テスティングフレームワーク

JUnit

  • テストクラスはpublicクラス
  • テストメソッド@Testがついたpublicかつvoid
  • throw句は設定可能

テストメソッドのthrow句

  • 例外はテスト失敗とみなす
  • 通常は例外を期待値としていない場合、テストコード内で例外をcatchせず、throwする
    → 新しい例外の追加時などのテストクラスの変更コストを下げれる
    → ただし、例外クラスの状態(メッセージやエラーコードなど)を検証する際はcatchして各項目を検証する必要があるかと思われる
コメント

例外など設計時にきちんと考えておかないと何でもExceptionを投げられるケースがある。
→ それだと保守もテストもしにくくなる

可読性

  • 通常はクラスごとに対応するテストクラスを作る
  • テストクラスはテスト対象と同じパッケージにする

一般的な命名規約

  • テストクラスの名前=「テスト対象のクラス名+Test」
  • 実測値=actual
  • 期待値=expected

テストを行いやすいメソッド

  • メソッドが戻り値を持つ
  • メソッドの呼び出しの結果、副作用がない
  • 同じ状態、同じパラメータで実行すれば、必ず同じ結果を返す

  • 乱数や現在時刻などが使われるメソッドはテストが行いにくい

4フェーズテスト

  • 事前準備(setUp):テスト大砲オブジェクトの初期化、入力値と結果の準備
  • 実行(exercise):テストする操作を1つだけ行う
  • 検証(verify):実測値が期待値と等価であるか比較検証する
  • 後処理(tear down):他のテストに影響がでないように後始末をする

テストフィクスチャ

  • テストを行うための入力値と期待値のこと
  • 簡単なものはテストコードに記述
  • データベースを扱うなどの複雑なケースは外部定義ファイルやフィクスチャの初期化メソッドを外部クラスに用意するなどの工夫が必要

アサーション

Matcherオブジェクト

コメント

assertEqualsメソッドは使うこともある。
→ 個人的好みの問題かと思われるがassertThatよりassertEqualsのほうが楽だしわかりやすいのでは?
→ ただしJUnit3の書式だとどっちが実績値でどっちが期待値かわかりづらい

JUnitが提供するアノテーション

@Test

コメント
  • @TestアノテーションがあってassertThatがないとどうなる?
    → 単に常に成功するテストメソッドになり、グリーンになるケース数が1つ増えることになる(テスト失敗にはならない)
  • 逆にassertThatがあって@Testアノテーションがないとどうなる?
    → テストメソッドとしての実装上の要件を満たさないので、ケースにカウントされない。(テストフレームワークからは、見えないメソッドになる。)

expected属性

  • 例外の検出するテストで使われる
  • 機体される例外クラスを指定する
@Test(expected = IllegalArgumentException.class)

timeout属性

  • ユニットテストの実行のタイムアウト値を設定する
  • 単位はミリ秒
  • 指定時間を超した場合はテスト失敗になる
  • 上限を決めるためのものでパフォーマンステストに使うものではない

@Ignore

  • テストの実行から除外されるアノテーション
    → このアノテーションがあるテストケースやクラスはテストの実行が行われない
  • 一時的なテストを抑制する場合に使うべき
  • メソッドだけでなくクラスにも定義可能
コメント

そもそも@Ignoreアノテーションは意味があるのか?
→ 実装を忘れることもあるのでは?
→ 実装忘れの予防は@Ignoreを文字列検索すればいいのでは?

@Before

  • テストケース(テストメソッド)の実行前に処理を行うアノテーション
  • メソッド名は慣習としてsetUp
  • public で戻り値なしの void のメソッドにする
  • setUpメソッドで例外が発生するとテスト失敗になる
  • 同一クラス内での共通的な初期化処理に使うのであって、継承を多用すべきではない
    JUnit 4.7で導入されたルールを使う

@After

※ リソースの開放などが必ず行わなければならない後処理がある場合に使われる

@BeforeClass

  • テストクラスがクラスローダに読み込まれて最初のテストケースが実行される前に1度だけ実行される
  • public で戻り値なしの void のメソッドにする
  • テストメソッドは基本的に独立しているべきなので、あまり使うことがない
  • ライブラリの制約やデータの初期化のコストが大きくテストメソッドごとに行えない場合などに使うべき

@AfterClass

  • テストクラスが全てのテストケースを実行した後に1度だけ実行される
  • public で戻り値なしの void のメソッドにする
  • BeforeClass同様、あまり使うべきではない

JUnitのテストパターン

  • 標準的な振る舞いを検証するテスト
  • 例外を検出するテスト
  • コンストラクタを検証するテスト

例外検出するテスト

  • 指定した例外クラスおよびそのサブクラスが検出した際に成功となる
  • expected属性だと例外に含まれるメッセージなどは検証できない
  • 詳細に例外を検証したい場合はルールの一つであるorg.junit.rules.ExpectedExceptionを使う
コメント

ルールを使えばエラーメッセージなどもチェックできるようになるのか疑問?

コンストラクタを検証するテスト

コメント
  • コンストラクタも特殊なメソッドと見れるので、別にsutでもいいのでは?
  • 経験として、そもそも変数名も自動補完を使うのでクラス名と一緒なことがほとんど