Main Content

本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

创建基本参数化测试

此示例演示如何创建基本参数化测试。

创建要测试的函数

在您的工作文件夹下,于文件 sierpinski.m 中创建一个函数。此函数返回一个表示 Sierpinski 地毯分形图像的矩阵。它采用分形级别和可选数据类型作为输入。

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

创建 TestCarpet 测试类

在您的工作文件夹下的文件中,创建一个新类 TestCarpet 以测试 sierpinski 函数。

classdef TestCarpet < matlab.unittest.TestCase

定义属性块

定义用于参数化测试的属性。在 TestCarpet 类中,使用 TestParameter 特性在一个属性块中定义这些属性。

    properties (TestParameter)
        type = {'single','double','uint16'};
        level = struct('small', 2,'medium', 4, 'large', 6);
        side = struct('small', 9, 'medium', 81,'large', 729);
    end

type 属性包含您要测试的不同数据类型。level 属性包含您要测试的不同分形级别。side 属性包含 Sierpinski 地毯矩阵的行数和列数并且对应于 level 属性。要为每个参数化值提供有意义的名称,请将 levelside 定义为结构体。

定义测试方法块

TestCarpet 类中定义以下测试方法。

    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

testRemainPixels 方法通过验证特定级别的非零像素数是否与预期相同,来测试 sierpinski 函数的输出。此方法使用 level 属性,因此产生三个测试元素 - level 中的每个值各一个。testClass 方法使用 typelevel 属性的每个组合测试从 sierpinski 函数输出的类。此方法产生九个测试元素。testDefaultL1Output 测试方法不使用 TestParameter 属性,因此不会被参数化。该测试方法验证 1 级矩阵是否包含预期值。因为该测试方法未被参数化,所以它产生一个测试元素。

在上面的测试方法中,您未定义 Test 方法块的 ParameterCombination 属性。该属性默认为 'exhaustive'。测试框架对测试参数的每个组合调用给定测试方法一次。

使用 ParameterCombination 属性定义测试方法块

TestCarpet 类中定义以下测试方法以确保 sierpinski 函数的矩阵输出具有正确数目的元素。将 ParameterCombination 属性设置为 '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

ParameterCombination 属性设置为 'sequential' 的测试方法对该参数的每个相应值调用一次。属性 levelside 必须具有相同数目的值。因为这些属性中的每个都有三个值,所以 testNumel 方法被调用三次。

TestCarpet 类定义总结

TestCarpet.m 的完整内容如下。

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

运行所有测试

在命令提示符下,基于 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'

该套件有 16 个测试元素。该元素的 Name 指示任何参数化。

suite.run;
Running TestCarpet
..........
......
Done TestCarpet
__________

运行 level 参数属性命名为 small 的测试

使用 TestSuiteselectIf 方法选择使用特定参数化的测试元素。选择所有在 level 参数属性列表中使用参数名称 small 的测试元素。

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)'

该套件有五个元素。

s1.run;
Running TestCarpet
.....
Done TestCarpet
__________

或者,直接从 TestSuitefromFile 方法创建同一测试套件。

import matlab.unittest.selectors.HasParameter
s1 = matlab.unittest.TestSuite.fromFile('TestCarpet.m',...
    HasParameter('Name','small'));

另请参阅

| |

相关主题