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