ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

コマンド ライン検証のチュートリアル

この例では、Adjustable Rate Limiter の 3 つのテスト ケースを作成し、モデル カバレッジ ツールのコマンド ライン API を使用して、結果のモデル カバレッジを解析します。

Adjustable Rate Limiter の Simulink® モデル

Simulink® サブシステムの Adjustable Rate Limiter は、モデル 'slvnvdemo_ratelim_harness' 内の Rate Limiter です。これは、3 つの Switch ブロックを使用して、出力を制限するタイミングと、適用する制限のタイプを制御します。

入力は、From Workspace ブロック 'gain'、'rising limit' および 'falling limit' で生成され、これによって区分的線形信号が生成されます。入力の値は、MATLAB® ワークスペースで定義されている 6 つの変数 (t_gain、u_gain、t_pos、u_pos、t_neg および u_neg) で指定されます。

open_system('slvnvdemo_ratelim_harness');
open_system('slvnvdemo_ratelim_harness/Adjustable Rate Limiter');

最初のテスト ケースの作成

最初のテスト ケースは、入力値が急激に変化しないときは出力が入力と一致することを検証します。正弦波を時変信号として使用し、立ち上がりと立ち下がりの制限に定数を使用します。

t_gain = (0:0.02:2.0)';
u_gain = sin(2*pi*t_gain);

MATLAB 関数 diff を使用して、時変入力の最小変化と最大変化を計算します。

max_change = max(diff(u_gain))
min_change = min(diff(u_gain))
max_change =

    0.1253


min_change =

   -0.1253

信号の変化は 1 よりはるかに小さく -1 よりはるかに大きいため、変化率の制限を 1 と -1 に設定します。変数はすべて、シミュレーション前に読み込まれる MAT ファイル 'within_lim.mat' に保存されます。

t_pos = [0;2];
u_pos = [1;1];
t_neg = [0;2];
u_neg = [-1;-1];

save('within_lim.mat','t_gain','u_gain','t_pos','u_pos','t_neg','u_neg');

追加のテスト ケース

2 番目のテスト ケースでは、最初のケースに補足して、変化率の制限を超える立ち上がりゲインを使用します。直後に、変化率の制限を拡大し、ゲインの変化が制限未満になるようにします。

t_gain = [0;2];
u_gain = [0;4];
t_pos = [0;1;1;2];
u_pos = [1;1;5;5]*0.02;
t_neg = [0;2];
u_neg = [0;0];

save('rising_gain.mat','t_gain','u_gain','t_pos','u_pos','t_neg','u_neg');

3 番目のテスト ケースは 2 番目の鏡像で、立ち上がりゲインが立ち下がりゲインに置き換えられています。

t_gain = [0;2];
u_gain = [-0.02;-4.02];
t_pos = [0;2];
u_pos = [0;0];
t_neg = [0;1;1;2];
u_neg = [-1;-1;-5;-5]*0.02;

save('falling_gain.mat','t_gain','u_gain','t_pos','u_pos','t_neg','u_neg');

カバレッジ テストの定義

テスト ケースは、cvtest コマンドと cvsim コマンドを使用して編成され、実行されます。これらのコマンドは、Simulink のシミュレーションをプログラム実行する際に通常使用される sim コマンドに代わるものです。

cvtest コマンドは、テスト シミュレーションに関する情報を登録する際に使用します。次の 3 つの引数を取ります。

  • ルート計測サブシステムの絶対パス (またはモデル全体を計測するためのモデル名)

  • レポートで使用するラベル文字列

  • シミュレーションの開始直前にベース ワークスペースで評価されるセットアップ コマンド

testObj1 = cvtest('slvnvdemo_ratelim_harness/Adjustable Rate Limiter', ...
                  'Gain within slew limits', ...
                  'load(''within_lim.mat'');')
 testObj1 = ... cvtest
                  id: 307 (READ ONLY)
            modelcov: 306 (READ ONLY)
            rootPath: Adjustable Rate Limiter
               label: Gain within slew limits
            setupCmd: load('within_lim.mat');
            settings: [1x1 struct]
    modelRefSettings: [1x1 struct]
         emlSettings: [1x1 struct]
        sfcnSettings: [1x1 struct]
             options: [1x1 struct]
              filter: 

他のテスト オブジェクトも同様に用意されます。

testObj2 = cvtest('slvnvdemo_ratelim_harness/Adjustable Rate Limiter', ...
                  'Rising gain that temporarily exceeds slew limit', ...
                  'load(''rising_gain.mat'');')

