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 testRemainPixes
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.selectors.HasParameter
| matlab.unittest.TestCase
| matlab.unittest.TestSuite.selectIf