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.
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.
classdef UserNameEnvironmentVariableFixture < ... matlab.unittest.fixtures.Fixture properties (SetAccess=private) UserName end
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
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.
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
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
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
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 __________
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
.
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.
matlab.unittest.fixtures.Fixture