testObj3 = cvtest('slvnvdemo_ratelim_harness/Adjustable Rate Limiter', ...
                  'Falling gain that temporarily exceeds slew limit', ...
                  'load(''falling_gain.mat'');')
 testObj2 = ... cvtest
                  id: 309 (READ ONLY)
            modelcov: 306 (READ ONLY)
            rootPath: Adjustable Rate Limiter
               label: Rising gain that temporarily exceeds slew limit
            setupCmd: load('rising_gain.mat');
            settings: [1x1 struct]
    modelRefSettings: [1x1 struct]
         emlSettings: [1x1 struct]
        sfcnSettings: [1x1 struct]
             options: [1x1 struct]
              filter: 

 testObj3 = ... cvtest
                  id: 311 (READ ONLY)
            modelcov: 306 (READ ONLY)
            rootPath: Adjustable Rate Limiter
               label: Falling gain that temporarily exceeds slew limit
            setupCmd: load('falling_gain.mat');
            settings: [1x1 struct]
    modelRefSettings: [1x1 struct]
         emlSettings: [1x1 struct]
        sfcnSettings: [1x1 struct]
             options: [1x1 struct]
              filter: 

カバレッジ テストの実行

cvsim コマンドを使用して、最初のテスト ケースのカバレッジ テスト オブジェクトを実行します。これにより、モデルのシミュレーションが開始されます。

cvsim コマンドの構文は、組み込みの sim コマンドと似ていますが、最初の入力と最初の出力の引数がそれぞれ cvtest オブジェクトと cvdata オブジェクトである点が異なります。シミュレーション結果は複数の戻り値を使用して取得されます。

[dataObj1,T,X,Y] = cvsim(testObj1,[0 2]);
dataObj1
dataObj1 = ... cvdata
                 id: 313
               type: TEST_DATA
               test: cvtest object
             rootID: 315
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 22-Dec-2016 12:33:25
           stopTime: 22-Dec-2016 12:33:25
  intervalStartTime: 0
   intervalStopTime: 0
simulationStartTime: 0
 simulationStopTime: 2
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

出力が入力と一致することをチェックすることにより、最初のテスト ケースを検証します。

subplot(211),plot(T,Y(:,1),T,Y(:,4)),xlabel('Time (sec)'),ylabel('Value'),
title('Gain input and output');
subplot(212),plot(T,Y(:,1)-Y(:,4)),xlabel('Time (sec)'),ylabel('Difference'),
title('Difference between the gain input and output');

同じ方法で 2 番目のテスト ケースを実行し、結果をプロットします。

制限された出力が入力から離れた場合は、最大スルー レートでのみ復元可能になります。このため、プロットには異常なねじれがあります。出力と入力が一致したら、2 つは同時に変化します。

[dataObj2,T,X,Y] = cvsim(testObj2,[0 2]);
dataObj2

subplot(211),plot(T,Y(:,1),T,Y(:,4)),xlabel('Time (sec)'),ylabel('Value'),
title('Gain input and output');
subplot(212),plot(T,Y(:,1)-Y(:,4)),xlabel('Time (sec)'),ylabel('Difference'),
title('Difference between the gain input and output');
dataObj2 = ... cvdata
                 id: 429
               type: TEST_DATA
               test: cvtest object
             rootID: 315
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 22-Dec-2016 12:33:26
           stopTime: 22-Dec-2016 12:33:26
  intervalStartTime: 0
   intervalStopTime: 0
simulationStartTime: 0
 simulationStopTime: 2
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

3 番目のテスト ケースを実行して結果をプロットします。

[dataObj3,T,X,Y] = cvsim(testObj3,[0 2]);
dataObj3

subplot(211), plot(T,Y(:,1),T,Y(:,4)), xlabel('Time (sec)'), ylabel('Value'),
title('Gain input and output');
subplot(212), plot(T,Y(:,1)-Y(:,4)), xlabel('Time (sec)'), ylabel('Difference'),
title('Difference between the gain input and output');
dataObj3 = ... cvdata
                 id: 535
               type: TEST_DATA
               test: cvtest object
             rootID: 315
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 22-Dec-2016 12:33:26
           stopTime: 22-Dec-2016 12:33:26
  intervalStartTime: 0
   intervalStopTime: 0
simulationStartTime: 0
 simulationStopTime: 2
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

