Create Advanced Parameterized Test
This example shows how to create a test that is parameterized in
the TestClassSetup, TestMethodSetup, and
Test
methods blocks. The example test class tests random number
generation.
Create TestRand Test Class
In a file in your current folder, create the TestRand class
to test various aspects of random number generation. Define the properties used
for parameterized testing.
classdef TestRand < matlab.unittest.TestCase properties (ClassSetupParameter) generator = {'twister','combRecursive','multFibonacci'}; end properties (MethodSetupParameter) seed = {0,123,4294967295}; end properties (TestParameter) dim1 = struct('small',1,'medium',2,'large',3); dim2 = struct('small',2,'medium',3,'large',4); dim3 = struct('small',3,'medium',4,'large',5); type = {'single','double'}; end end
In the TestRand class, each properties
block corresponds to parameterization at a particular level. The class
setup-level parameterization defines the type of random number generator. The
method setup-level parameterization defines the seed for the random number
generator, and the test-level parameterization defines the data type and size of
the random values.
Define Test Class and Test Method Setup Methods
Define the setup methods at the test class and test method levels. These
methods register the initial random number generator state. After the framework
runs the tests, the methods restore the original state. The
classSetup method defines the type of random number
generator, and the methodSetup method seeds the
generator.
classdef TestRand < matlab.unittest.TestCase properties (ClassSetupParameter) generator = {'twister','combRecursive','multFibonacci'}; end properties (MethodSetupParameter) seed = {0,123,4294967295}; end properties (TestParameter) dim1 = struct('small',1,'medium',2,'large',3); dim2 = struct('small',2,'medium',3,'large',4); dim3 = struct('small',3,'medium',4,'large',5); type = {'single','double'}; end methods (TestClassSetup) function classSetup(testCase,generator) orig = rng; testCase.addTeardown(@rng,orig) rng(0,generator) end end methods (TestMethodSetup) function methodSetup(testCase,seed) orig = rng; testCase.addTeardown(@rng,orig) rng(seed) end end end
Define Test Method with Sequential Parameter Combination
Define the testSize method in a methods
block with the Test and ParameterCombination =
'sequential' attributes.
classdef TestRand < matlab.unittest.TestCase properties (ClassSetupParameter) generator = {'twister','combRecursive','multFibonacci'}; end properties (MethodSetupParameter) seed = {0,123,4294967295}; end properties (TestParameter) dim1 = struct('small',1,'medium',2,'large',3); dim2 = struct('small',2,'medium',3,'large',4); dim3 = struct('small',3,'medium',4,'large',5); type = {'single','double'}; end methods (TestClassSetup) function classSetup(testCase,generator) orig = rng; testCase.addTeardown(@rng,orig) rng(0,generator) end end methods (TestMethodSetup) function methodSetup(testCase,seed) orig = rng; testCase.addTeardown(@rng,orig) rng(seed) end end methods (Test, ParameterCombination = 'sequential') function testSize(testCase,dim1,dim2,dim3) testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3]) end end end
The method tests the size of the output for each corresponding parameter value
in dim1, dim2, and
dim3. For a given TestClassSetup and
TestMethodSetup parameterization, the framework calls the
testSize method three times — one time for each of
the 'small', 'medium', and
'large' values. For example, to test with all of the
'medium' values, the framework uses
testCase.verifySize(rand(2,3,4),[2 3 4]).
Define Test Method with Pairwise Parameter Combination
Define the testRepeatable method in a
methods block with the Test and
ParameterCombination = 'pairwise' attributes.
classdef TestRand < matlab.unittest.TestCase properties (ClassSetupParameter) generator = {'twister','combRecursive','multFibonacci'}; end properties (MethodSetupParameter) seed = {0,123,4294967295}; end properties (TestParameter) dim1 = struct('small',1,'medium',2,'large',3); dim2 = struct('small',2,'medium',3,'large',4); dim3 = struct('small',3,'medium',4,'large',5); type = {'single','double'}; end methods (TestClassSetup) function classSetup(testCase,generator) orig = rng; testCase.addTeardown(@rng,orig) rng(0,generator) end end methods (TestMethodSetup) function methodSetup(testCase,seed) orig = rng; testCase.addTeardown(@rng,orig) rng(seed) end end methods (Test, ParameterCombination = 'sequential') function testSize(testCase,dim1,dim2,dim3) testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3]) end end methods (Test, ParameterCombination = 'pairwise') function testRepeatable(testCase,dim1,dim2,dim3) state = rng; firstRun = rand(dim1,dim2,dim3); rng(state) secondRun = rand(dim1,dim2,dim3); testCase.verifyEqual(firstRun,secondRun) end end end
The method verifies that the random number generator results are repeatable.
For a given TestClassSetup and
TestMethodSetup parameterization, the framework calls the
testRepeatable method 10 times to ensure testing with
each pair of parameter values specified by dim1,
dim2, and dim3. If the parameter
combination were exhaustive, the framework would call the method 3³ = 27
times.
Define Test Method with Exhaustive Parameter Combination
Define the testClass method in a methods
block with the Test attribute. Because the
ParameterCombination attribute is not specified, the
parameter combination is exhaustive by default.
classdef TestRand < matlab.unittest.TestCase properties (ClassSetupParameter) generator = {'twister','combRecursive','multFibonacci'}; end properties (MethodSetupParameter) seed = {0,123,4294967295}; end properties (TestParameter) dim1 = struct('small',1,'medium',2,'large',3); dim2 = struct('small',2,'medium',3,'large',4); dim3 = struct('small',3,'medium',4,'large',5); type = {'single','double'}; end methods (TestClassSetup) function classSetup(testCase,generator) orig = rng; testCase.addTeardown(@rng,orig) rng(0,generator) end end methods (TestMethodSetup) function methodSetup(testCase,seed) orig = rng; testCase.addTeardown(@rng,orig) rng(seed) end end methods (Test, ParameterCombination = 'sequential') function testSize(testCase,dim1,dim2,dim3) testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3]) end end methods (Test, ParameterCombination = 'pairwise') function testRepeatable(testCase,dim1,dim2,dim3) state = rng; firstRun = rand(dim1,dim2,dim3); rng(state) secondRun = rand(dim1,dim2,dim3); testCase.verifyEqual(firstRun,secondRun) end end methods (Test) function testClass(testCase,dim1,dim2,type) testCase.verifyClass(rand(dim1,dim2,type),type) end end end
The method verifies that the class of the output from rand
is the same as the expected class. For a given TestClassSetup
and TestMethodSetup parameterization, the framework calls the
testClass method 3×3×2 = 18 times to ensure testing with
each combination of dim1, dim2, and
type parameter values.
Create Suite from Test Class
At the command prompt, create a suite from the TestRand
class.
suite = matlab.unittest.TestSuite.fromClass(?TestRand)
suite =
1×279 Test array with properties:
Name
ProcedureName
TestClass
BaseFolder
Parameterization
SharedTestFixtures
Tags
Tests Include:
17 Unique Parameterizations, 0 Shared Test Fixture Classes, 0 Tags.
For a given TestClassSetup and
TestMethodSetup parameterization, the framework creates
3+10+18 = 31 test elements. These 31 elements are called for each
TestMethodSetup parameterization (resulting in 3×31 = 93
test elements for each TestClassSetup parameterization).
There are three TestClassSetup parameterizations; therefore,
the suite has a total of 3×93 = 279 test elements.
Query the name of the first test element.
suite(1).Name
ans =
'TestRand[generator=twister]/[seed=0]testClass(dim1=small,dim2=small,type=single)'The name of the first element is composed of these parts:
Test class —
TestRandClass setup property and parameter name —
[generator=twister]Method setup property and parameter name —
[seed=0]Test method name —
testClassTest method property and parameter names —
(dim1=small,dim2=small,type=single)
Run Suite Created Using Selector
At the command prompt, create a selector to select test elements that test the
'twister' generator for 'single'
precision. Create a suite by omitting test elements that use properties with the
'large' parameter name.
import matlab.unittest.selectors.HasParameter s = HasParameter('Property','generator','Name','twister') & ... HasParameter('Property','type','Name','single') & ... ~HasParameter('Name','large'); suite2 = matlab.unittest.TestSuite.fromClass(?TestRand,s)
suite2 =
1×12 Test array with properties:
Name
ProcedureName
TestClass
BaseFolder
Parameterization
SharedTestFixtures
Tags
Tests Include:
9 Unique Parameterizations, 0 Shared Test Fixture Classes, 0 Tags.
If you first generate the full suite from the TestRand
class, you can construct the same filtered suite using the selectIf method.
suite = matlab.unittest.TestSuite.fromClass(?TestRand); suite2 = selectIf(suite,s);
Run the filtered test suite.
suite2.run;
Running TestRand .......... .. Done TestRand __________
Run Suite from Method Using Selector
Create a selector that omits test elements that use properties with the
'large' or 'medium' parameter names.
Limit results to test elements from the testRepeatable
method.
import matlab.unittest.selectors.HasParameter s = ~(HasParameter('Name','large') | HasParameter('Name','medium')); suite3 = matlab.unittest.TestSuite.fromMethod(?TestRand,'testRepeatable',s); {suite3.Name}'
ans =
9×1 cell array
{'TestRand[generator=twister]/[seed=0]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=twister]/[seed=123]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=twister]/[seed=4294967295]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=combRecursive]/[seed=0]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=combRecursive]/[seed=123]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=combRecursive]/[seed=4294967295]testRepeatable(dim1=small,dim2=small,dim3=small)'}
{'TestRand[generator=multFibonacci]/[seed=0]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=multFibonacci]/[seed=123]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=multFibonacci]/[seed=4294967295]testRepeatable(dim1=small,dim2=small,dim3=small)'}Run the test suite.
suite3.run;
Running TestRand ......... Done TestRand __________
Run All Double Precision Tests
At the command prompt, run all of the test elements from the
TestRand class that use the 'double'
parameter name.
runtests('TestRand','ParameterName','double');
Running TestRand .......... .......... .......... .......... .......... .......... .......... .......... . Done TestRand __________
See Also
matlab.unittest.TestSuite | matlab.unittest.TestCase | matlab.unittest.selectors.HasParameter