%% Requirements-Based Testing for Model Development
%
% Test an autopilot subsystem against requirements.

% Copyright 2018 The MathWorks, Inc.

%%
% This example demonstrates testing a subsystem against a requirement,
% using the test manager, test harness, Test Sequence block, and Test
% Assessment block. The requirements document links to the test case and
% test harness, and |verify| statements assess the component under test.
%
% As you build your model, you can add test cases to verify the model
% against requirements. Subsequent users can run the same test cases, then
% add test cases to accomplish further verification goals such as achieving
% 100% coverage or verifying generated code.
%
% This example tests the |Roll Reference| subsystem against a
% requirement using three scenarios. A Test Sequence block provides inputs,
% and a Test Assessment block evaluates the component. The |Roll Reference|
% subsystem is one component of an autopilot control
% system. |Roll Reference| controls the reference angle of the aircraft's
% roll control system. The subsystem fails one
% assessment, prompting a design change that limits the subsystem output at
% high input angles.

%% Paths and Example Files
% 
% Enter the following to store paths and file names for the example:
%
filePath = fullfile(matlabroot,'toolbox','simulinktest','simulinktestdemos');
topModel = 'TestAndVerificationAutopilotExample';
rollModel = 'RollAutopilotMdlRef';
testHarness = 'RollReference_Requirement1_3';
testFile = 'AutopilotTestFile.mldatx';

%% Open the Test File and Model
%
% Open the test file in the Test Manager. You can also open the Test
% Manager by selecting *Analysis > Test Manager* from the Simulink menu.
%
tf = sltest.testmanager.load(fullfile(filePath,testFile));
sltest.testmanager.view;

%% 
%
% Open the |RollAutopilotMdlRef| model.
%
open_system(fullfile(filePath,rollModel));

%% View Test and Model Requirements
%
% In the lower right corner of the canvas, click the icon and 
% select the Requirements tile. The Requirements perspective 
% shows requirements associated
% with the model. You can view model items or test cases
% that implement or verify a requirement by clicking the links.

%%
% <<reqentries.png>>

%%
% In the test case, expand the *Requirements* section to view links to the
% requirement set.

%%
% <<reqlink.png>>

%% Test Inputs
%
% The test creates three scenarios to test normal conditions and
% exceptions in the Roll Hold Reference requirements. The test vectors are
% authored in the Test Sequence block.

%%
% Open the Test Sequence block.
%
sltest.harness.load([rollModel '/Roll Reference'],testHarness)
open_system('RollReference_Requirement1_3/Test Sequence')

%%
% For each scenario, the test sequence sets a signal level, then engages the
% autopilot. The test sequence checks that |PhiRef| is stable for a minimum
% time |DurationLimit| before it transitions to the next signal level. For
% the first two
% scenarios, the test sequence sets the |EndTest| local variable to |1|,
% triggering the transition to the next scenario.

%%
% <<AutopilotTestSeqReq1-3.png>>

%% Test Assessments
% Open the Test Assessment block.
%
open_system('RollReference_Requirement1_3/Test Assessment')

%%
% <<AutopilotTestAssessReq1-3.png>>

%%
%
% The Test Assessment block evaluates |Roll
% Reference|. The assessment block is a library linked subsystem, which
% facilitates test assessment reuse between multiple test harnesses. The
% block contains |verify| statements corresponding to:
%
% * The requirement that |PhiRef| = |Phi| when |Phi| operates inside the low and
% high limits.
% * The requirement that |PhiRef = 0| when |Phi < 6| degrees.
% * The requirement that |PhiRef = 30| when |Phi > 30| degrees.
% * The requirement that when |TurnKnob| is engaged, |PhiRef = TurnKnob| if 
% |TurnKnob >= 3| degrees.
% 

%% Run the Test
%
% In the Test Manager toolstrip, click *Run*.
%
% The simulation returns |verify| statement results and simulation output in
% the Test Manager. The |verify_high_pos| statement fails.
%
% # Click *Results and Artifacts* in the test manager.
% # In the results tree, expand *Verify Statements*. Click *Simulink:
% verify_high_pos*. The trace shows when the statement fails.

%%
%
% <<rollref_req_testing_verify_fail.png>>

%%
% # In the *Data Inspector* tab, click *Subplots* and select two plots
% arranged vertically. Select the lower plot in the *Visualize* pane.
% # In the results tree, expand *Results*, *Requirement 1.3
% Test*, and *Sim Output*.
% # Select |PhiRef| and |Phi|. The output traces align with the |verify|
% results in the above plot. Observe that |PhiRef| exceeds 30 degrees
% when |Phi| exceeds 30 degrees.

%%
% <<rollref_req_testing_output.png>>

%% 
%
% Update |RollReference| to limit the |PhiRef| signal:
%%
% # Add a Saturation block as shown. 
% # Set the lower limit to |-30| and the upper limit to |30|.
% # Link the block to its requirement. From the Requirements browser, drag
% requirement 1.1.2 to the Saturation block. An icon appears on the block,
% and the requirement is highlighted.

%%
% <<autopilotHighLimitAdd.png>>

%%
% Run the test again. The |verify| statement passes,
% and the output in the test manager shows that |PhiRef| does not exceed 30
% degrees.

%%
% <<rollref_req_testing_output_revised.png>>

%%
%

close_system(rollModel,0);
close_system(topModel,0);
close_system('RollRefAssessLib',0);
sltest.testmanager.clear;
sltest.testmanager.clearResults;
sltest.testmanager.close;
clear filePath topModel reqDoc rollModel testHarness testFile
displayEndOfDemoMessage(mfilename)