カバレッジ レポートの生成

すべてのテストがパスしたと仮定して、すべてのテスト ケースを組み合わせたレポートを生成し、100% カバレッジの達成を検証します。各テストのカバレッジ率は、[モデルの階層構造] という見出しの下に表示されます。どのテストも単独では 100% カバレッジを達成していませんが、累計ではフル カバレッジを達成しています。

cvhtml('combined_ratelim',dataObj1,dataObj2,dataObj3);

カバレッジ データの保存

cvsave コマンドを使用してテストの設定およびカバレッジの結果をテキスト ファイル "ratelim_testdata.cvt" に保存し、後から解析できるようにします。

cvsave('ratelim_testdata','slvnvdemo_ratelim_harness');

モデルを閉じてカバレッジ環境を終了します。

close_system('slvnvdemo_ratelim_harness',0);
clear dataObj*
clear testObj*

カバレッジ データの読み込み

モデルを開いた後にcvload コマンドを使用して、保存したカバレッジ テストをファイル "ratelim_testdata.cvt" から復元します。データおよびテストは cell 配列で取得されます。

open_system('slvnvdemo_ratelim_harness');
[SavedTests,SavedData] = cvload('ratelim_testdata')
SavedTests =

  1×3 cell array

    [1×1 cvtest]    [1×1 cvtest]    [1×1 cvtest]


SavedData =

  1×3 cell array

    [1×1 cvdata]    [1×1 cvdata]    [1×1 cvdata]

カバレッジ データ オブジェクトの操作

オーバーロードされた演算子、+、- および * を使用して cvdata オブジェクトを操作します。* 演算子は、2 つのカバレッジ データ オブジェクトの共通部分を見つけるために使用します。これにより、もう 1 つの cvdata オブジェクトが生成されます。たとえば、次のコマンドを実行すると、3 つすべてのテストの共通カバレッジの HTML レポートが生成されます。

common = SavedData{1} * SavedData{2} * SavedData{3}
cvhtml('intersection',common)
common = ... cvdata
                 id: 0
               type: DERIVED_DATA
               test: []
             rootID: 644
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 22-Dec-2016 12:33:25
           stopTime: 22-Dec-2016 12:33:26
  intervalStartTime: 0
   intervalStopTime: 0
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

カバレッジ データ オブジェクトからの情報の抽出

生のドキュメント化されていない形式のカバレッジ情報が必要になる場合があります。単一のテストから生の数値を直接参照するには、cvdata オブジェクトを使用します。

common.metrics.decision
ans =

     1
     0
     1
     0
     1
     0
     0
    35
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0

decisioninfo コマンドは、ブロック パスまたはブロック ハンドルからカバレッジ情報を取得します。出力は、単一のモデル オブジェクトの達成された結果と全体の結果を含むベクトルです。

cov = decisioninfo(SavedData{1} + SavedData{2} + SavedData{3}, ...
                   'slvnvdemo_ratelim_harness/Adjustable Rate Limiter')
cov =

     6     6

この取得したカバレッジ情報を使用して、次のようにカバレッジのパーセンテージにアクセスします。

percentCov = 100 * (cov(1)/cov(2))
percentCov =

   100

2 つの出力引数が使用されている場合、decisioninfo コマンドは、Simulink ブロックまたは Stateflow® オブジェクト内で判定と結果をキャプチャする構造体を返します。

[blockCov,desc] = decisioninfo(common, ...
         'slvnvdemo_ratelim_harness/Adjustable Rate Limiter/Delta sign')
descDecision = desc.decision
outcome1 = desc.decision.outcome(1)
outcome2 = desc.decision.outcome(2)
blockCov =

     0     2


desc = 

  struct with fields:

           isFiltered: 0
    justifiedCoverage: 0
          isJustified: 0
      filterRationale: ''
             decision: [1×1 struct]


descDecision = 

  struct with fields:

               text: 'Switch trigger'
    filterRationale: ''
         isFiltered: 0
        isJustified: 0
            outcome: [1×2 struct]


outcome1 = 

  struct with fields:

               text: 'false (out = in3)'
     executionCount: 0
         isFiltered: 0
        isJustified: 0
    filterRationale: ''


outcome2 = 

  struct with fields:

               text: 'true (out = in1)'
     executionCount: 0
         isFiltered: 0
        isJustified: 0
    filterRationale: ''

モデル例を閉じます。

close_system('slvnvdemo_ratelim_harness',0);