よしたろうブログ

設計・人文知・歴史・哲学・漫画とかの話が好きです。

テストのいろんな定義(WF・アジャイル・シラバス・テストピラミッド・ロンドン学派・古典学派・Google)

1. テストの種類について

テストの種類・定義・レベル(規模や外部システムの数など)・タイプ(目的)に対するの認識が個々人で違う。アジャイルとWFでも責務が異なる。その上、手動でないと検査できない暗黙的検証を多く含むので余計複雑。

開発チーム用の定義を作りたい。人によって指してる内容が違うからまず定義を統一したい。そのような経緯で世間で言われているテストについて整理してみた。

WF的な正解とアジャイル的な正解は合致しない部分が多いように思う。これまでのテストの意義や定義を効率主義から成果主義に寄せて再構築したものがアジャイル用に分類したように見える。

ここでは、さまざまな視点でのテストの種別・観点を記述する。大事なことは絶対的な正しさなどなく、チームの状況・構造・レベル・コミュニケーションのあり方・開発手法などによって正しい有りかたが引っ張れることを踏まえて選択することである。

単体テスト (ユニットテスト) や統合テスト、 E2Eテストそれぞれについてこれだという定義はない。そのため、チーム内での認識がずれることが当然である。

2. WF的(最大公約数的な?)分類

無理やり分類してる所もあるし、あえて網羅した上で責務を明確にしようとしているので、WF的な定義からすると結合・統合テストあたりは意味が乖離している。

JSTQBでは単体テストとユニットとユニットの相互作用も含めてコンポーネントテストとするが、アジャイル4象限では区別されている。なんでや?

ここで書いたのは個人整理用でもあるし、開発チーム内でのテストレベル定義についての議論のたたき台になればいいとも思う。やや適当。

テストレベル

テストレベルは、一連のテスト活動(計画/設計/実装/実行・管理/評価・報告)の管理単位である。 また、テスト対象の規模(外部APIの数やコンポーネント数など)によって分けられる。

単体テスト

ソフトウェアの最小単位であるクラスやメソッド(ユニット)をテスト。 入力値と期待値を定義し、それらに基づいてテスト。ソフトウェアテストが可能な最小単位をユニットと呼ぶが、後述するようにユニットは厳密に定義されているわけではなく、ソースコード上で個々の関数やクラスをユニットとすることもあれば、画面や機能単位でテストを行うこともある。詳しくは「単体テストの定義と流派」にて 目的:クラス・メソッド単体での正常動作を確認

コンポーネントテスト

単体テスト結合テストの両方に含まれる場合もあるが、ここでは結合テストと同義として認識している。 ※一般的に結合テスト=統合テスト(JSTQBの定義では結合テストというテストレベルは存在しない)として扱われているのが散見される。ここでいう結合テストはレベルの低いテストとなる。

結合と統合を分けるか一緒にするかで意味が変わる。分けるなら結合・コンポーネントは同一のテスト、結合=統合とするなら、下記の結合テストコンポーネントテストとなる。言葉の意味としては分けた方がしっくり来る派。JSTQBでは上記単体テストと下記のテストを含めてコンポーネントテストと呼ぶ

結合テスト

単体テスト合格後のクラス・メソッド(ユニットとユニット)やモジュール同士を結合してテスト。 相互作用・データ受け渡しなどをテスト。 目的:結合して正常に動作するかを確認。

統合テスト

システム全体で『機能要件』を満たしているかをテスト。全体とは、DB・外部API・プロダクト内の他モジュールなどである。それらが統合された状態で想定通りに機能することを検証する。 目的:システム全体が正常に動作するかを確認

システムテスト

システム全体が『機能・非機能要件』を満たしているかをテストする。統合テストに加えて、パフォーマンスやセキュリティなどの非機能要件もテスト。 目的:システム全体で機能非機能要件を満たしているかを確認

受け入れテスト

ユーザー(ステークホルダー)がシステムを受け入れられるかを確認するテスト。 目的:ユーザー視点での『要求』がシステムで実現できているのかを確認

テストタイプ

