Main Content

要件に基づくテストを使用した MATLAB アルゴリズムの検証

この例では、関数とテストの MATLAB® コード行から要件への検証リンクを作成して MATLAB アルゴリズムを検証する方法を示します。この例では、グラフ上の 2 つのノード間の最短経路を計算するアルゴリズムを含むプロジェクトを使用します。

プロジェクトを開きます。

slreqShortestPathProjectStart

プロジェクトのアーティファクトの確認

プロジェクトには以下が含まれます。

  • 機能要件とテスト要件の要件セット (requirements フォルダーに格納)

  • MATLAB アルゴリズム (src フォルダーに格納)

  • MATLAB ユニット テスト (tests フォルダーに格納)

  • MATLAB コード行から要件へのリンク (.slmx ファイルとして src フォルダーと tests フォルダーに格納)

  • プロジェクトの解析を自動化するためのスクリプト (scripts フォルダーに格納)

機能要件セットを開く

shortest_path_func_reqs 要件セットは、関数 shortest_path に必要な機能的な動作を取得したものです。定格の動作について記述した要件と、関数への入力が有効でない場合など、無効な条件における想定される動作について記述した要件があります。[要件エディター] で要件セットを開きます。

funcReqs = slreq.open("shortest_path_func_reqs");

最短経路関数の使用

関数 shortest_path は、関数への入力の有効性をテストしてから、ダイクストラ アルゴリズムを使用してグラフ上の 2 つのノード間の最短経路にあるエッジの数を計算します。関数への入力は、グラフ、開始ノード、終了ノードを表す隣接行列です。たとえば、6 つのノードをもつグラフを表す次の隣接行列について考えてみます。

A = [0 1 0 0 1 0;
    1 0 1 0 0 0;
    0 1 0 1 0 0;
    0 0 1 0 1 1;
    1 0 0 1 0 0;
    0 0 0 1 0 0];

行列からグラフを作成してプロットします。

G = graph(A);
plot(G,EdgeLabel=G.Edges.Weight)

ノード 1 とノード 6 の間の最短経路にあるエッジの数を計算します。

pathLength = shortest_path(A,1,6)
pathLength = 3

テスト要件セットを開く

shortest_path_tests_reqs 要件セットには、テスト ケースでテストする必要がある機能的な動作について記述したテスト要件が含まれています。テスト要件は機能要件から派生したものです。定格の動作についてのテスト要件と無効な条件についてのテスト要件があります。[要件エディター] で要件セットを開きます。

testReqs = slreq.open("shortest_path_tests_reqs");

graph_unit_tests のクラスベースの MATLAB ユニット テストには、shortest_path_tests_reqs で記述されているテスト ケースが実装されています。このクラスには、shortest_path_tests_reqs からのテスト要件に基づくテスト メソッドが含まれています。また、テスト ケースで検定メソッドとして使用する verify_path_length メソッドも含まれています。これを使用して、想定される結果と実際の結果が等しいことが検証されます。さらに、テスト ケースの隣接行列を作成する静的メソッドも含まれています。

検証の状態の表示

検証の状態を確認するには、[要件エディター] のツールストリップで [ビュー] セクションの showColumns_16.png [列] をクリックし、[検証の状態] を選択します。機能要件の 3 つとテスト要件の 1 つに検証リンクがありません。各要件の検証の状態が黄色であり、リンクされたテストが実行されていないことを示しています。

missingVerification.png

runTests メソッドを使用してテストを実行し、要件セットの検証の状態を更新します。

status1 = runTests(funcReqs);
Running graph_unit_tests
.......... ......
Done graph_unit_tests
__________
status2 = runTests(testReqs);
Running graph_unit_tests
.......... ....
Done graph_unit_tests
__________

検証の状態が緑色になり、リンクされたテストにパスしたことが示されます。ただし、テストへのリンクがない要件がいくつかあります。

プロジェクトのトレーサビリティ ギャップの特定

機能要件とテスト要件は shortest_path ファイルと graph_unit_tests ファイルのコード行にリンクされていますが、トレーサビリティが完全ではありません。トレーサビリティ マトリクスを使用して、テストにリンクされていない要件を特定し、リンクを作成して要件を完全にトレースできるようにします。

トレーサビリティ マトリクスを使用した欠損リンクの特定

