This example shows how to create a basic parameterized test.
In your working folder, create a function in the file
sierpinski.m
. This function returns a matrix representing
an image of a Sierpinski carpet fractal. It takes as input the fractal level and
an optional data type.
function carpet = sierpinski(nLevels,classname) if nargin == 1 classname = 'single'; end mSize = 3^nLevels; carpet = ones(mSize,classname); cutCarpet(1,1,mSize,nLevels) % begin recursion function cutCarpet(x,y,s,cL) if cL ss = s/3; % define subsize for lx = 0:2 for ly = 0:2 if lx == 1 && ly == 1 % remove center square carpet(x+ss:x+2*ss-1,y+ss:y+2*ss-1) = 0; else % recurse cutCarpet(x + lx*ss, y + ly*ss, ss, cL-1) end end end end end end
In a file in your working folder, create a new class,
TestCarpet
, to test the sierpinski
function.
classdef TestCarpet < matlab.unittest.TestCase
Define the properties used for parameterized testing. In the
TestCarpet
class, define these properties in a property
block with the TestParameter
attribute.
properties (TestParameter) type = {'single','double','uint16'}; level = struct('small', 2,'medium', 4, 'large', 6); side = struct('small', 9, 'medium', 81,'large', 729); end
The type
property contains the different data types you
want to test. The level
property contains the different
fractal level you want to test. The side
property contains
the number of rows and columns in the Sierpinski carpet matrix and corresponds
to the level
property. To provide meaningful names for each
parameterization value, level
and side
are
defined as structs.
Define the following test methods in the TestCarpet
class.
methods (Test) function testRemainPixels(testCase, level) % expected number pixels equal to 1 expPixelCount = 8^level; % actual number pixels equal to 1 actPixels = find(sierpinski(level)); testCase.verifyNumElements(actPixels,expPixelCount) end function testClass(testCase, type, level) testCase.verifyClass(... sierpinski(level,type), type); end function testDefaultL1Output(testCase) exp = single([1 1 1; 1 0 1; 1 1 1]); testCase.verifyEqual(sierpinski(1), exp) end end
The testRemainPixels
method tests the output of the
sierpinski
function by verifying that the number of
nonzero pixels is the same as expected for a particular level. This method uses
the level
property and, therefore, results in three test
elements—one for each value in level
. The
testClass
method tests the class of the output from the
sierpinski
function with each combination of the
type
and level
properties. This
approach results in nine test elements. The
testDefaultL1Output
test method does not use a
TestParameter
property and, therefore, is not
parameterized. This test method verifies that the level 1 matrix contains the
expected values. Since the test method is not parameterized, it results in a one
test element.
In the test methods above, you did not define the
ParameterCombination
attribute of the
Test
methods block. This attribute is, by default,
'exhaustive'
. The test framework invokes a given test
method once for every combination of the test parameters.
Define the following test methods in the TestCarpet
class
to ensure that the matrix output by the sierpinski
function
has the correct number of elements. Set the
ParameterCombination
attribute to
'sequential'
.
methods (Test, ParameterCombination='sequential') function testNumel(testCase, level, side) import matlab.unittest.constraints.HasElementCount testCase.verifyThat(sierpinski(level),... HasElementCount(side^2)) end end end
Test methods with the ParameterCombination
attribute set to
'sequential'
are invoked once for each corresponding
value of the parameter. The properties, level
and
side
, must have the same number of values. Since these
properties each have three values, the testNumel
method is
invoked three times.
The complete contents of TestCarpet.m
follows.
classdef TestCarpet < matlab.unittest.TestCase properties (TestParameter) type = {'single','double','uint16'}; level = struct('small', 2,'medium', 4, 'large', 6); side = struct('small', 9, 'medium', 81,'large', 729); end methods (Test) function testRemainPixels(testCase, level) % expected number pixels equal to 1 expPixelCount = 8^level; % actual number pixels equal to 1 actPixels = find(sierpinski(level)); testCase.verifyNumElements(actPixels,expPixelCount) end function testClass(testCase, type, level) testCase.verifyClass(... sierpinski(level,type), type) end function testDefaultL1Output(testCase) exp = single([1 1 1; 1 0 1; 1 1 1]); testCase.verifyEqual(sierpinski(1), exp) end end methods (Test, ParameterCombination='sequential') function testNumel(testCase, level, side) import matlab.unittest.constraints.HasElementCount testCase.verifyThat(sierpinski(level),... HasElementCount(side^2)) end end end
At the command prompt, create a suite from
TestCarpet.m
.
suite = matlab.unittest.TestSuite.fromFile('TestCarpet.m');
{suite.Name}'
ans = 'TestCarpet/testNumel(level=small,side=small)' 'TestCarpet/testNumel(level=medium,side=medium)' 'TestCarpet/testNumel(level=large,side=large)' 'TestCarpet/testRemainPixels(level=small)' 'TestCarpet/testRemainPixels(level=medium)' 'TestCarpet/testRemainPixels(level=large)' 'TestCarpet/testClass(type=single,level=small)' 'TestCarpet/testClass(type=single,level=medium)' 'TestCarpet/testClass(type=single,level=large)' 'TestCarpet/testClass(type=double,level=small)' 'TestCarpet/testClass(type=double,level=medium)' 'TestCarpet/testClass(type=double,level=large)' 'TestCarpet/testClass(type=uint16,level=small)' 'TestCarpet/testClass(type=uint16,level=medium)' 'TestCarpet/testClass(type=uint16,level=large)' 'TestCarpet/testDefaultL1Output'
The suite had 16 test elements. The element’s Name
indicates any parameterization.
suite.run;
Running TestCarpet .......... ...... Done TestCarpet __________
Use the selectIf
method of the TestSuite
to select test elements that use a particular parameterization. Select all test
elements that use the parameter name small
in the
level
parameter property list.
s1 = suite.selectIf('ParameterName','small'); {s1.Name}'
ans = 'TestCarpet/testNumel(level=small,side=small)' 'TestCarpet/testRemainPixels(level=small)' 'TestCarpet/testClass(type=single,level=small)' 'TestCarpet/testClass(type=double,level=small)' 'TestCarpet/testClass(type=uint16,level=small)'
The suite has five elements.
s1.run;
Running TestCarpet ..... Done TestCarpet __________
Alternatively, create the same test suite directly from the
fromFile
method of TestSuite
.
import matlab.unittest.selectors.HasParameter s1 = matlab.unittest.TestSuite.fromFile('TestCarpet.m',... HasParameter('Name','small'));
matlab.unittest.TestCase
| matlab.unittest.TestSuite.selectIf
| matlab.unittest.selectors.HasParameter