プログラミング初心者が調べてみたソフトウェアテストのあれこれ

ソフトウェアの開発において、テストの実施は必要不可欠です。そこで、エンジニアとしてコードを書くだけでなく、ソフトウェアテストに関しても知見を広げるべきだと考えました。初学者である私が、テスト技法に関して網羅的に理解を深めたいと思い、この記事を書いています。
この記事作成を通して、初学者である私が感じた学習に対する認識の変化も書いているので、是非最後まで読んでいただけると幸いです。
# ソフトウエアテストの目的
ソフトウェアテストを行う主な目的は、「欠陥（バグ）を発見すること」にあります。
テストによって、「欠陥がある」ことは示せても、「欠陥がない」ということは証明できません。つまり、欠陥が見つからないとしても、正しさの証明にはなりません。
また、テストに共通する目的として、
* 欠陥を発見する。
* すべての要件を満たしているか検証する。
* テストを繰り返し、品質が所定のレベルにあるか検証する。
* 品質レベルに関して、クライアントが意思決定をするのに十分な情報を提供する。
などがあげられます。
（JSTQB Foundation Level シラバスより）
# テストレベル・技法
テストは、
テストの工程が存在し、その工程によってどのようなテストを行うかが判断されます。
主に、
* コンポーネント（単体）テスト
* 結合テスト
* システム（総合）テスト
* 受入テスト
に分類されます。
また、
* ある特定の目的
* テストする対象は何か
* 典型的な欠陥や故障
等によって、テストレベルが特徴づけられます。

### コンポーネントテスト
テスト工程の初めに実施されるテストです。
コンポーネントには「構成要素」、「部品」などの意味があり、テストにおいて独立してテストできるソフトウェアの最小単位を表します。
このテストでは、各機能や画面が単体で適切に動作するかを検証します。
などがあげられます。ユニットテスト、モジュールテストとも言われます。

* 主な目的
このテストはテスト工程の最初に行われます。各機能が仕様通りに動作するか、仕様に漏れがないかなど、早い段階で確認することで、のちのテストレベルで新たな欠陥が見つかるリスクを軽減するために重要です。
このテストで発見される欠陥は確認する範囲が限定されているため、どのソースコードに問題があるのか把握しやすいという特徴があります。
これによって、不具合を修正するためのコスト削減が図れます。

* 技法の例
ホワイトボックステスト、ブラックボックステスト

### 結合テスト
コンポーネントテストの次に行われるテストです。
コンポーネントテストとは違い、複数のプログラムを組み合わせて実際のソフトウェアに近い状態で挙動の確認が行われます。
具体的には、データの受け渡しが正常に行われるか、データを渡すタイミングは適切かなどを判断します。

* 主な目的
結合テストで考慮することが、のちの「システムテスト」、「受け入れテスト」にも影響し、テストの工数や品質に大きな影響を与えると言われています。
コンポーネントテストと同様に、結合テストによって得られたフィードバックは具体的かつ確認する範囲が比較的小さいため、欠陥の発生箇所を特定することが容易になります。
それ以降のテストレベルでは、得られるフィードバックが抽象的なことが多いため、欠陥箇所の特定に時間を要します。
だから、結合テストの段階で欠陥を発見する必要があります。
また、コンポーネントテストを経て、独立した機能を組み合わせる最初のテストです。そのため、綿密なテスト計画やチーム内でテストの粒度の認識合わせをする必要があります。

* 技法の例
インターフェーステスト、ブラックボックステスト、業務シナリオテスト、負荷テスト

### システム（総合）テスト
システム構築後、全ての機能が揃った状態で、全体を通して要件通りの性能や機能を果たしているかを検証するテストです。
ハードウェアや通信回線なども含めて、要件に準拠しているか、機能間での連携は取れているか、運用や保守が実現可能であるかなどが評価されます。

