単体テスト (ユニットテスト)とは
単体テスト (ユニットテスト) とは、プログラムの個々のコンポーネント、つまりユニットの機能を、アプリケーションの他の部分から切り離して検証を行うソフトウェアテスト手法です。
「ユニット」とは通常、関数、メソッド、クラス、スクリプトなど、テスト可能なプログラムの最小単位を指します。複雑なスクリプトやアルゴリズムをこうした小さい単位に分解することで、各コンポーネントの機能に的を絞って検証を行う正確なテストを作成できます。
単体テストが重要な理由
早い段階で各ユニットの単体テストを行うことでエラーの発見や修正が可能になるため、コードの信頼性を高めて、時間を要する複雑なデバッグ作業を軽減することができます。単体テストは、モジュール化されたメンテナンスの容易なソフトウェアの開発にも活用できるため、コードの品質向上につながります。
単体テストのメリットと課題
単体テストには、次のようなメリットがあります。
- システム全体または広範囲のテストに比べて、単体テストは簡単に記述でき、素早く実行できることが多い
- 早い段階でバグを特定して対処しやすい
- ソフトウェアの他の部分の問題を特定しやすくなり、サブシステム間の処理を最小限に抑えられる
- アプリケーション全体の完成を待たずとも、開発の早い段階でテストを開始できる
一方で、各ユニットを単体でテストしても、すべての問題を検出できるとは限らないという点が課題になっています。
単体テストの実施タイミング
コード品質を確保して変更の影響を把握するためには、以下の開発プロセス全体を通して、単体テストを実施する必要があります。
- 開発中: 新機能の開発と同時に単体テストを記述します。これにより、開始時点から各コンポーネントが想定どおりに機能することを確認できます。
- リファクタリング時: 単体テストを用いて、リファクタリング処理でコードの想定動作が変更されていないことを確認します。
- バグ修正後: 修正されたバグに対して単体テストを実行することで、今後の再発を防止し、修正が他のソフトウェア機能に影響を与えていないことを確認します。
- 統合前 / 統合時: 変更をメインコードに統合する前や継続的インテグレーション (CI) パイプラインに組み込む前に、単体テストを実施します。これにより、新しいコードに起因するエラーを防止し、安定したコードベースを維持することができます。
ソフトウェアテストピラミッド
ソフトウェア開発の初期段階からプロセス全体を通して単体テストを行うことは、コードの品質向上を促進します。しかし、単体テストは包括的戦略の一部にすぎません。以下のソフトウェアテストピラミッドには、単体テスト、統合テスト、システムテストが異なるレベルで図示されており、それぞれ粒度と頻度がわかるようになっています。このピラミッドにより、テスト作業の管理や優先順位付けを体系的に行うことができ、最適なソフトウェア品質を実現するために必要なテストの比率が明確になります。
それぞれのテストには、次のような特徴があります。
- 単体テストは、ピラミッドの土台となる層で、粒度と実行頻度が最も高くなっています。単体テストは一般的に規模が小さいため、素早く作成して実行でき、費用対効果にも優れています。開発プロセスの早い段階で実行が可能なため、即座に各コンポーネントの機能性に関するフィードバックを得ることができます。
- 統合テストは、ピラミッドの中間層に位置し、異なるコンポーネントやシステム間の処理に重点を置いて検証を行います。単体テストよりもやや複雑で時間がかかりますが、統合されたコンポーネントが想定どおりに連動して機能することを確認するためには不可欠です。
- システムテストは、ピラミッドの頂点にあり、アプリケーション全体を評価します。より包括的で多くのリソースを必要とします。通常、開発サイクルの後半に実施され、システム全体が指定した要件を満たしているかを検証します。
このピラミッドでは、単体テストのような下層レベルのテストの頻度を増やし、上層レベルのテストを減らす重要性が強調されており、プロジェクトの完了までに、単体テスト 70%、統合テスト 20%、システムテスト 10% の比率で実施することを目標としています。この戦略により、信頼性の高いコードの基盤が確立され、上層レベルのテスト段階における問題発生率を抑えることができます。
その他のソフトウェアテスト
ソフトウェアテストピラミッドで示されているテストの粒度と頻度以外にも、いくつかのテスト手法があり、それぞれ想定する結果に応じた特定の目的があります。主に機能テストと非機能テストに分類されます。
- 機能テストは、ソフトウェアの正しい機能と動作を検証することに重点を置きます。例として、基本的な機能をチェックするスモークテストや、新たなコード変更が既存の機能に影響を与えないことを確認する回帰テストなどがあります。
- 非機能テストは、使いやすさやセキュリティ、安定性など、ソフトウェアの他の重要な側面を評価します。非機能テストの最も典型的なのがパフォーマンステストで、負荷やストレスといった特定の条件下でソフトウェアがどの程度正常に機能するかを評価します。
機能テストと非機能テストの両方を活用することで、ソフトウェアが正しく機能し、品質標準を満たしていることを確認できます。
MATLAB を使用した単体テスト
コードのテストは、品質の高いソフトウェアを開発する上で不可欠です。MATLAB® には、単体テストを作成して、コード機能にリグレッションがないか監視できる、強力な組み込みフレームワークが用意されています。このフレームワークはクラスを使用したテスト作成をサポートしているため、テストの論理的な構築が可能になります。さらに、テストを実行して結果を解析することもできます。
クラスベースの単体テスト
この手法では、テストをクラス内のメソッドとして定義します。MATLAB では汎用テンプレートを生成でき、MATLAB Test™ では特定のコードに対応するテストを生成できます。この手法を用いることで、テストメソッド内でスクリプトや関数のテストが可能になり、オブジェクト指向プログラミングのメリットと、さまざまなコードタイプをテストする柔軟性を組み合わせることができます。この例では、クラスベースの単体テストの記述方法について解説しています。
テストの実行
テストファイルを保存した後、MATLAB ツールストリップからテストを実行できます。また、runtests
関数や MATLAB のテスト ブラウザー アプリを使用して、テストの実行、結果の表示、エラーのデバッグを対話的に行うこともできます。
テスト結果の解析
MATLAB には、ソースコードを解析するための要約、詳細レポート、コードカバレッジが用意されています。
さらに高度な機能として、MATLAB Test には、自動テスト生成、強化されたテスト管理、CI/CD システムとの統合、高度なコードカバレッジ、品質ダッシュボードなど、テストプロセスを強化する機能が追加されています。テスト結果解析の詳細については、こちらをご覧ください。
MATLAB の単体テスト例
以下の例は、単純な fibonacci
関数に対して単体テストを実行する方法を示しています。この関数は指定された数 (n) までのフィボナッチ数列を計算します。この計算の正確性を検証するためにサンプル入力を用意し、単体テストで計算出力がその入力値に対する期待出力と一致しているか否かをチェックします。出力が一致していればテストは合格で、そうでなければ不合格になります。
function x = fibonacci (n) % 最初の n 個のフィボナッチ数を生成します n=6; x = ones (1,n); for ii = 3:n; x(ii) = x(ii - 1) + x(ii - 2); end end
% これはファイル fibonacci.m に対して自動生成されたサンプルテストです classdef test fibonacci < matlab.unittest.TestCase methods (Test) function test_fibonacci (testCase) % fibonacci の入力を % 指定します n = 6; % 想定する fibonacci の出力を % 指定します expected_x = [1, 1, 2, 3, 5, 8]; % fibonacci 関数を実行します actual_x = fibonacci(n); testCase.verifyEqual(actual_x,expected_x); end end end
製品使用例および使い方
ソフトウェア リファレンス
参考: MATLAB Test, ソフトウェアテスト