Main Content

Write and Run Tests that Inject Faults by Using the Simulink Test Manager

Since R2024a

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:

  1. Open the Simulink Test app. In the Apps tab, click Simulink Test.

  2. Open the Simulink Test Manager. In the Tests tab, click Simulink Test Manager.

  3. Create a new test case or load an existing test case.

  4. 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.

An example fault set with faults. The picture shows a fault set named Fault Set 1 with four faults on an example model. Each fault has a timed 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:

  1. Retrieve or create the sltest.testmanager.TestCase (Simulink Test) object. See, createTestCase (Simulink Test), getTestCases (Simulink Test), and getTestCaseByName (Simulink Test).

  2. Add a fault set to the test case by using the addFaultSet method. This method creates an instance of the sltest.testmanager.FaultSet class.

  3. Update the available faults by using the sltest.testmanager.refreshFaults function on the model under test.

  4. Add faults to the fault set by using the addSpecifiedFault method. This method creates an instance of the sltest.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.

The starting Fault Table pane. The model has four faults. Each fault is on a different model element.

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.

The test manager shows four tests. Each test corresponds to a unique fault combination of active faults for testing. The test name indicates the fault that is injected.

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.

The Fault Settings section for the test case that injects the throttle_fault fault. The fault set is expanded and contains four faults. The fault labeled throttle_fault is selected, and the others are not.

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.

The temporal assessment for the test case that injects the throttle_fault fault. The assessment has two symbols, and a trigger response assessment. The assessment is expanded.

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.

The test results. The test suite is expanded. The results show that each test passed.

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.

The visualized results of the test that injects throttle_fault. The plot also shows the normal_operation status. throttle_fault is a dark yellow, and normal_operation is purple. Both throttle_fault and normal_operation change their status at 5 seconds.

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)

Related Topics