Create Advanced Custom Fixture
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 a
Format 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 the
addTeardown method within the
setup 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 and
TeardownDescription 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 your
Fixture 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. Two
NumericFormatFixture 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 the
NumericFormatFixture 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.
runtests("ExampleTest");Running ExampleTest . Done ExampleTest __________
Apply Custom Fixture as Shared Fixture
In your current folder, create three test classes that each use an instance of
NumericFormatFixture 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, the
TestC class is assigned a fixture that enforces a different
numeric format. According to the implementation of the
isCompatible 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 from
TestA to TestB because both classes require
the same environment. However, when switching from TestB to
TestC, 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