要件を上にし、ユニット テストを左にして、両方の要件セットのトレーサビリティ マトリクスを作成します。トレーサビリティ マトリクスの詳細については、トレーサビリティ マトリクスを使用した要件リンクの追跡を参照してください。

mtxOpts = slreq.getTraceabilityMatrixOptions;
mtxOpts.topArtifacts = {'shortest_path_func_reqs.slreqx','shortest_path_tests_reqs.slreqx'};
mtxOpts.leftArtifacts = {'graph_unit_tests'};
slreq.generateTraceabilityMatrix(mtxOpts)

[フィルター パネル][上] セクションで、次のようにクリックして、テストにリンクされていない機能要件だけを表示するようにマトリクスをフィルター処理します。

  • [上][リンク][欠損リンク]

  • [上][タイプ][機能要件]

[左] セクションで、次のようにクリックして、graph_unit_tests ファイルのテスト関数だけを表示します。

  • [左][タイプ][関数]

  • [左][属性][テスト]

ツールストリップで [欠損リンクの強調表示] をクリックします。

missingLinksTRMX.png

[トレーサビリティ マトリクス] ウィンドウに、検証リンクがない 3 つの機能要件と 1 つのテスト要件が表示されます。

要件の検証リンクの作成

テスト要件 2.1.3 の Test for a graph that is a tree はテストにリンクされていません。ツリーのグラフでは、どの 2 つのノード間も 1 つの経路でのみ接続されています。

テスト ケース check_invalid_start_1 は、静的メソッド graph_straight_seq を使用して隣接行列を作成することでツリー グラフをテストします。 graph_straight_seq メソッドを使用してツリー グラフを表示します。

A = graph_unit_tests.graph_straight_seq;
G = graph(A);
plot(G,EdgeLabel=G.Edges.Weight)

前に生成したトレーサビリティ マトリクスを使用して、要件 Test for a graph that is a tree から check_invalid_start_1 テスト ケースへのリンクを作成します。

slreq.generateTraceabilityMatrix(mtxOpts)

要件とテストに対応するセルをクリックし、[作成] を選択します。[リンクの作成] ダイアログ ボックスで、[作成] をクリックします。

createTestLink.png

テスト要件にリンクされたテストを実行して、[要件エディター] の検証の状態を更新します。check_invalid_start_1 テストで要件 Test for a graph that is a tree が検証されます。

status3 = runTests(testReqs);
Running graph_unit_tests
.......... ....
Done graph_unit_tests
__________

さらに、次の 3 つの機能要件にテストへのリンクがありません。

  • 要件 2.2.1: Returns -9 for invalid adjacency matrices

  • 要件 2.2.2: Returns -19 if the start node is encoded incorrectly

  • 要件 2.2.3: Returns -29 if end node is encoded incorrectly

これらの要件にはトレーサビリティ ギャップがあります。これらの要件を検証するテストはないため、このギャップをテストへのリンクを作成して埋めることはできません。

カバレッジ ギャップとトレーサビリティ ギャップを修正するためのテストの作成

テストへのリンクがない 3 つの機能要件には、関数 shortest_path のコード行へのリンクがありません。カバレッジを使用してテストを実行し、関数 shortest_path のそれらのコード行がテストでカバーされているかどうかを判定します。

カバレッジを使用したテストの実行

RunTestsWithCoverage スクリプトを使用して、関数とステートメントのカバレッジを使用してテストを実行し、それらのカバレッジをレポートで確認します。詳細については、Generate Code Coverage Report in HTML Formatを参照してください。

RunTestsWithCoverage
Running graph_unit_tests
.......... ........
Done graph_unit_tests
__________

Code coverage report has been saved to:
 C:\Users\jdoe\MATLAB\Projects\examples\ShortestPath\coverageReport\index.html

カバレッジ レポートを開きます。20 行目、25 行目、および 30 行目にあるエラー コードのステートメントがテストでカバーされていません。

missingCoverage.png

それらのコード行のカバレッジ ギャップと要件 2.2.1、2.2.2、および 2.2.3 のトレーサビリティ ギャップが同じエラー コードを参照していることに注目してください。それらのコード行のテストを作成して要件へのリンクを作成すれば、カバレッジ ギャップとトレーサビリティ ギャップを同時に埋めることができます。

カバレッジの改善するための新しいテストの作成

