Create Advanced Custom Fixture - MATLAB & Simulink (original) (raw)

This example shows how to create a custom fixture that changes the output display format for numeric values. You can apply the fixture to a single test class or share the fixture across multiple test classes. After testing, the fixture restores the display format to its original state.

Create NumericFormatFixture Class

In a file named NumericFormatFixture.m in your current folder, create the NumericFormatFixture class by deriving from the matlab.unittest.fixtures.Fixture interface. Because you want to pass the fixture a numeric format, add aFormat property to your class.

properties (SetAccess=immutable)
    Format (1,1) string
end

Add Fixture Constructor

In a methods block in your class, define a constructor that sets the Format property.

methods
    function fixture = NumericFormatFixture(fmt)
        fixture.Format = fmt;
    end
end

Implement setup Method

Subclasses of the Fixture interface must implement the setup method, which makes changes to the environment when the testing framework sets up the fixture. To restore the environment when the framework tears down the fixture, you can call theaddTeardown method within thesetup method.

In a methods block, implement the setup method to change the numeric format to the format specified during fixture construction and to restore the format to its original state after testing. To provide descriptive information when the framework sets up and tear downs the fixture, set the SetupDescription andTeardownDescription properties within the method.

methods
    function setup(fixture)
        originalFormat = format;
        fixture.addTeardown(@format,originalFormat)
        format(fixture.Format)
        fixture.SetupDescription = "Set the numeric format to " + ...
            fixture.Format + ".";
        fixture.TeardownDescription =  ...
            "Restored the numeric format to " + ...
            originalFormat.NumericFormat + ".";
    end
end

Implement isCompatible Method

Implement the isCompatible method in yourFixture subclass if the fixture is configurable (for instance, if its class constructor accepts input arguments). In this example, because you set the Format property using the class constructor, you must implement isCompatible.

The testing framework calls isCompatible to determine whether instances of the same Fixture subclass correspond to the same shared test fixture state. The information about fixture compatibility helps the framework decide when to perform teardown and setup actions. TwoNumericFormatFixture instances make the same change to the environment when their Format properties are equal. Specify this compatibility definition by implementing the isCompatible method in a methods block with protected access.

methods (Access=protected)
    function tf = isCompatible(fixture1,fixture2)
        tf = fixture1.Format == fixture2.Format;
    end
end

Fixture Class Definition

This code provides the complete contents of theNumericFormatFixture class.

classdef NumericFormatFixture < matlab.unittest.fixtures.Fixture properties (SetAccess=immutable) Format (1,1) string end

methods
    function fixture = NumericFormatFixture(fmt)
        fixture.Format = fmt;
    end

    function setup(fixture)
        originalFormat = format;
        fixture.addTeardown(@format,originalFormat)
        format(fixture.Format)
        fixture.SetupDescription = "Set the numeric format to " + ...
            fixture.Format + ".";
        fixture.TeardownDescription =  ...
            "Restored the numeric format to " + ...
            originalFormat.NumericFormat + ".";
    end
end

methods (Access=protected)
    function tf = isCompatible(fixture1,fixture2)
        tf = fixture1.Format == fixture2.Format;
    end
end

end

Apply Custom Fixture to Single Test Class

In a file named ExampleTest.m in your current folder, create the ExampleTest class that applies the custom fixture and verifies that a numeric value is displayed in the expected format. To simplify this example, the actual value is produced by a call to the formattedDisplayText function. In practice, you test user-defined code.

classdef ExampleTest < matlab.unittest.TestCase methods (Test) function formatTest(testCase) testCase.applyFixture(NumericFormatFixture("bank")) actual = strtrim(formattedDisplayText(pi)); expected = "3.14"; testCase.verifyEqual(actual,expected) end end end

Run the ExampleTest class. The testing framework sets up the fixture, which changes the display format to the currency format. Once the test run is complete, the framework tears down the fixture, which restores the original display format. In this example, the test passes.

Running ExampleTest . Done ExampleTest


Apply Custom Fixture as Shared Fixture

In your current folder, create three test classes that each use an instance ofNumericFormatFixture as a shared test fixture.

In a file named TestA.m, create the TestA class.

classdef (SharedTestFixtures={NumericFormatFixture("bank")}) ... TestA < matlab.unittest.TestCase methods (Test) function formatTest(testCase) actual = strtrim(formattedDisplayText(pi)); expected = "3.14"; testCase.verifyEqual(actual,expected) end end end

In a file named TestB.m, create the TestB class.

classdef (SharedTestFixtures={NumericFormatFixture("bank")}) ... TestB < matlab.unittest.TestCase methods (Test) function formatTest(testCase) actual = strtrim(formattedDisplayText(100/3)); expected = "33.33"; testCase.verifyEqual(actual,expected) end end end

In a file named TestC.m, create the TestC class.

classdef (SharedTestFixtures={NumericFormatFixture("hex")}) ... TestC < matlab.unittest.TestCase methods (Test) function formatTest(testCase) actual = strtrim(formattedDisplayText(1)); expected = "3ff0000000000000"; testCase.verifyEqual(actual,expected) end end end

The TestA and TestB classes are assigned shared fixtures that make the same change to the environment. On the other hand, theTestC class is assigned a fixture that enforces a different numeric format. According to the implementation of theisCompatible method in this example, the testing framework finds the fixtures on TestA and TestB compatible. However, it finds the fixture on TestC incompatible with the other fixtures.

The information about fixture compatibility helps the framework decide when to perform teardown and setup actions. If you run TestA,TestB, and TestC as part of the same test suite, the framework does not tear down the fixture when switching fromTestA to TestB because both classes require the same environment. However, when switching from TestB toTestC, the framework tears down the existing fixture and sets up a fresh fixture required by TestC. In this example, all the tests pass.

runtests(["TestA" "TestB" "TestC"]);

Setting up NumericFormatFixture Done setting up NumericFormatFixture: Set the numeric format to bank.


Running TestA . Done TestA


Running TestB . Done TestB


Tearing down NumericFormatFixture Done tearing down NumericFormatFixture: Restored the numeric format to short.


Setting up NumericFormatFixture Done setting up NumericFormatFixture: Set the numeric format to hex.


Running TestC . Done TestC


Tearing down NumericFormatFixture Done tearing down NumericFormatFixture: Restored the numeric format to short.


Alternative Approach to Calling addTeardown in setup Method

An alternative approach to calling the addTeardown method within the setup method is to implement a separate teardown method. This code shows how to recreate the NumericFormatFixture class by implementing both the setup and teardown methods. Note that the alternative class definition contains an additional property,OriginalFormat, to pass information about the original format to the teardown method.

classdef NumericFormatFixture < matlab.unittest.fixtures.Fixture properties (SetAccess=immutable) Format (1,1) string end

properties (Access=private)
    OriginalFormat
end

methods
    function fixture = NumericFormatFixture(fmt)  
        fixture.Format = fmt;
    end

    function setup(fixture)
        fixture.OriginalFormat = format().NumericFormat;
        format(fixture.Format)
        fixture.SetupDescription = "Set the numeric format to " + ...
            fixture.Format + ".";
    end

    function teardown(fixture)
        format(fixture.OriginalFormat)
        fixture.TeardownDescription =  ...
            "Restored the numeric format to " + ...
            fixture.OriginalFormat + ".";
    end
end

methods (Access=protected)
    function tf = isCompatible(fixture1,fixture2)
        tf = fixture1.Format == fixture2.Format;
    end
end

end

See Also

matlab.unittest.fixtures.Fixture | matlab.unittest.TestCase | format

Topics