* 主な目的
結合テストが設計書の内容に沿っているかを確認するのに対し、システムテストでは、要件定義書に記載されている内容に沿っているかどうかを確認します。また、テスト環境においても、テストデータではなく実際のハードウェアや通信回線などを使って、より本番に近い環境でテストが行われます。
主に、「機能要件」と機能以外の「非機能要件（性能や拡張、運用や保守、移行、セキュリティなど）」に関して確認します。

#### 非機能要件とは？
IPAで定義されている、非機能要求グレードの6大項目について紹介したいと思います。
https://www.ipa.go.jp/files/000005076.pdf

1. 可用性：利用者が必要な時に使うことができるかを確認する。保守やメンテナンスによる利用停止時間、復旧方法や復旧にかかる時間なども確認する。

2. 性能・拡張性：処理速度やデータ量などのパフォーマンス。システム拡張、機能追加への対応のしやすさ。

3. 運用・保守性：運用や保守を行う中での処理時間など。

4. 移行性：システムへの移行期間、方法、データの種類や量を確認。

5. セキュリティ：不正アクセスなどのセキュリティ診断、認証や利用制限を確認。

6. システム環境・エコロジー：設置環境の耐震や免震、温度や湿度、場所、電圧などを確認する。

* システムテストの流れ
システムテストは、「テスト計画」、「テスト設計」、「テスト準備（環境・データ）」、「テスト実行」、「テスト実行進捗管理」、「テスト完了」という順に沿って行われます。
開発の設計、実装する工程と並行して行われます。
テストの対象範囲や、環境、役割、スケジュール、テストの合格基準など細かくテスト計画を行うことが重要です。
この計画に従ってテストを実行し、不具合を記録するという一連の流れを繰り返し、テストが完了に向かっていきます。

* 技法の例
機能テスト、構成テスト、回帰テスト、ユーザビリティテスト

### 受け入れテスト
受入テストでは、ソフトウェアやシステムの開発を受注を行った側が実際に近い環境で、ソフトウェアを使用します。その結果をもとに、利用者のニーズを満たしているのか、納品後にソフトウェアが運用可能な状態なのかを検証するテストです。

* 主な目的
このテストはテスト工程において最後に行われます。開発を発注した側が実際に使用する環境やそれに近い環境で検証が行われます。
たとえ、仕様書にあったソフトウェアであっても、実際の利用環境において機能しなければ、意味がありません。
そのようなことを防ぐために、受け入れテストを行います。発注側の求める要件を満たしているかどうかだけでなく、快適に利用できるか、使用するうえでの不都合は生まれないかなど使用を見据えたテスト結果をもとに、最適化を図ることが目的とされています。

# まとめ・感想
* ソフトウェアテストの目的は、「バグを発見すること」。
* ソフトウェアテストは、「コンポーネント（単体）テスト」、「結合テスト」、「システム（総合）テスト」、「受け入れテスト」のテストレベルに分類される。
* コンポーネント（単体）テストは、テスト工程の初めに各機能が単体で動作するかを検証する。
* 結合テストは、独立した機能を組み合わせて行われる。
* システム（総合）テストは、全体が要件通りに性能や機能を満たしているかを検証する。より本番に近い環境でテストが行われる。
* 受け入れテストは、発注した側が、実際の環境でソフトウェアを使用することで行われるテスト。

ソフトウェアテストについてまとめてみて思ったことは、
「工程が多すぎる！！」
ということです。
テストの工程が分かれているだけでなく、それぞれのテストにも手順があり、1つのシステムを開発して使えるようになるまでが大変長い道のりなのだと感じられたことが大きな収穫でした。
テストについて理解を深められたことで、自分がコードを書く際に意識できることもあると思いました。
私のような初学者でも、プログラミング学習に対して、より理解を深めていく一助になったので参考にしてみてください！


* 参考にした記事
https://service.shiftinc.jp/column/3636/
https://service.shiftinc.jp/column/3650/
https://service.shiftinc.jp/column/4740/
https://service.shiftinc.jp/column/3659/
https://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018V31.J03.pdf