システム開発におけるテストと単体テストの手法について
今回はシステム開発におけるテストについて書いてみます。
テスト不足によって、あとから重大なバグが発見されたり、原因の特定に時間がかかってしまったりなど、テストの重要性を身に染みて感じることが多いので「そもそもなぜテストが重要なのか」と、一般的なV字モデルにおけるテスト工程、そして単体テストについてまとめてみました。
1.テスト工程の重要性
開発プロセスにおいて、テスト工程ってつまらない…めんどくさい…と思いがち思われがちで、工数の兼ね合いで正常パターンだけしか確認してない…とかもやりがちかもしれません。しかし、システム開発におけるテスト工程はとても重要です。
テストは開発したプログラムが問題なく動作するか、また、要件や設計書通りに作成されているか、システムが期待通りに動作しユーザーが満足する品質であることを確認を行う工程です。
テストを怠ると、バグや不具合が発見されず、品質が低下する可能性があります。
要件が仕様に落とし込めているか、また要件が明確かつ正確に定義されていても、実際にシステムがその要件を満たしているかどうかを、テストせずには品質を保証することはできません。
テストはシステムが約束どおりに振る舞うことを確認するための”最終の防衛ライン”として不可欠です。要件と仕様のギャップを見つけ、修正することで、システム全体の信頼性を高めることができます。
テスト工程専門の開発会社やテスト専門のエンジニアという職種もあったり、「テスト駆動開発(Test-Driven Development: TDD)」というテストファーストなプログラムの開発手法もあるくらい、テストは開発プロセス全体で欠かせない要素であり、開発者も含めて開発工程全体で品質を意識していくことが重要になっています。
(TDDについては、初めて知りました。今後、詳しく調べてみたいと思います。)
品質の向上と証左が、クライアントやエンドユーザの満足度と信頼性に直結すると思うので、とにかくテスト工程はめっちゃ大事です!
2.V字モデルについて
いろいろな開発モデルがありますが、私の経験上は、V字モデルが多かったです。一般的なモデルだと思いますが、どのようなモデルかざっくりとお伝えしておきます。
V字モデルはソフトウェア開発モデルの一つです。要件定義や設計といった上流工程から製造・テストといった下流工程までの関係性を示すモデルです。
要求分析~受け入れテストまでがV字に並んでいることから、V字モデルと呼ばれています。
V字モデルでは、品質を決定する上流(要求分析~コーディング)と、品質を確認する下流(コードレビュー~受け入れテスト)の各工程の対応が明確に定義されているため、工程や作業プロセスごとに確認しやすいという特徴があります。
上流工程での仕様や設計が正しく行われることで、下流工程でのテストも効率的に実施できるようになります。
要件定義の内容をシステムテストで確認、基本設計の内容を結合テストで確認、というように、開発工程とテスト工程で各作業を対応させることで、実施されるテストがどのレベルの開発内容を検証するためのテストなのか、何に着目したテストが行われるのかを示すことができます。
ひとことで「テスト」と言っても、フェーズによって検証したい内容や着目したい内容、テスト観点がいろいろある、ということです。
参照:V字モデルとは?
3.単体テスト(UT:ユニットテスト、単体テスト、コンポーネントテスト)について
今回は、単体テスト(UT)で行われるテスト手法について、まとめたいと思います。
単体テストとは、開発したプログラムの最小単位(モジュールやクラスなど)を単独でテストする工程です。プログラムや機能単位の動作の確認を行うことを目的として行うテストです。
通常、モジュールやクラスごとにテストケースを作成し、それぞれのテストケースで期待される動作や結果を定義します。ここで発見された不具合は確認範囲が限定的なため、開発者が自身のコードをテストすることで、バグや不具合を早期に発見し対応しやすくなります。
この段階で不具合やバグをできる限りつぶしておくことで、以降のテスト工程での手戻りを防ぐことができ、システム全体の品質向上につながります。
蛇足:
いろいろなプロジェクトでの開発を経験したことがありますが、
①関数やモジュールなどの単位でのテストをUTと呼んだり、
②各機能単位や画面単位でのテストを単体テストと呼んでいるところもあり、プロジェクトや組織文化によって、「機能」の定義が異なるため「UTで対応する範囲」に差異があります。
前述のとおり「詳細設計に対応するもの」をテスト対象とすることがあるので、関数やモジュールのコードだけでなく、画面も対象になることがあります。
単体テストのやり方もプロジェクトによっていろいろだと思いますが、
デバッグ実行やログ出力で確認する方法やフレームワークを使用する方法などがあります。
ほとんどのプログラミング言語でテスト用のフレームワークが用意されているため、それを利用して「テストケース」と「テスト用プログラム」を作成することも多いです。
画面も対象となる場合は、見た目や入出力項目が適切か、も確認します。
単体テスト仕様書やテストのエビデンスも、ドキュメントとして作成することがあります。テスト仕様書やエビデンス資料だけに関わらず、ドキュメントを作成することは、自分(というかプロジェクトチーム、組織)を守ることにもつながります。工数が許せばできるだけ残したい派です。
ツールや方法もいろいろですが、どのツールや方法を使うとしても
プロジェクト内で「単体テストの目的と観点と範囲」の認識を合わせておくことは大事だと思います。
4.単体テストの手法
ホワイトボックステスト
ソースコードが明らかな状態で行うテストでシステムの内部構造に重点を置いたテスト手法です。個々のモジュール中の命令文や条件判定「if-else文」といった論理的な構成とその組み合わせや、入出力のデータパターンによるエラーを発見することを目的としています。
「モジュール内で実行されうる処理を確認するテスト」という事になります。
- 制御フローテスト
分岐条件に特定データを設定することで、設計通りの動作を確認する手法です。一般的に、テスト対象は複数の分岐条件を持つため、すべてのパターンをテストしようと思えば膨大なテストを行わなくてはなりません。
本来であれば、全てのフローを検証することが理想ですが、制御フローの数は小規模なプログラムでも膨大になってしまうため、
- 命令網羅
テスト対象となるプログラムのすべての命令を一度は実行すること
- 分岐網羅
テスト対象となるプログラムに含まれる条件分岐について、そのすべての分岐を一度は実行すること
- 条件網羅
テスト対象となるプログラムに含まれる条件分岐について、その条件の組み合わせのすべてを一度は実行すること
などの基準を設け、限定的に実施される場合がほとんどです。 - データフローテスト
データフローテストとは、データが順番通り正しく処理されるかをチェックするためのテストです。プログラム内で使用されるデータや変数には、「定義→使用→消滅」というライフサイクルがあり、これをデータフローと呼びます。定義されていないのに使用しようとしたり、エラーが出る可能性のあるパターンが見つかることがあります。
(正直なところ、私はこのテストを意識したことがないかもしれません…。コード上のミスで定義されていないものを使用しようとすると、IDEなどでエラーが出るし、ブラックボックステストでケース網羅することで補完しているかもしれません…。)
ブラックボックステスト
ソースコードが不明な状態で行うテスト方法です。
テスト対象に期待する動作(仕様書で求められている動作)を検証するもので、モジュール内でデータがどのように処理されるには着目せず、入力と出力の整合性にのみ着目します。
①関数やモジュールなどの単位でのテストとして、テストコードやテストツールなどで、行うこともあれば
②各機能単位や画面単位でのテスト にて、画面上から手で入力してテストすることもあります。
画面で入力したりツールを使う場合は、コーディングのスキルは不要ですが、仕様に基づいたテストを行うため、仕様を正しく理解している必要があります。
単体テストでは主に「ホワイトボックステスト」がイメージされる気がしますが、
ホワイトボックステストだけでなく、ブラックボックステストも併用することで、内部仕様と外部仕様のずれを見つけることができます。
- 同値クラステスト
同値クラスとはモジュールで同等に処理される、あるいは同じ結果を返すデータの集合です。
例えば、 a >= 10 && a <= 20 の条件でなにか処理をする場合
・10未満
・10~20
・20より大きい
という3つのクラスにわけられます。
定義したクラスから代表値を選び、それぞれテストケースを作成します。 - 境界値テスト
同値クラスの境界値をテストします。
先ほどの同値クラスでいうと
9→×
10→○
11→○
19→○
20→○
21→×
となるかどうかを確認します。
画面テスト(フロントエンド側の単体テスト)
UTに含まれないこともあるかと思いますが、フロントエンド側の単体テスト、という観点では重要なテストだと思います。画面で確認するブラックボックステストも含んだテストと思って良いかもしれません。
仕様書・デザインなど画面設計書をもとにチェックすべきことを網羅します。
画面仕様
└ レイアウト、色、アイコン、画像、ヘッダー・フッターなど
└ アクション(○○をクリックしたら、とか、画面読み込み時になにが起きる、とか)
└ エラー時
└メッセージ …など…
単項目(入出力の各項目)
└ 桁数、表示形式、型
└ ボタン、ラベル、テキスト…など…
入力項目のバリデーション
└ 単項目仕様を満たしているか
└ 未入力チェック
└ 異常値
空文字、スペース、ゼロ値、null値
数字なのに文字列が入力された場合や、桁数以上入力した場合など
まとめ
- 品質のために各テスト工程はとても重要!
- プロジェクトによって文化に差異があるので「テストの目的と観点と範囲」の認識を合わせておくことも大事!
- 単体テストはプログラムや機能が単体で動作するかの確認することが目的
- 単体テストのテスト手法
ホワイトボックステストとブラックボックステスト、画面テストを併用することで、バグや不具合、また内部仕様(プログラムの仕様)と外部仕様(インターフェースや主要機能などの仕様)のずれを早期に発見できる!
テスト工程ってめんどくさい…と思いがちですが、テストはシステムの品質や信頼の向上、自分や組織を守ることにつながると思います。
また、このようなテスト手法や主なテスト観点を知っておくことで、コーディングする際も、バグや不具合になりそうなポイントを減らすことを意識して対応できるのではないかと思います。