覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Javaでユニットテストを書く時に気を付けたいこと

Javaプログラムに対するユニットテスト(単体テスト)を書く際に気にしておきたいことを書いてみました。

以下、個人的な経験則と本で読んだ内容が混ざっています


ユニットテスト作成時の原則

  • 「このクラスはXXXの理由でユニットテストが難しいんです!」と言いたくなったら
    • ユニットテストし易いように対象のクラスを作る(作り直す)
      一般的にこのような設計の変更をした方が実運用にも適していたり、要件変更への対応が柔軟になったりする場合が多いです
  • privateメソッドを強引にユニットテストしない
    • リフレクションを使って出来なくはないが、基本的にやるべきではない。ユニットテストが内部の実装に依存しすぎる
    • 呼び出し元のpublicメソッドのユニットテスト経由で処理を網羅すればよい
    • どうしてもprivateメソッドのテストをしたいなら、そもそもprivateメソッドではなく別クラスのpublicメソッドとして公開する必要性が高い(元の設計が間違っている)
  • テストが書けない(書きにくい)箇所もある
    • 画面が絡む部分はJUnitでのユニットテストは書きにくい。無理やり書く必要は無いと思います。
  • 振る舞いをテストする
    • テストを作成する際には、個々のメソッドをテストするとは思わず、対象のクラスのふるまいに着目する必要があります。
    • ユニットテストを作成する際には、まず全体的な観点を持つべきです。
      個々のメソッドをテストするのではなく、それぞれの組み合わせからなるクラスとしてのふるまいをテストするということを念頭に置く必要があります


AAA

アプリケーションのテストは一般的に、Arrange(セットアップ) と Act(操作) と Assert(アサーション) という3つの部分に分かれています。
この構成を頭文字をとってAAAと呼ぶことがあります

  • Arrange(セットアップ)
    • テスト実施の準備をし、テストが実行される環境が適切な状態である事を保証します
  • Act(操作)
    • テストのコードを実行します。
  • Assert(アサーション)
    • テスト対象のコードが正しくふるまったかどうかを確認します。コードからの戻り値やテストに関わったオブジェクトの状態などがチェックされます。


FIRST

良いテストはFIRST

  • Fast(迅速)
  • Isolated(隔離)
  • Repetable(繰り返し可能)
  • Self-validation(自律的検証)
  • Timely(タイムリー)

逆に以下に該当すると良くないテストと言えるかもしれません

  • 読んだ人が理解できないテスト
  • 成功することも失敗することもあるテスト
  • 意味のある検証を行っていないテスト
  • テスト対象のコードを十分に網羅していないテスト
  • 実行に長い時間がかかるテスト
  • テスト対象のコードが少し変更されただけでも、多数の失敗が発生してしまうような依存性の強いテスト
  • セットアップに多くの時間を必要とする複雑なテスト


カバレッジ

  • ソフトウェア全体として カバレッジが70%未満の場合はかなり低い(と思います)
  • 本質的ではないコードに対してテストを書いてカバレッジを無理やりあげる必要は無いです(以下のようなテストは書くのは本質的ではない)
    • JavaBeansの単純なgetter/setterに対するユニットテスト
    • privateコンストラクタのユニットテスト
  • カバレッジの感覚的な把握ではなく、できるだけツールで測定する(EclEmma等)。


バグが発生しやすい場所

バグが発生しやすい場所(状況)として以下のようなものがあります。これらは重点的にテストすべき箇所となります。

  • 境界値近傍の引数
  • ifやforループなどがネストしている箇所
  • if文の条件が複雑になっている箇所
  • メソッド内で早期returnができる状況で早期returnをしていない場合
  • nullを取り扱っている箇所
  • ローカル変数を使い回している箇所
  • 他プロダクト(他システムと)とのインターフェース境界部分
  • 不変ではない(可変の)変数やオブジェクトをマルチスレッドで扱っている場合


関連ツール・ライブラリ

  • Mockito
    • モックライブラリ
  • JMockit
    • モックライブラリ
  • EclEmma
    • テストのカバレッジを計測・可視化するためのツール
  • AssertJ
    • 流れるようなインターフェースで書けるので、HamcrestのMatchersよりテストケースのコードが書きやすい
  • mocker
    • Fluent Mockito Builder



関連書籍・関連エントリ

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

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

実践 JUnit ―達人プログラマーのユニットテスト技法

実践 JUnit ―達人プログラマーのユニットテスト技法

blog.y-yuki.net