Write and Run Tests that Inject Faults by Using the Simulink Test Manager
If you have Simulink® Test™, you can add faults to test cases and inject them into your models by creating fault sets. In each test case, the fault set specifies the active faults for that test. For more information on how to add faults to models, see Define and Model Faults. You can create multiple test cases with different combinations of active faults in a test suite to simulate multiple combinations. After you inject faults, you can assess the signals to determine if the faults caused the desired outputs by using temporal assessments. For more information on how to create basic tests in Simulink Test, see Create a Simple Baseline Test (Simulink Test).
Create Fault Sets in the Simulink Test Manager
To create a fault set in a test case:
Open the Simulink Test app. In the Apps tab, click Simulink Test.
Open the Simulink Test Manager. In the Tests tab, click Simulink Test Manager.
Create a new test case or load an existing test case.
Expand the Fault Settings section and click Add > Add Fault Set.
The new fault set is empty. To add faults, select the fault set and click Add > Add Fault. If you add faults to your model after you add the fault set, click Refresh to update the faults that the Simulink Test Manager identifies from your model. You can add more than one fault as long as each fault is on a different model element. Click OK. The fault set displays each fault name, their assigned model element, and their trigger.
Select a fault to simulate it. To specify additional fault combinations, create a new fault set and select different faults. You can select one fault set for each simulation in a test.
When you run the test, the test overrides the activation status of the faults assigned to the model. If you do not select a fault set, the test runs the simulation by using the fault settings specified in the model. To run a test without faults, select the fault set and clear the faults.
If you want to run more than one combination of faults in a test, create a test iteration. See Test Iterations (Simulink Test). If you want to adjust additional fault properties in each test, create a callback. See Callbacks (Simulink Test).
After simulating, you can view the fault simulation results in the embedded Simulation Data Inspector.
Programmatically Create Fault Sets
You can also create and modify fault sets programmatically. The model that you test must already have faults. For more information on creating faults in models programmatically, see Add and Configure Faults Programmatically.
To add a fault set programmatically:
Retrieve or create the
sltest.testmanager.TestCase
(Simulink Test) object. See,createTestCase
(Simulink Test),getTestCases
(Simulink Test), andgetTestCaseByName
(Simulink Test).Add a fault set to the test case by using the
addFaultSet
method. This method creates an instance of thesltest.testmanager.FaultSet
class.Update the available faults by using the
sltest.testmanager.refreshFaults
function on the model under test.Add faults to the fault set by using the
addSpecifiedFault
method. This method creates an instance of thesltest.testmanager.SpecifiedFault
class.
If you already have fault sets in a test case, you can retrieve the sltest.testmanager.FaultSet
class instance by using
the getFaultSets
method on the
sltest.testmanager.TestCase
class instance. Similarly, retrieve the
sltest.testmanager.SpecifiedFault
from a fault set by
using the getSpecifiedFaults
method on the
sltest.testmanager.FaultSet
class instance.
To remove fault sets and faults, use the remove
method on the fault
set or fault.
Run Fault Injection Tests on an Example Model
This example shows how to run tests that activate and inject faults by using fault sets. After you inject faults, you can assess the signals and determine if the faults caused the desired outputs by using temporal assessments.
Open the Model
Open the sldemo_fuelsys_fault_analyzer
model and set up the faults by using the fuelSysFaultTestSetup
helper function. The helper function deletes the existing Simulink® Fault Analyzer™ model artifacts and replaces them with the faults used in the example.
mdlName = "sldemo_fuelsys_fault_analyzer";
open_system(mdlName)
fuelSysFaultTestSetup
To view the code that sets up the faults, open the fuelSysFaultTestSetup
MATLAB® file or go to the Helper Function section.
The model represents a fuel control system for a gasoline engine, and is a modified version of the model in Model Fault-Tolerant Fuel Control System. The model produces a fuel mode signal after detecting faults in the controller. When the controller detects a single fault, the controller changes the fuel_mode
signal from LOW
, which represents low emissions, to RICH
, which represents a rich mixture. When the controller detects a second fault, it sets fuel_mode
to DISABLED
. When the controller detects a fault, the model logs this behavior by setting the normal_operation
signal to false
.
The model contains four faults. To view the faults, open the Fault Table pane. In the Apps tab, click Fault Analyzer. In the Fault Analyzer tab, in the View section, click Fault Table. Expand each model element to view the faults. Each fault uses a timed trigger, where the fault is injected at the specified simulation time.
View the Tests
Each fault causes the normal_operation
signal to output false
after the fault is injected. In this example, you run tests to verify this behavior. Open the Simulink Test Manager and load the fault_tests_example.mldatx
test file. In the Apps tab, click Simulink Test. In the Tests tab, click Simulink Test Manager. In the Simulink Test Manager, open the fault_tests_example.mldatx
test file. Alternatively, enter this command:
tf = sltest.testmanager.load("fault_tests_example.mldatx");
sltest.testmanager.view;
The test file has four test cases.
Each test case activates a fault by specifying a fault set with one selected fault. To view the fault set, in the Simulink Test Manager, in the left pane, click Test Browser. Expand the test file and the test suite, and select a test. Expand the Fault Settings section to view the fault set and the faults. This image shows the fault set for the test case that injects the throttle_fault
fault.
To verify that the fault produces the desired behavior, each test case includes a temporal assessment. See Assess Temporal Logic by Using Temporal Assessments (Simulink Test). In a test, expand the Logical and Temporal Assessments section. The assessment checks when the faulted signal equals the injected value. If the signal value equals the injected value from the fault, then the normal_operation
signal must be false
. This image shows the temporal assessment for the test case that injects the throttle_fault
fault.
Run the Tests
Run the tests. Select Fault Injection Test Suite and click Run, or enter this command:
run(tf);
Select Results and Artifacts, then expand the results. Each test case passes, which means the controller detects when each fault is injected.
You can view the fault trigger status of the active faults of a test in the embedded Simulation Data Inspector in the Simulink Test Manager. Expand a test result, expand Sim Output, and select the name of the fault to view the trigger status. This image shows the fault trigger and the normal_operation
status in the test that activated throttle_fault
.
Helper Function
The fuelSysFaultTestSetup
function adds the faults to the model, and adds fault sets and faults to the test cases. To see the example code that creates the fault sets, adds the faults, and enables the faults, see the Create Fault Sets and Add Faults in Test Cases
section.
function fuelSysFaultTestSetup %% Initializing mdl = "sldemo_fuelsys_fault_analyzer"; bmdl = mdl + "_FaultModel"; load_system(mdl); fault = Simulink.fault.Fault.empty(0,4); ports = 4; Simulink.fault.save(mdl) % Load the test file, and get the test suite and test cases. tf = sltest.testmanager.load("fault_tests_example.mldatx"); ts = getTestSuites(tf); tc = getTestCases(ts); %% Deleting existing faults, conditionals, and tests for n = 1:numel(tc) initialFaultSets = getFaultSets(tc(n)); if numel(initialFaultSets) > 0 for m = 1:numel(initialFaultSets) remove(initialFaultSets(m)) end end end existingFaults = Simulink.fault.findFaults(mdl); if numel(existingFaults) > 0 warnID = "safetyanalyzer:faultinfo:DeletedEmptyFaultModelWarning"; warning("off",warnID) for n = 1:numel(existingFaults) Simulink.fault.deleteFault(existingFaults(n).ModelElement,... existingFaults(n).Name) end warning("on",warnID) end sltest.testmanager.refreshFaults(mdl) Simulink.fault.deleteConditional(mdl) Simulink.fault.addConditional(mdl,"SampleConditional","x == true"); %% Adding faults and behaviors for n = 1:ports fault(n) = Simulink.fault.addFault(mdl ... + "/To Controller/Inport/" + num2str(n)); end % Add behavior to each fault. Three of the faults use stuck-at-ground % behavior and one of them uses stuck-at-constant behavior. addBehavior(fault(1),bmdl,... FaultBehavior="mwfaultlib/Stuck-at-Ground"); addBehavior(fault(2),bmdl,... FaultBehavior="mwfaultlib/Stuck-at-Ground"); addBehavior(fault(3),bmdl,... FaultBehavior="mwfaultlib/Stuck-at-Constant"); addBehavior(fault(4),bmdl,... FaultBehavior="mwfaultlib/Stuck-at-Ground"); load_system(bmdl) set_param(bmdl+"/ego_fault/Constant",Value="12") %% Specify Fault Properties % Define the trigger types. Each fault uses a timed trigger % at a different time. fault(1).TriggerType = "Timed"; fault(1).StartTime = 5; fault(2).TriggerType = "Timed"; fault(2).StartTime = 10; fault(3).TriggerType = "Timed"; fault(3).StartTime = 15; fault(4).TriggerType = "Timed"; fault(4).StartTime = 20; % Disable the faults. Simulink.fault.enable(mdl + "/To Controller/Inport/1",0) Simulink.fault.enable(mdl + "/To Controller/Inport/2",0) Simulink.fault.enable(mdl + "/To Controller/Inport/3",0) Simulink.fault.enable(mdl + "/To Controller/Inport/4",0) save_system(bmdl); Simulink.fault.save(mdl) %% Create Fault Sets and Add Faults in Test Cases % Update the available faults to include the faults in the model % that you can select for the fault set. sltest.testmanager.refreshFaults(mdl) % Create the fault sets and add the faults to each fault set. % Activate only one fault for each fault set, and disable the others. faultSets = sltest.testmanager.FaultSet.empty(0,ports); testedFaults = sltest.testmanager.SpecifiedFault.empty(0,ports); for i = 1:ports faultSets(i) = addFaultSet(tc(i),Name="Fault Set"); for m = 1:ports testedFaults(m) = addSpecifiedFault(faultSets(i),... "sldemo_fuelsys_fault_analyzer/To Controller/Inport/" ... + num2str(m),fault(m).Name); if m == i testedFaults(m).IsActive = true; else testedFaults(m).IsActive = false; end end end end
See Also
Simulink Test Manager (Simulink Test)