テストタイプとは、「どのテスト目的に向けたものか」という観点から見たテストの分類であり、システムに求められる品質により、実施すべきテスト内容を定義したものである。

機能テスト

機能単体での『要求』を満たしているかをテスト。仕様通りに動作するかを確認。アジャイルではユーザストーリを満たすかどうかに焦点を置く。

業務シナリオテスト

業務を想定したシナリオに基づいて実施するテスト。お客様にて行われる業務が実現できるか、といったように要求と合致していることを確認する。

ジョブ運用テスト

(ジョブスケジューラなどの運用ツールの利用がある場合)定義内容が正しいことを確認する。

他システム接続テスト

他の社内システムと連携に着目して実施するテスト。他社内システムとの連携処理について、仕様と合致していること を確認する。

外部接続テスト

社外システムとの連携に着目して実施するテスト。社外システムとの連携処理について、仕様と合致していることを確 認する。

ユーザビリティテスト

操作性や視認性などを評価するためのテスト

セキュリティテスト

脆弱性への対処など、セキュリティ要件を充足していることを確認

運用マニュアルテスト

運用マニュアル・手順書の内容通りに操作を行い、記載内容が正しいことを確認する。

運用監視テスト

運用監視の設定が正しく行われていることを確認する。

障害耐性テスト

障害が発生した場合においても、実行レベルを維持できることを確認する

障害回復テスト

障害発生後に、実行レベル再確立やデータ回復ができることを確認する。コンティンジェンシープランや代替業務を定 めている場合は、定めた方針や手順通りに業務再開ができることを確認する。

ロードテスト

テスト対象に負荷を与えた場合(大容量データや多数のデータを与えた場合、一定時間内に多数の処理を行う場合など)において、正しい動作を行うことを確認するテスト

ストレステスト

テスト対象に負荷を与えたとき、メモリやサーバなどのリソースの可用性が低減したときの限界を超えた場合において 、正しい動作を行うことを確認するテスト

ロングランテスト

テスト対象に対して繰り返し長時間、要求された処理を行った場合に、正しく動作することを確認するテスト

性能テスト

性能要件を充足していることを確認する(レスポンス、キャパシティなど)

保守性テスト

保守要件を充足していることを確認

移行テスト

移行手順書、移行ツールといった移行時に使用する資産の内容が正しいことを確認する。

クロスブラウザテスト

ブラウザバージョンが異なる環境でテスト対象が正しい動作を行うことを確認する。

無影響確認テスト

変更により欠陥混入がないこと、想定外の影響が発生していないことを確認するため、従来機能のプログラムに対して実行するテスト。

ブラックボックステスト

テスト実施者がソフトウェアの内部構造を把握することなく、システムの入力と出力の整合性をチェックするテスト。

ホワイトボックス(構造)テスト

ホワイトボックステストは、構造テストとも呼ばれ、ソフトウェアの内部構造を対象にテスを行うテス。テスト実施には対象プログラミングの知識が求められる。

3. JSTQB によるテストレベル定義

https://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018V31.J03.pdf

コンポーネントテスト

  • 単体テストのテスト対象は、コンポーネントとも呼ばれるソフトウェア単体。テストの単位は、関数、クラス、モジュール、コードおよびデータ構造など。
  • ユニットテストからユニットとユニットの結合したコンポーネントまでを含む振る舞いを検証
  • インプット(妥当性を検証する対象):詳細設計(アジャイルでは価値なし、WFでも大体は不要派)

②統合テスト

  • 統合したコンポーネントやシステムのインターフェースや相互作用の欠陥を摘出するためのテスト
  • コンポーネントまたはシステム間の相互処理の2視点に加え、それぞれのIFの振る舞いを検証
  • インプット(妥当性を検証する対象):基本設計書など(機能仕様書に相当、だいぶ簡略化している)

システムテスト

  • システム全体のエンドツーエンドの振る舞いを検証。実行する機能や非機能的な振る舞いが要件を満たすことや、要件に反する欠陥がないことなどを検証。
  • 統合されたシステムが、特定の要件を満たすことを実証するためのテストプロセス。
  • インプット(妥当性を検証する対象):要件定義書など