テストのカバレッジを改善して要件 2.2.1、2.2.2、および 2.2.2 を検証するテストを作成します。graph_unit_tests テスト ファイルを開きます。

open("graph_unit_tests.m");

次の関数で 3 つのエラー コードをテストします。このコードをコピーして graph_unit_tests ファイルの 4 行目にあるテスト メソッドのセクションに貼り付け、ファイルを保存します。

function check_invalid_nonsquare(testCase)
    adjMatrix = zeros(2,3);
    startIdx = 1;
    endIdx = 1;
    expOut = -9;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'Graph is not square');
end

function check_invalid_entry(testCase)
    adjMatrix = 2*ones(4,4);
    startIdx = 1;
    endIdx = 1;
    expOut = -9;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'Adjacency matrix is not valid');
end

function check_invalid_noninteger_startnode(testCase)
    adjMatrix = zeros(4,4);
    startIdx = 1.2;
    endIdx = 1;
    expOut = -19;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'Start node is not an integer');
end

function check_invalid_noninteger_endnode(testCase)
    adjMatrix = zeros(4,4);
    startIdx = 1;
    endIdx = 2.2;
    expOut = -29;
    verify_path_length(testCase, adjMatrix, startIdx, endIdx, expOut, ...
        'End node is not an integer');
end

カバレッジを使用してテストを再度実行し、カバレッジ レポートを開きます。

RunTestsWithCoverage
Running graph_unit_tests
.......... ........
Done graph_unit_tests
__________

Code coverage report has been saved to:
 C:\Users\jdoe\MATLAB\Projects\examples\ShortestPath\coverageReport\index.html

今度はエラー コードのステートメントがテストでカバーされています。

improvedCoverage.png

ただし、97 行目にテストでカバーされないステートメントがあります。これは、97 行目のステートメントをテストでカバーすることを必要とする条件で 87 行目の return も実行されるためです。つまり、97 行目のステートメントには到達できず、デッド ロジックになります。

deadLogic.png

要件のトレーサビリティ ギャップの修正

トレーサビリティ マトリクスを再生成し、前と同じようにフィルターを適用してから、ツールストリップで [欠損リンクの強調表示] をクリックします。

slreq.generateTraceabilityMatrix(mtxOpts)
  • [上][リンク][欠損リンク]

  • [上][タイプ][機能要件]

  • [左][タイプ][関数]

  • [左][属性][テスト]

エラー コードの要件と新しいテストの間のリンクを作成します。

createLinksImproveCoverage.png

両方の要件セットにリンクされたテストを再実行して、[要件エディター] の検証の状態を更新します。

status4 = runTests(funcReqs);
Running graph_unit_tests
.......... ......
Done graph_unit_tests
__________
status5 = runTests(testReqs);
Running graph_unit_tests
.......... ....
Done graph_unit_tests
__________

すべての要件にテストへのリンクがあり、すべてのテストにパスします。

updatedVerificationStatus.png

生成されたコード内での要件のトレース

Embedded Coder® を使用して shortest_path アルゴリズムからコードを生成し、生成されたコード内で要件をトレースできるようにする要件コメントを含めます。詳細については、Requirements Traceability for Code Generated from MATLAB Codeを参照してください。

コード構成オブジェクトを作成し、LIB ビルド タイプを使用してコードを生成します。

cfg = coder.config("lib","ecoder",true);

コード コンフィギュレーション パラメーターを有効にして、生成されたコードに要件コメントを含めます。

cfg.ReqsInCode = true;

coder.typeof (MATLAB Coder)を使用して、最大サイズを 100 行 100 列とする可変サイズの double の配列と、生成されたコードで入力として使用する double のスカラーを定義します。

mtxType = coder.typeof(ones(100,100),[],1);
scalarDblType = coder.typeof(1);

指定したコード コンフィギュレーション パラメーターと入力型を使用して、shortest_path アルゴリズムから C コードを生成します。コード生成レポートを作成し、そのレポートを起動します。

codegen shortest_path -config cfg -args {mtxType, scalarDblType, scalarDblType} -launchreport
Code generation successful: View report

codegen-report-requirements-comments.png

shortest_path.c ファイルには、リンクされた要件、shortest_path.m ファイルの絶対ファイル パス、リンクされたコード行からなる概要が記載されたコメントが含まれています。

参考

| (MATLAB Coder) | (MATLAB Coder)

関連するトピック