This example shows how to create a test that is parameterized in the TestClassSetup
, TestMethodSetup
, and Test
methods
blocks. The example test class tests the random number generator.
The TestRand
test class is parameterized at three different levels.
Parameterization Level | Parameterization Definition | Accessible Parameterization Properties | |
---|---|---|---|
Method Attribute | Property Attribute | ||
Test level | Test | TestParameter | TestParameter , MethodSetupParameter , and ClassSetupParameter |
Method setup level | TestMethodSetup | MethodSetupParameter | MethodSetupParameter and ClassSetupParameter |
Class setup level | TestClassSetup | ClassSetupParameter | ClassSetupParameter |
At each test level, you can use the ParameterCombination
method attribute to specify the test parameterization.
ParameterCombination Attribute | Method Invocation |
---|---|
'exhaustive' (default) | Methods are invoked for all combinations of parameters. The test framework uses this default combination if you do not specify the ParameterCombination attribute. |
'sequential' | Methods are invoked with corresponding values from each parameter. Each parameter must contain the same number of values. |
'pairwise' | Methods are invoked for every pair of parameter values at least once. While the test framework guarantees that tests are created for every pair of values at least once, you should not rely on that size, ordering, or specific set of test suite elements. |
For example, use the combined methods attribute TestMethodSetup, ParameterCombination='sequential'
to specify sequential combination of the method setup-level parameters defined in the MethodSetupParameter
properties block.
For this example, 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 number output.
In a file in your working folder, create a class that inherits from matlab.unittest.TestCase
. This class tests various aspects of random number generation.
classdef TestRand < matlab.unittest.TestCase
Define the properties used for parameterized testing. Each properties
block corresponds to parameterization at a particular level.
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
Define the setup methods at the test class and test method level. 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 TestMethodSetup
seeds the generator.
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
Define a methods
block with the Test
and ParameterCombination='sequential'
attributes. The test framework invokes these methods once for each corresponding property value.
methods (Test, ParameterCombination='sequential') function testSize(testCase,dim1,dim2,dim3) testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3]) end end
The method tests the size of the output for each corresponding parameter in dim1
, dim2
, and dim3
. For example, to test all the 'medium'
values use: testCase.verifySize(rand(2,3,4),[2 3 4]);
. For a given TestClassSetup
and TestMethodSetup
parameterization, the framework calls the testSize
method three times—once each for the 'small'
, 'medium'
, and 'large'
values.
Define a methods
block with the Test
and ParameterCombination='pairwise'
attributes. The test framework invokes these methods at least once for every pair of property values.
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
The test method verifies that the random number generator results are repeatable. For a given TestClassSetup
and TestMethodSetup
parameterization, the framework calls the testRepeatble
method 10 times to ensure testing of each pair of dim1
, dim2
, and dim3
. However, if the parameter combination attribute is exhaustive, the framework calls the method 3^3=27
times.
Define a methods
block with the Test
attribute or no defined parameter combination. The parameter combination is exhaustive by default. The test framework invokes these methods once for every combination of property values.
methods (Test) function testClass(testCase,dim1,dim2,type) testCase.verifyClass(rand(dim1,dim2,type), type) end end
The test 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 of each combination of dim1
, dim2
, and type
.
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
At the command prompt, create a suite from TestRand.m
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.
The test suite contains 279 test elements. For a given TestClassSetup
and TestMethodSetup
parameterization, the framework creates 3+10+18=31
test elements. These 31 elements are called three times—once for each TestMethodSetup
parameterization resulting in 3*31=93
test elements for each TestClassSetup
parameterization. There are three TestClassSetup
parameterizations resulting in a total of 3*93=279
test elements.
Examine the names of the first test element.
suite(1).Name
ans = 'TestRand[generator=twister]/[seed=value1]testClass(dim1=small,dim2=small,type=single)'
The name of each element is constructed from the combination of the following:
Test class: TestRand
Class setup property and property name: [generator=twister]
Method setup property and property name: [seed=value1]
Test method name: testClass
Test method properties and property names: (dim1=small,dim2=small,type=single)
The name for the seed
property isn’t particularly meaningful (value1
). The testing framework provided this name because the seed
property values are numbers. For a more meaningful name, define the seed
property as a struct with more descriptive field names.
At the command prompt, create a selector to select test elements that test the 'twister'
generator for 'single'
precision. Omit test elements that use properties with the 'large'
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, construct the same test suite as above using the selectIf
method.
suite = matlab.unittest.TestSuite.fromClass(?TestRand); suite2 = selectIf(suite,s);
Run the test suite.
suite2.run;
Running TestRand .......... .. Done TestRand __________
At the command prompt, create a selector that omits test elements that use properties with the 'large'
or 'medium'
name. 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=value1]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=twister]/[seed=value2]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=twister]/[seed=value3]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=combRecursive]/[seed=value1]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=combRecursive]/[seed=value2]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=combRecursive]/[seed=value3]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=multFibonacci]/[seed=value1]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=multFibonacci]/[seed=value2]testRepeatable(dim1=small,dim2=small,dim3=small)' 'TestRand[generator=multFibonacci]/[seed=value3]testRepeatable(dim1=small,dim2=small,dim3=small)'
Run the test suite.
suite3.run;
Running TestRand ......... Done TestRand __________
At the command prompt, run all the test elements from TestRand.m
that use the parameter name 'double'
.
runtests('TestRand','ParameterName','double');
Running TestRand .......... .......... .......... .......... .......... .......... .......... .......... . Done TestRand __________
matlab.unittest.TestCase
| matlab.unittest.TestSuite
| matlab.unittest.selectors