④受け入れテスト

  • 「システムが、ユーザーのニーズ、要件、ビジネスプロセスを満足するかチェックする公式テスト」
  • 受け入れテストの対象は、システムテストを実施し検出した欠陥への対処を完了した、システム全体
  • インプット(妥当性を検証する対象):ユーザー要求、契約要件

4. アジャイル4象限による定義というか分類

アジャイルテストは、 ビジネス面または技術面の軸とチームを支援する目的か製品を批評する目的かの軸による4象限の分類で説明されている。

  1. 技術面: 作る側の面
  2. ビジネス面: 出来上がったものを検証する面
  3. チームを支援する: チームの効率化の面
  4. 製品を批評する : 欠陥を探す面

各象限の概要は以下のとおり。

image.png

第1象限(内部品質中心)

第1象限はチームを支援する技術面のテスト。テスト駆動開発などアジャイル開発の中心である。 - 単体テスト - コンポーネントテスト

コンポーネントテスト

コンポーネントテストはコンポーネントの振る舞いを確認するもの。 コンポーネントテストはオブジェクト間の相互作用をテストすることによ り、コンポーネントの設計を助ける。コンポーネントとは単独に展開できるシステム全体のより大きな部分。

第2象限(外部品質と顧客要求)

第2象限はチームを支援するビジネス面のテスト。顧客の視点からのハイレベルの機能テストなど。 - 機能テスト - ストーリーテスト - プロトタイプ

機能テスト

システムの決められたインプットやアクションの期待する振る舞いを確認する。機能 (フィーチャ) とは、顧客によって記述された機能性 (ファンクショナリティ)の一部で、製品バックログの項目。機能は、関連するストーリーに細分化され、見積もられる。

ストーリーテスト

ストーリーテストはストーリーによってデリバリーされるコードの期待される動作を定義。ストーリーテストは、 機能要求を確認するビジネス面のテストもある。セキュリティやパフォーマンステストなどの技術面のテストもある。これらのテストはコードを確認するのと同様に、開発を推進するために使われる。

ストーリーとは、ユーザーや顧客にとって価値のある、ユーザー視点による機能性の短い記述。ストーリーは伝統的にインデックスカード上に書かれる。カードは典型的に、機能のオンライン記述を含む。例えば、「買い物客として、私は物をショッピングカートに入れて、後で会計をする」というのがストーリー。

ストーリーテストは、ユーザーストーリーに含まれる機能を対象にテストが実施される。ストーリーテストでは、利用者の行動過程と心理状態を想定したテスト設計が必要で、利用者に対する深い理解が求められる。

多くのアジャイルの実施者は、 「ストーリーテスト」 という用語を「受入テスト」と同義で使うことが多いらしい。

第3象限(機能面におけるプロダクト批評)

第3象限は製品を批評するビジネス面のテスト。

探索的テスト

探索的テスト (ET) はアジャイルの世界におけるテストの重要なアプローチ。テストケースを事前に設計しない。テストの実施を伴うテスト設計を組み合わせたインタラクティブなテストで、アプリケーションを学ぶことに集中する。

すでにテストされ、明らかになっているバリエーションを超えて行うことを可能にする。テスト実施者は過去の経験や学習をベースにテストを実行し、その過程や実行結果からテストの最終的な目的や範囲を決定。テストの実施に必要な設計書や、仕様書の準備がなくなるため、スピード感のあるテストが可能である。

探索的テストは、学習、テストの設計、テストの実行を1つのテストアプローチに組み合わせたもの。発見的アプローチとテクニックを厳格な方法で適用することで、多くの未発見のテストケースを明らかにする可能性がある。

テストを行うにつれて、テスト中であるシステムについて学習し、新しいテストを設計するために役立つ情報を用いることができるようになります。探索的テストは、徹底的なテストを通してソフトウェアを評価する手段ではない。満足のいく形でストー リーが完了したかを確認するために十分なことを行います。

探索的テストの価値のある副産物は、それを通して学習した結果である。よりテスト自動化が可能な領域を明らかにし、新しいストーリーにつながる新しい機能・機能の変更のアイデアをもたらす。

