うさぎ組

ソフトウェア開発、チームによる製品開発、アジャイル、ソフトウェアテスト

ソフトウェアテストの言葉入門 #kyon_mmAdvent

kyon_mm Advent Calendar

つぎのリンクにあるAdventCalendarの17日目です。
http://connpass.com/event/1457/


これは非常にながーい時間がかかりましたが、いぜんにid:kura_replace(@PG_kura)さんのWeb プログラミングってこんな感じじゃなかろうか - 偏見プログラマの語り!という素晴しい記事へのおへんじとなります。
もう半年近く書き足しては書き直しの日々でございましたが、ようやく公開できるようになりました。
@PG_kura さんがおっしゃっている「テストのあり方:テストコードはこう書きましょうという汎用的なコンセプト」については当連載での後半で書きます。

ここに書いてあることが僕がNagoya.Testingという場で伝えたい事でもあるなぁと書いていてしみじみと思いました。
このような機会を頂きありがとうございました。勉強になりました。


この連載では5つにわけて次の話をかこうと思います。

  1. ソフトウェアテストの言葉入門
  2. 開発者のテストとソフトウェアテストの相違
  3. kyon_mmが考えるソフトウェアテスト1
  4. kyon_mmが考えるソフトウェアテスト2
  5. TDDとリファクタリングの自殺


また、ここで書く言葉の多くはソフトウェアエンジニアリングのコンテキストであり、ソフトウェアサイエンスの言葉ではございません。
ご了承ください。

大前提

僕はテストが嫌いです。テストをこの世の全てのプロジェクトからどうやってなくすかをかんがえています。
テストを撲滅したいがために1年と9ヶ月ソフトウェアテストを勉強したエンジニアのレポートだとおもってください。

ソフトウェアテストにおけるたくさんの言葉

みなさんがソフトウェアテストといったときにたくさんの表現をすると思います。
単体テスト」「結合テスト」「性能テスト」「機能テスト」「互換性テスト」「セキュリティテスト」「境界値テスト」「受け入れテスト」


これらは別別のカテゴリーがあたえられていることがほとんどです。今回はこれらの言葉を「ソフトウェアテスト」というコンテキストではこのように区別しています。という話をしましょう。
なぜこのような話というか単語の定義をするかというと、「コンテキストあわせ」だったり「より明確に仕事をすることで思考を研ぎ澄まさせるため」だったりと思っています。


今回は次のカテゴリーについて話します。(圏論のことではありません)
後半になるほどわけわからない感じになると思うので、とりあえず上の3つ(テストレベル、テスト技法、テストタイプ)だけ覚えていれば大丈夫です。だいたい話が通じます。

  1. テストレベル
  2. テスト技法
  3. テストタイプ
  4. テスト対象
  5. テスト目的
  6. テストプロセス
  7. テスト観点

テストレベル

テストレベルとは「テストの対象物の粒度」によって区別するテストの分け方です。
おおくは「単体テスト」「結合テスト」「システムテスト」となっていたり、「社内結合テスト」「社外結合テスト」「受け入れテスト」といったものがあることもあるでしょう。


これらの定義はありますが、あくまで定義なので「そのプロジェクト全体で全員が参照できる各テストレベルの定義」があればそれでよい感じです。
ただ、僕はそれがないがしろになっていることが多い現場があり、それによってプロジェクトの失敗率があがるのではないかと思うことがあり、次のようなことを考えていたりします。



単体テスト/結合テストなんて存在しない - Togetterまとめ


ここでは二つの定義を引用します。
JSTQBとBeizerのものです。個人的にはBeizerの定義をつかうことがおおいですね。
JSTQB

  • コンポーネントテスト:スタブ使うようなコンポーネントやクラス内でのテスト。TDDなど担当開発者が行う事が多い。
  • 統合テスト:コンポーネント間やシステム間を統合して動作させるテスト。
  • システムテスト:ステージング環境などでのプロジェクトのスコープにあたるソフトウェアを動作させてのテスト
  • 受け入れテスト:要求を出した人の意に沿ったものであるかを確認するテスト。

Beizer

  • ユニットテスト:1ファイル内で動作が可能なテスト。ほとんどの場合はモックが必要になる。
  • コンポーネントテスト:あるユニットが動作するのに必要なユニットを含めたテスト。例えば、Foo機能のエントリであるAaaClassのあるメソッドをテストすることになるでしょう。そのメソッドではBbbClassを参照しており、CccClassをフィールドに持っていたら、BbbClassまでふくめたものも、CccClassまで含めたものもコンポーネントテストになります。つまり、ある機能を達成するための各ユニットの再帰的な定義になります。
  • 統合テスト:コンポーネント間のテストになります。先はFoo機能のためにAaa , Bbb, Ccc といったクラスの関連をテストしたわけですが、Bar機能のためのXxxClass, YyyClass, ZzzClassは別のコンポーネントと考える事になります。このばあいに、直交しているかもしれませんし、別のリソース部分でなにか関連しているかもしれません。この連携をテストします。
  • システムテスト:システム全体を動作させてのテスト。コンポーネントテスト、統合テストでは検出されないようなバグを検出するためのテストになります。自然とJSTQBのようなステージング環境が想定され、実際のシナリオが必要になります。

テスト技法

これらは「入力パラメータ、出力結果の列挙や組合せをどのように決定するか」の手法のことをいいます。
詳細な説明は割愛しますが、次のようなものがあげられます。

  1. 同値分割
  2. 境界値分析
  3. デシジョンテーブル
  4. 直交表
  5. All-Pair
  6. 状態遷移表
  7. 原因結果グラフ
  8. CFD

テストタイプ

