Create Advanced Custom Fixture
This example shows how to create a custom fixture that sets an
environment variable. Prior to testing, this fixture will save the current
UserName
variable.
Create UserNameEnvironmentVariableFixture Class Definition
In a file in your working folder, create a new class,
UserNameEnvironmentVariableFixture
that inherits from the
matlab.unittest.fixtures.Fixture
class. Since you want to
pass the fixture a user name, create a UserName
property to
pass the data between methods.
properties (SetAccess = private) UserName end
Define Fixture Constructor
In the methods
block of the
UserNameEnvironmentVariableFixture.m
file, create a
constructor method that validates the input and defines the
SetupDescription
. Have the constructor accept a character
vector and set the fixture’s UserName
property.
methods function fixture = UserNameEnvironmentVariableFixture(name) validateattributes(name, {'char'}, {'row'}, '','UserName') fixture.UserName = name; fixture.SetupDescription = sprintf( ... 'Set the UserName environment variable to "%s".',... fixture.UserName); end end
Implement setup Method
Subclasses of the Fixture
class must implement the
setup
method. Use this method to save the original
UserName
variable. This method also defines the
TeardownDescription
and registers the teardown task of
setting the UserName
to the original state after
testing.
Define the setup
method within the
methods
block of the
UserNameEnvironmentVariableFixture.m
file.
methods function setup(fixture) originalUserName = getenv('UserName'); fixture.assertNotEmpty(originalUserName, ... 'An existing UserName environment variable must be defined.') fixture.addTeardown(@setenv, 'UserName', originalUserName) fixture.TeardownDescription = sprintf(... 'Restored the UserName environment variable to "%s".',... originalUserName); setenv('UserName', fixture.UserName) end end
Implement isCompatible Method
Classes that derive from Fixture
must implement the
isCompatible
method if the constructor is configurable.
Since you can configure the UserName
property through the
constructor, UserNameEnvironmentVariableFixture
must
implement isCompatible
.
The isCompatible
method is called with two instances of the
same class. In this case, it is called with two instances of
UserNameEnvironmentVariableFixture
. The testing framework
considers the two instances compatible if their UserName
properties are equal.
In a new methods
block within
UserNameEnvironmentVariableFixture.m
, define an
isCompatible
method which returns logical
1
(true
) or logical
0
(false
).
methods (Access = protected) function bool = isCompatible(fixture, other) bool = strcmp(fixture.UserName, other.UserName); end end
Fixture Class Definition Summary
Below are the complete contents of
UserNameEnvironmentVariableFixture.m
.
classdef UserNameEnvironmentVariableFixture < ... matlab.unittest.fixtures.Fixture properties (SetAccess = private) UserName end methods function fixture = UserNameEnvironmentVariableFixture(name) validateattributes(name, {'char'}, {'row'}, '','UserName') fixture.UserName = name; fixture.SetupDescription = sprintf( ... 'Set the UserName environment variable to "%s".',... fixture.UserName); end function setup(fixture) originalUserName = getenv('UserName'); fixture.assertNotEmpty(originalUserName, ... 'An existing UserName environment variable must be defined.') fixture.addTeardown(@setenv, 'UserName', originalUserName) fixture.TeardownDescription = sprintf(... 'Restored the UserName environment variable to "%s".',... originalUserName); setenv('UserName', fixture.UserName) end end methods (Access = protected) function bool = isCompatible(fixture, other) bool = strcmp(fixture.UserName, other.UserName); end end end
Apply Custom Fixture to Single Test Class
In a file in your working folder, create the following test class,
ExampleTest.m
.
classdef ExampleTest < matlab.unittest.TestCase methods(TestMethodSetup) function mySetup(testCase) testCase.applyFixture(... UserNameEnvironmentVariableFixture('David')); end end methods (Test) function t1(~) fprintf(1, 'Current UserName: "%s"', getenv('UserName')) end end end
This test uses the UserNameEnvironmentVariableFixture
for
each test in the ExampleTest
class.
At the command prompt, run the test.
run(ExampleTest);
Running ExampleTest Current UserName: "David". Done ExampleTest __________
Apply Custom Fixture as Shared Fixture
In your working folder, create three test classes using a shared fixture.
Using a shared fixture allows the
UserNameEnvironmentVariableFixture
to be shared across
classes.
Create testA.m
as follows.
classdef (SharedTestFixtures = {... UserNameEnvironmentVariableFixture('David')}) ... testA < matlab.unittest.TestCase methods (Test) function t1(~) fprintf(1, 'Current UserName: "%s"', getenv('UserName')) end end end
Create testB.m
as follows.
classdef (SharedTestFixtures = {... UserNameEnvironmentVariableFixture('Andy')}) ... testB < matlab.unittest.TestCase methods (Test) function t1(~) fprintf(1, 'Current UserName: "%s"', getenv('UserName')) end end end
Create testC.m
as follows.
classdef (SharedTestFixtures = {... UserNameEnvironmentVariableFixture('Andy')}) ... testC < matlab.unittest.TestCase methods (Test) function t1(~) fprintf(1, 'Current UserName: "%s"', getenv('UserName')) end end end
At the command prompt, run the tests.
runtests({'testA','testB','testC'});
Setting up UserNameEnvironmentVariableFixture Done setting up UserNameEnvironmentVariableFixture: Set the UserName environment variable to "David". __________ Running testA Current UserName: "David". Done testA __________ Tearing down UserNameEnvironmentVariableFixture Done tearing down UserNameEnvironmentVariableFixture: Restored the UserName environment variable to "Kim". __________ Setting up UserNameEnvironmentVariableFixture Done setting up UserNameEnvironmentVariableFixture: Set the UserName environment variable to "Andy". __________ Running testB Current UserName: "Andy". Done testB __________ Running testC Current UserName: "Andy". Done testC __________ Tearing down UserNameEnvironmentVariableFixture Done tearing down UserNameEnvironmentVariableFixture: Restored the UserName environment variable to "Kim". __________
Recall that the fixtures are compatible if their UserName
properties match. The tests in testA
and
testB
use incompatible shared fixtures, since
'David'
is not equal to 'Andy'
.
Therefore, the framework invokes the fixture teardown
and
setup
methods between calls to testA
and testB
. However, the shared test fixture in
testC
is compatible with the fixture in
testB
, so the framework does not repeat fixture teardown
and setup before testC
.
Alternative Approach to Calling addTeardown in setup Method
An alternate approach to using the addTeardown
method
within the setup
method is to implement a separate
teardown
method . Instead of the setup
method described above, implement the following setup
and
teardown
methods within
UserNameEnvironmentVariableFixture.m
.
Alternate
UserNameEnvironmentVariableFixture
Class
Definition
The setup
method does not contain a call to
addTeardown
or a definition for
TeardownDescription
. These tasks are relegated to the
teardown
method. The alternative class definition
contains an additional property, OriginalUser
, which allows
the information to be passed between methods.
See Also
matlab.unittest.fixtures.Fixture