一方で、非常に属人性が高く、テストケースの網羅性も担保されないため、要件や仕様が明確に決まっているようなソフトウェアのテストには不向きと言われている。

一般的には、ソフトウェアテストを探索的テストのみで実施するケースは少ない。ドキュメンテーションをベースとする記述式テストと補完関係を持ちながら、テストが行われるのが一般的であるが、アジャイルにおいてはそうではない。

受入テスト

それぞれのストーリーがデリバリーしなければいけないビジネスの価値を定義するテスト。機能要求や、パフォーマンスや信頼性などの非機能要求を確認。それらは開発を導く役に立つが、テスト駆動開発でのコード設計に使われる単体レベルより高いレベルのもの。 受入テストは、ビジネス面と技術面のテストを含む広い意味を持つ。

第4象限(非機能面におけるプロダクト批評)

第4象限は技術面のテストを使った製品の批評。

  • 負荷テスト
  • セキュリティテスト

参考:実践アジャイルテスト テスターとアジャイルチームのための実践ガイド (IT Architects' Archiveソフトウェア開発の実践)

5. テストピラミッド・テスティングトロフィー

  1. 静的テスト
  2. 単体テスト
  3. 統合テスト
  4. E2Eテスト

分類は以上になる。基本的にこれが好きだけど、自動化できるテストしかスコープにない。手動テストは無くせないのでどうするべきか悩む。

テストピラミッド

テストレベルごとにテストの量(数・実行)を上層ほど小さく下層ほど大きく(ピラミッド型に)すると良いというコンセプト。大半のプロダクトはこの形が望ましいと言われる

テストピラミッドは、テスト・スイートにおいて、 次の異なる種類のテストがそれぞれ特定の割合でテスト・ケースを持つようになっている、ということを提唱している概念です。

このテストピラミッドの横幅はテスト・スイートを構成する各種類のテストのに含まれるテスト・ケースの数を示します。 そのため、テスト・ピラミッドの層が横に長いものほど、テスト・ケースが多いことになります。次に、テストピラミッドの高さは、対象のテストがどれくらいエンドユーザの視点に近いのかを示します。

Vladimir Khorikov (著) 須田智之 (翻訳) 「単体テストの考え方使い方」より引用

テスティングトロフィー

React Testing Libraryの作者であるKent C. Dodds氏は「Testing Trophy(テスティングトロフィー)」というインテグレーションテストに最も重点をおいたテストコンセプトを提唱。

image.png

kentcdodds.com

kentcdodds.com

kentcdodds.com

しかし、ピラミッドの上に行くほど、それぞれのテストの信頼指数が高くなることは、この図では示されていません。(中略)統合テストは、信頼性と速度 費用のトレードオフのバランスをうまくとっています。 このため、ほとんどの労力をそこに費やすことが推奨されます (すべてではありませんが)。

https://kentododds.com/blog/write-tests より引用

参考動画

www.youtube.com

静的テストとは

動的テストはプログラムコードを実行して行うテストです。

実装が完了したソフトウェアを手元で動かしてみて、製品仕様を満たしているか、意図しない挙動やバグが発生していないか、チェックを行います。テスターはプログラムの内部状態を把握せずにテストを実施します。

一方、静的テストではプログラムコードを実行しない。

ソフトウェアのソースコードを対象に、第三者によるコードレビューや、コード解析ツールによる分析を行う。コード内の「バグ発見」「脆弱性発見」「メンテナンス困難なコード検出」などをサポートする自動コードレビューを行う。ソフトウェアの内部構造を細かくチェックするため、実装ミスや仕様漏れを開発プロセスの早期に解決できると言われている。

動的テストと静的テストは、どちらか一方を実施すればいいというものではなく、相互補完的に実施することで、ソフトウェアの品質向上を実現する。

プロジェクト途中から導入の問題点

とんでもなくエラーとか警告吐かれる可能性が高い。これの対応だけでかなりの対応コストが取られると思われる。実際の導入には慎重になる必要がある。

「大きな修正を行うタイミング」を狙うしかないか。

例えば、リリースからの半年or1年は安定稼働を主とし、この期間で 静的解析ツール導入+単体テスト結合テストを実施する。最低限80%以上の担保など基準を設ける。

もしくは、「管理画面の全改修」のような目玉機能+品質確保というような形で導入する。この場合の導入では全てを対応する訳ではなく、優先度をつけて対応 ※約60%以上の担保を目標とするなど、段階的な実現を狙う。このような形で対応していくしか ないか・・。

6. 単体テストの定義と流派

書籍 「単体テストの考え方/使い方」 では単体テストと統合テストを次のように定義している。

単体テストの定義と性質

  1. 単体(Unit)と呼ばれる少量のコードを検証する
    1. (1単位の振る舞いを検証すること)
  2. 実行時間が短い
  3. 隔離された状態で実行される
    1. (他のテストケースから隔離された状態で実行されること)

※ 対象はドメインモデル・ビジネスロジックアルゴリズムである

の3つの性質を持つ。

3つの性質のうち1つでも損なっているものを統合テストに分類している。 ただし、 上記定義でも全てが明確になるものではなく、 例えば 以下のように古典学派とロンドン学派によって「Unit」の定義・範囲が異なる。最も重要な焦点は「隔離された状態」の考え方である。

隔離に対する考え方の違いは、単体とは何か、そして、テスト対象システム (SystemUnder Test: SUT) が必要とする依存をどのように扱うのか、ということに関する見解に影響を与えている。

本来の単体テストの意義としては古典学派であると考える。ビジネス的に意味のあるテストで言えば完全古典学派の考え方である。

ただしその場合、統合テストとの責務の分け方がやや曖昧になりうる。以下の「ロンドン学派にとっての統合テスト」を参照

 

隔離対象

Unitの意味

テストダブル(モック)の置換対象

置換対象例

ロンドン学派

単体

1つのクラス

不変である依存対象(本来のValueObjectがこれ。Setterなし。そ他、enumもこれにあたる)以外の全ての依存

不変オブジェクト以外は全て対象

古典学派

テスト・ケース

1単位の振る舞い (a unit of behavior) を検証

1つのクラス、もしくは、同じ目的を達成するためのクラスの1グループ

共有依存
※ 読込専用API(取得のみなど)は当たらないが、モックにしても良い。

  1. DB

  2. 可変な static フィールド

  3. シングルトン

ロンドン学派(モック主義者)

テスト対象となる単体を他の単体から隔離すべきである、という考えを持っている。 そして、 ロンドン学派の考える 「単体」とは、 1単位のコード(a unit of code)、 つまり、 クラスのことと考えている。 そのため、ロンドン学派の単体テストでは、不変依存を除くすべての依存がテスト・ダブル(モック)に置き換えられる。ただし、モックは所詮モック。作成者の思い描く挙動でしかなく、本物の挙動であることは保証されない。

古典学派(デトロイト学派)

古典学派では、 クラスを隔離するのではなく、単体テストのテスト・ケースをそれぞれ隔離しなくてはならない、という考えを持っている。 そして、古典学派の考える 「単体」とは、 1単位のコードではなく、 1単位の振る舞い (a unit of behavior)のことを指している。 古典学派の単体テストでは、他のテストケースの実行に影響を与えるであろう共有依存だけをテスト ダブルに置き換えるようになっている。単一のテストで共有依存先のデータを変更したことにより、次のテストの成否が左右される様なものは共有依存である。

両学派の比較

  • ロンドン学派の長所はより細かな粒度で検証できることに加え、複雑に絡み合った依存関係を持つクラスのテストが簡単に行えるようになること、さらには、テストが失敗したときにその原因となるバグが潜んでいる箇所を見つけやすくなることがある。
  • ロンドン学派の長所は魅力的なように思えるが、課題もいくつか抱えている。 まず、単体テストにおいて、テスト対象の焦点をクラスに当てることは間違いである。焦点を当てなくてはならないのは1単位のコードではなく、 1単位の振る舞いである。さらに、もし、一部のコードを簡単にテストできないのであれば、それはコードの設計に問題があることを強く示唆している。 しかも、この問題はテスト ダブルを使っても解決できるものではなく、仮に、テスト ダブルを使ってテストを行えるようにしたとしても、問題そのものはテストの際に隠れるようになっただけに過ぎない。
  • また、ロンドン学派が単体テストの導入において利点として考えている、テストが失敗した際、どこにバグが潜んでいるのかを簡単に見つけられるようになる、ということは確かに有用な事実ではあるが、古典学派の単体テストと比べて、その有用性にあまり大きな違いはない。なぜなら、古典学派の単体テストであっても、プロダクション コードを変更するたびに単体テストを実施するようにしていれば、どこに間違いがあったのかをすぐに見つけられるからである(つまり、最後に修正をした部分がバグを持ちこんだ部分ということになる)。
  • ロンドン学派の最大の課題は検証内容が詳細になり過ぎてしまうことである。 つまり、単体テストがテスト対象の内部的なコードと密接に結び付いてしまうことである。

ロンドン学派にとっての統合テスト

古典学派にとっての単体テストは、共有依存やプライベート依存を用いたテストは全て統合テストとなる。 プライベート依存とは共有されない依存であり、可変依存と不変依存に別れる。不変依存とは、上記で言うところの ValueObject である。可変依存とはテスト対象とはならないが、テスト実施に必要なオブジェクトで協力者オブジェクトなどと呼ぶ。ロンドン学派は協力者オブジェクトもモックに置き換え、呼び出された際にどの様な振る舞いをするかを、以下の様に事前に定義してから検証を行う。 Mockito.doReturn(toBeReturn)when(mock).getSomeThing(any(), anyString(), anyInt());

古典学派では、when()の引数にある mock オブジェクトをコンストラクタで初期化しインスタンス化して使用するため、古典学派にとっての単体テストはロンドン学派からすると統合テストに分類されるわけだ。ただ、一般的には(自分の観測範囲内であるが)その辺りが混在しているためあまり気にしても意味がないし、そこまで明確に区別して運用できる気もしない。メンバーによって定義ややり方がバラバラすぎるし、最初から統一するというなら解るけど、リリース後などの途中から統一することの費用対効果がよくわからない。自分だったらその時に出来上がっているやり方でその後のテスト戦略を考える。最初から考えられているのがベストだけど。

テスト対象をSUT(System Under Test)と呼ぶため変数名をSUTとすることもある。

Java においての ValueObject は setter をつけられるせいで可変にできてしまうため、不完全な ValueObject が散見されたり、不変であることが ValueObject であると定義されるが、そもそも不変でしか扱えない言語発祥の概念のため定義となり得ない。前提でしかない。本来の定義は「一意の識別子ではなく、自身の持つ値の組み合わせのみによって識別性を有するオブジェクト」である。例えば、位置情報を表現するオブジェクトである。緯度と経度という二つのフィールドによってオブジェクトが識別される。

詳しくはこちらを参照

martinfowler.com

古典学派の定義の延長線上にある統合テストとE2Eテストの考え方

統合 (integration) テストとは、単体テストが持つべき1〜3の性質を1つでも欠いたテストのことであり、対象はドメインモデル・ビジネスロジックではなく、コントローラとなる。統合テストはドメインモデルとプロセス外依存を結びつけるコントローラを検証する。 下記の定義は古典学派の定義に則っって再定義された単体テストの定義である

  1. 1単位の振る舞い (a unit of behavior) を検証すること
  2. 実行時間が短いこと
  3. 他のテスト・ケースから隔離された状態で実行されること

E2E (End-to-End) テストは統合テストの一種であり、エンド・ユーザの視点からシステムを検証するため、テスト対象のアプリケーションが使用するすべての(もしくは、ほぼすべての)プロセス外依存をそのまま使ってテストすることになる(統合テストもプロセスが依存を1•2個は使用されることもある)。

プロセス外依存とは「更新機能を有する外部API」「DB」などがあたる。DBは共有依存でもあり、プロセス外依存でもある。統合テストとE2Eテストの違いは「プロセス外依存」を多く含むか含まないかである。多く含めば含むほど、ユーザ視点の操作に近くなる。また、統合テストで扱われるプロセス外依存は開発者の制御下(DBなど)にあるものが、E2Eテストでは制御外のプロセス外依存を含める(外部APIなど)。ただし、E2Eでも全てのプロセス外依存を扱えるわけではない。自前で用意する場合もあるが、その場合は統合テストとの境界線が曖昧になる。

image.png

Vladimir Khorikov (著) 須田智之 (翻訳) 「単体テストの考え方使い方」より引用

7. Googleの定義

テストサイズ テストの実行速度と決定性に着目したテスト分類

書籍 「Googleのソフトウェアエンジニアリング」より

「実行速度が十分に速くて安定した 偽陽性偽陰性がない=決定性がある) テストならいくらあっても良い」

