Пример по верификации командной строки

Этот пример создает три теста для ограничителя регулируемой процентной ставки и анализирует получившееся покрытие модели с помощью API командной строки Инструмента model coverage.

Модель Simulink® для ограничителя регулируемой процентной ставки

Ограничитель Регулируемой процентной ставки подсистемы Simulink® является ограничителем уровня в модели 'slvnvdemo_ratelim_harness'. Это использует три блока switch, чтобы управлять, когда вывод должен быть ограничен и тип предела, чтобы применяться.

Входные параметры производятся с Из блоков Рабочей области 'усиление', 'возрастающий предел', и 'падающий предел', которые генерируют кусочные линейные сигналы. Значения входных параметров заданы с шестью переменными, заданными в рабочей области MATLAB®: 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);

Вычислите минимальное и максимальное изменение входа варьирования времени с помощью функции diff MATLAB.

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');

Дополнительные тесты

Второй тест дополняет первый случай возрастающим усилением, которое превышает ограничение скорости. После секунды это увеличивает ограничение скорости так, чтобы изменения усиления были ниже того предела.

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');

Третий тест является зеркальным отображением второго с возрастающим усилением, замененным падающим усилением.

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');

Определение тестов покрытия

Тесты организованы и выполнили использование команды cvsim и cvtest. Эти команды заменяют команду sim, которая обычно используется, чтобы программно выполнить симуляции Simulink.

Команда cvtest используется, чтобы указать информацию о тестовой симуляции. Требуются следующие три аргумента:

  • полный путь к корневой подсистеме инструментирования (или только имя модели, чтобы оснастить целую модель)

  • строка метки используется в создании отчетов

  • команда настройки, которая оценена в базовом рабочем пространстве только до запуска симуляции.

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');

Выполните и постройте результаты для второго теста таким же образом.

Заметьте, что, если ограниченный вывод отличался от входа, который он может только восстановить на максимальной скорости просмотра. Поэтому график имеет необычную петлю. Однажды соответствие ввода и вывода, эти два изменяются вместе.

[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

Выполните и постройте результаты для третьего теста.

[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" после открытия модели. Данные и тесты получены в массиве ячеек.

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. Оператор * используется, чтобы найти пересечение двух объектов данных покрытия, которое приводит к другому объекту cvdata. Например, следующая команда производит отчет 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 получает информацию о покрытии из блока path или указателя блока. Вывод является вектором с достигнутыми и общими результатами для одного объекта модели.

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

Когда два выходных аргумента используются, команда decisioninfo возвращает структуру, которая получает решения и результаты в объекте Stateflow® или блоке Simulink.

[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);