これらは「どのような目的か」で分類したテストになります。これらもテストレベルと同様にプロジェクト毎に合意できるようになっていれば問題ありません。
あまり聞かない言葉だと思いますが、一部の分類については聞いたことがあるかもしれません。

  1. 機能テスト:単機能で動作が仕様通りであるかを実証する
  2. 機能組み合わせテスト:機能同士が有則や無則で組合さったときの動作が妥当かを実証する
  3. シナリオテスト:ユーザーや業務的な実際のフローにおいて妥当かを実証する
  4. ユーザビリティテスト:ユーザーが快適にそのプロダクトを使えるかを実証する
  5. セキュリティテスト:保護すべき情報が漏洩しにくいかを実証する
  6. ストレステスト:どれくらいの負荷まで耐えられるかを実証する

ここまでの言葉がわかればとりあえずいいかなっておもっています。

コラムっぽいなにか:ソフトウェアテストの定義

テストとは何であるか?という定義は様々です。
例えば、JSTQBでは「レビュー、解析ツール、プロダクトを動作させての実証」などをふくめてテストと言います。
僕の場合は「誰が確認しても一意に特定できるもの」をテストと呼んでいます。だから「かっこいいかの確認」というのはテストではなく、評価のフィードバックループであり、それはテストとは呼ばないが必要な作業である場合もある。という認識です。
また、某なごやの静的型付け関数型プログラマー達は「コンパイラもテストである」といっています。
僕はどの解釈であってもいいと思っていますが、なにがしかの定義をしないとチームでのソフトウェア開発はうまくいかないだろうなって思っています。

テスト対象

これらは「ソフトウェアテストの対象物」をいいます。プロダクトを機能で分割することもできますし、インフラ面で分割することもできます。
テストレベル毎にテストしやすい粒度で分割するのがオーソドックスかもしれません。
いわゆるTDDで「テストが書きにくい」「プロダクトコードのあるクラスの責務がおおきくなりすぎている」という「設計における粒度や分割の視点」がこのテスト対象の分割にはいってきます。
分割の仕方は様々なのでなんとも具体例がだしにくいのですが、結合テストレベルでは次のようなものがもうすこし詳細になった形であげられそうかなっておもいます。

  1. 仮会員登録
  2. 本会員登録
  3. 一覧表示
  4. メール送信

これが単体テストのレベルになるとFooClassとかClassやmodule単位になるのだと思います。

テスト目的

これらは「どのような理由でそのテストが必要か」で分類したものになります。言い換えればテスト目的とは「このテストは誰が望んでいるのかという視点での分類」というのが僕の解釈に近い感じです。
いわゆるV字モデルではテスト目的というものを、Vの右側の各テストがVの左側の各ドキュメントに沿っている事という目的にしています。テストが必要になればなるほど、この事から、Vの左側が重要になってきます。Vの左側が弱い場合はVの右側にハイレベルなテストエンジニアとハイレベルなプログラマーが必要になるでしょう。


少し話がずれましたが、オーソドックスにいけばテスト目的を手段に置き換え、ある程度抽象化したものがテストタイプとなります。また、テスト目的はなんらかの品質モデルをベースに考えられる事が多いです。
品質モデル -> テスト目的 -> テストタイプ
右側にいけばいくほどプロジェクトの具体的な手段になるイメージです。
ISO9126のソフトウェアの品質特性を使った例を出してみます。

  1. 機能性(ISO9126 主特性
    1. 正確性(ISO9126 副特性
      1. ユーザーガイド準拠(インストール方法や機能など) (テスト目的
      2. プラットフォーム準拠(課金機能など) (テスト目的

テストプロセス

「ソフトウェア開発のプロセスのようにテストにもプロセスを定義した」という感じです。
だいたい以下の流れで説明されることが多いように思います。

  1. テスト要求分析:上記のテスト目的を導出したり、リスク分析を行ったりする。
  2. テスト戦略策定:テスト観点などをベースにしてテストのアーキテクチャをつくったり、人的リソースや手段などを考慮してテストの準備からライフサイクルをふくめたテストの進め方を構築する
  3. テスト設計:テスト実装がうまくいくように設計する
  4. テスト実装:テストを実装する。いわゆるテスト仕様書やテストケースと言われているもの。
  5. テスト実施:テストを実施していき不具合などがあればレポートにしておく。
  6. テスト報告:テストの結果を報告する。


ほとんどソフトウェア開発で使われる言葉と変わらないのですが、最初のほうだけ違う感じですね。
また、テスト設計の部分は「テスト分析、テスト設計、テスト詳細設計」とわける場合もあります。
ソフトウェア開発で外部設計、内部設計とわける場合があるのと似たようなイメージで構いません。
また、これはプロセスですがどれをどの程度行うかなどは全くの自由ですし、このプロセスが正義なわけでもありません。
オーソドックスなテストプロセスという位置づけです。

僕が「テスト戦略!」「テストアーキテクチャ!」と言っているのはテスト戦略策定の部分がメインになってくるものです。


テスト観点

観点という言葉は非常に多様に使われる言葉であり定まっていないようにも見えますが、日本のソフトウェアテスト業界におけるテスト観点とは「テスト対象とテスト目的のペアである」という認識が広まっているように思えます。
ただ、原則としては「テストにおける関心事」という認識でよいでしょう。
これらを中心的に発信しているのは智美塾というコミュニティになります。
詳細な説明というか、図はJaSSTの次の資料を読んでみてください。


http://www.jasst.jp/symposium/jasst12tokyo/pdf/A2-3.pdf :テストアーキテクチャ設計の概念


ただ僕の考えとは相容れない部分もありまして、その辺は後半で書こうと思っています。