Smallテスト (小テスト)

単一プロセス (シングルスレッド) 内で実行されなければならない。 sleep禁止。 I/O禁止。 ブロック禁止

Midiumテスト (中テスト)

単一マシン内で実行されなければならない。 localhost以外のシステムへのネットワーク呼び出し禁止

Largeテスト (大テスト)

複数マシンにまたがるテスト 。より定義がはっきりしているので、認識を揃えるために本発表ではテストサイズを使った説明を試みる

想定アプリケーションとテストサイズのイメージ

  • 専用のDBを持ち他のコンポーネントと連動しながら動くAPIサーバ
  • Smallテストはテスト対象がAPIサーバ内部
  • MediumテストはAPIサーバ専用DBまでをテストデータベースとして用意
  • Largeテストはコンポーネント全体の動作が対象

※ 上述した単体テストの定義と流派」で紹介する単体テスト・統合テスト・E2Eテストの範囲を示す図に似ている。

image.png

テストサイズ + テスティングトロフィー

  • テストサイズでテスティングトロフィーを表現
  • SmallテストよりMidiumテストを重視した構成になる

image.png

8. test の種類・観点・技法まとめ

ここでは、上記で紹介したさまざまな世界観・開発手法・学派などで区別せずより一般化した分類で記述している。

【テスト種別】

