SE情報技術研究会’s blog

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

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

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

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

第2章 ユニットテスト

ソフトウェア開発におけるテストの定義

ある条件下においてソフトウェアの振る舞いを記録し、その結果が期待される結果となること

ある条件下

  • 前提条件(事前条件)
  • 使用するデータ、環境、事前の操作手順

ソフトウェアの振る舞いの記録

  • 結果を確認できないといけない
  • ただし画面の表示などは目で変化をすることが確認できれば十分なケースもある

期待される結果との検証

  • ランダム性の高い振る舞いであるほど困難

Scala関数型デザインでは状態をあらわす章でランダム値も再現できる方法を紹介している。

ソフトウェア開発におけるテスト

  • ソフトウェア上の問題や制約などが実際に作ってみないとわからないことが多い
  • 一度作ったものを破棄して作り直すことが容易
  • 設計段階で徹底的に検証して品質を高める手法は、ソフトウェア開発ではあまり効果的ではない
  • 作りながら同時にテストを行うのが有効
  • 実施したテストをフィードバックからテストを追加するのも有効
コメント

設計段階で検証して品質を高める手法は効果できなのでは?
→ ここで言っている設計とは外部設計の話ではなく詳細設計の話なのでは?
→ 詳細設計の話なら効果的でないのは納得できる。

自動テストで一度つくったものを破棄して作りなおすことが容易になっても、ファイルの差分管理が手間がかかるので大幅な禁止してるところも多い。
→ ファイル管理のためというのは本末転倒な気もするが、規模が大きいとそういうケースもあるのかも?

テストケースとテストスイート

テストケース

  • 1つのテスト項目
  • 前提条件、実行する操作、期待される値や状態、全てが含まれる

テストスイート

  • 複数のテストケースをまとめたもの
  • テストケースが増えてくると、何らかの形で似たテストケースをまとめる必要があるため

ソフトウェアテスト

  • 主な目的は品質保証だが品質保証以外の目的もある
  • 全てをテストできないので効果的な入力値を選択し、「十分に良いテスト」を行うしかない
  • 「十分に良いテスト」はユーザの要求や予算に依存する

機能テスト

  • 設計時に考慮した仕様が不足なく実装されているかを検証するテスト
  • 品質だけでなく設計そのものが妥当であるか検証する目的もある

テスト技法

ホワイトボックステストブラックボックステストを組み合わせる

ホワイトボックステストの問題点

  • ホワイトボックステストは内部ロジックに依存しすぎると変更に対してもろくなる面もある
  • そのため、テストデータは外部仕様からテストデータを選択したほうが良い

同値クラスに対するテスト

  • ソフトウェアが同様の結果をもたらす値を同値クラスとしてグループ化し、各同値クラスからテストデータを選択するテスト技法
  • 外部仕様(特に出力結果)に着目してテストデータを作成する
  • それぞれの結果の条件を満たす同値グループを作成する
  • すべての組み合わせは膨大になるので代表値を選ぶ
  • 代表値で動作が正しければ他の同値クラスの値でも正常に動作するとみなす

境界値に対するテスト

  • 境界値 = 異なる結果をもたらす値
  • 境界値およぼその近辺の値でテストを行う
コメント

テストコードにおける境界値などはハードコーディングすべき?
→ ハードコーディングすると変更に対応できないのでは
→ テストクラスで定数を使うのはどうなのか?
→ プロダクトクラスに定数クラスがあればそれを使ってもよいか?

ユニットテスト

  • プログラムとして実行できる仕様書とみなせる
  • プログラムとして実装されているので設計書の文による曖昧さを回避できる
  • テストのクラスは対象のクラスのサンプルコードとしても考えることができる
  • 使いにくさを感じたら設計や仕様に問題がある可能性がある
  • テストを自動化することで簡単にテストを繰り返しおこなえ、リグレッション(デグレ)を最小限にできる
  • GUIなどは自動化が難しい(コストとのトレードオフになる)
  • 結果が一定でないテストは避けたほうが良い
  • 常にすべてのテストが成功している状態にすべき
  • テストケースは小さな単位で行うべき
  • 可読性の低いテストは避けるべき
    → 各行が前提条件、実行、検証のどこに属しているか明確な短いコードにするべき
  • 1つのテストケースで1つのテストのための実行を行うべき
  • 結果の検証を1つのテストケースで複数おこなう場合は検証する項目は1行ずつ行う
    → データクラスの検証はequalsメソッドで行うと便利だが失敗した時に一致しないフィールドを分析するのに時間がかかるなど
  • テストケースはお互いに影響を与えないようにすべき
    → テストケースの実行順序に結果を依存させない

ユニットテストフレームワークにはJUnit以外にもTestNGもある
ユニットテストのパターンをまとめたサイト:xUnit Test Patterns

コメント

テストの自動化で繰り返しテストが簡単にできるというのはテストの規模やシステムの規模によるのでは?
→ 最近ではテスト設計もきちんと考えて効率的にするべきという意見も出てきている

テストコードの可読性を向上するためのTips

  • 同じ前提条件のコードが出てきたらsetUpメソッドに抽出する
  • 同じテストクラスで重複する前提条件が2つ以上でたらコンテキストをわける

独立性を向上するためのTips

  • 各テストの初期化処理で必要なデータを用意し、テスト終了後に元に戻す
  • ハードコーディングされた設定ファイルは避ける
  • ミュータブルなシングルトンは避ける
コメント

シングルトンは必要ある場合もあるので、よいテスト方法はないものなのか、あれば知りたい。