単体テスト

  • モジュールテスト
  • 制御フローテスト(命令、分岐などパターンで確認)
  • データフローテスト(定義→使用→消滅)

結合テスト・機能テスト

  • 状態遷移テスト
  • モジュール連携テスト

システムテスト

  • 確認テスト
  • 評価テスト
  • 負荷テスト
  • 環境テスト
  • 機能テスト
  • アドホックテスト(ランダムテスト)
  • 探索型テスト
  • リスクベーステスト
  • モデルベーステスト
  • エラー推測テスト
  • ミューテーションテスト
  • バックトゥバックテスト
  • ローカライゼーションテスト

ユーザーテスト 

  • 受入テスト(ユーザー要求を満たしているか)
  • 運用テスト(実際の操作環境下にて)
  • αテスト(試作段階のものを開発者にて)
  • βテスト(開発者以外のユーザーが操作)

【テスト観点】

機能 

正常系

  • 基本機能:アプリケーションの基本的な機能
  • 機能仕様を満たす(機能仕様書参考)
  • 表示:画面表示の正確性
  • 遷移:画面間の適切な移動
  • データCRUD:データの作成、読み取り、更新、削除の正確性
  • 設定(保持・変更・反映): アプリケーション設定の保持、変更、反映の正確性
  • GUI:正確性。操作に問題がないか?(機能仕様・UX面など)
  • アップロード・ダウンロード:ファイルの正常なアップロードとダウンロードの検証
  • セキュリティ:セキュリティ機能の検証
  • インストール:アプリケーションの正常なインストールの確認
  • 外部接続:外部システムやAPIとの適切な接続確認
    • 外部API・外部検索エンジンの使用(接続)に問題がないか?
    • 極端にレスポンスが重い・レスポンス結果に異常がないか、など

異常系

  • 異常値入力:不正な入力に対するアプリケーションの振る舞い(バリデーションなど)
  • 記憶装置異常:ストレージやメモリの異常な動作の検証
  • エラー検知:エラーや障害がキャッチされているか?
  • 異常状態:キャッチされた後のハンドリングが想定通りか?
  • エラーメッセージ:想定通りのエラーメッセージが表示されているか?
  • エラー復旧:正常にハンドリングがされた場合に適切なエラー画面などの表示
  • 異常環境:異常な環境下での挙動。ネットワーク異常環境とかWifi切るとかで再現できるんちゃう?
  • 異常操作:ユーザーの異常な操作に対する振る舞い。連打、バック・フォアグラウンド操作とか?
  • エラーログ:エラー発生時のログの正確な記録や出力

組み合わせ

  • 同時操作
  • 構成
  • 割り込み操作
  • 設定
  • 排他制御(同時アクセス)
  • 相互運用性
  • 互換性
  • オプション/付属品

非機能

パフォーマンス

  • 処理速度
  • 連続動作
  • 負荷
  • 通信帯域不足
  • 大容量
  • リース不足

ユーザー

テスト

【テスト技法】

9. テストの7大原則

テストの7つの原則(Seven Principles of Testing)は、ISTQB(International Software Testing Qualifications Board)が提唱するソフトウェアテストに関する基本的な指針。

1. テストは欠陥があることしか示せない

テストにより、欠陥があることは示せるが、欠陥がないことは証明できない。テストにより、ソフトウェアに残る未検出欠陥の数を減らせるが、欠陥が見つからないとしても、正しさの証明とはならない。

2. 全数テストは不可能

すべてをテストすること(入力と事前条件の全組み合わせ)は、ごく単純なソフトウェア以外では非現実的である。全数テストの代わりに、リスク分析、テスト技法、および優先度によりテストにかける労力を集中すべきである。

バグは“数千パターンのテスト”をすり抜けた―NTTデータ「2023/10/10 全銀ネット障害」について説明

バグは“数千パターンのテスト”をすり抜けた ―NTTデータ「2023/10/10 全銀ネット障害」について説明 | gihyo.jp

image.png https://twitter.com/ockeghem/status/1723553968629129645?s=20

3. 早期テストで時間とコストを節約

早い段階で欠陥を見つけるために、静的テスト活動と動的テスト活動の両方をソフトウェア開発ライフサイクルのなるべく早い時期に開始すべきである。早期テストは、シフトレフトとも呼ばれる。ソフトウェア開発ライフサイクルの早い時期にテストを行うことにより、コストを低減または削減できる。

4. 欠陥の偏在

リリース前のテストで見つかる欠陥や運用時の故障の大部分は、特定の少数モジュールに集中する。テストの労力を集中させるために欠陥の偏在を予測し、テストや運用での実際の観察結果に基づいてリスク分析を行う。(原則2で触れたことと同様)。

5. 殺虫剤のパラドックス

同じテストを何度も繰り返すと、最終的にはそのテストでは新しい欠陥を見つけられなくなる。この「殺虫剤のパラドックス」を回避するため、テストとテストデータを定期的に見直して、改定したり新規にテストを作成したりする必要がある(殺虫剤を繰り返し使用すると効果が低減するのと同様に、テストにおいても欠陥を見つける能力は低減する)。ただし、自動化されたリグレッションテストの場合は、同じテストを繰り返すことでリグレッションが低減しているという有益な結果を示すことができる。

6. テストは条件次第

状況が異なれば、テストの方法も変わる。例えば、安全性が重要な産業用制御ソフトウェアのテストは、eコマースモバイルアプリケーションのテストとは異なる。また、アジャイルプロジェクトとシーケンシャルソフトウェア開発ライフサイクルプロジェクトでは、テストの実行方法が異なる。

7.「バグゼロ」の落とし穴

テスト担当者は可能なテストすべてを実行でき、可能性のある欠陥すべてを検出できると期待する組織があるが、原則2と原則1により、これは不可能である。また、大量の欠陥を検出して修正するだけでシステムを正しく構築できると期待することも誤った思い込みである。例えば、指定された要件すべてを徹底的にテストし、検出した欠陥すべてを修正しても、使いにくいシステム、ユーザーのニーズや期待を満たさないシステム、またはその他の競合システムに比べて劣るシステムが構築されることがある。

ソフトウェアテストは品質保証において必ずしも万能ではない。 それぞれの詳細は以下のサイトが非常に勉強になる。

appkitbox.com

10. 参考資料