本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。
此示例演示如何创建在 TestClassSetup
、TestMethodSetup
和 Test
methods
块中被参数化的测试。该示例测试类测试随机数生成器。
TestRand
测试类在三个不同级别被参数化。
参数化级别 | 参数化定义 | 可访问的参数化属性 | |
---|---|---|---|
方法属性 | 属性特性 | ||
测试级别 | Test | TestParameter | TestParameter 、MethodSetupParameter 和 ClassSetupParameter |
方法设置级别 | TestMethodSetup | MethodSetupParameter | MethodSetupParameter 和 ClassSetupParameter |
类设置级别 | TestClassSetup | ClassSetupParameter | ClassSetupParameter |
在每个测试级别,您可以使用 ParameterCombination
方法属性指定测试参数化。
ParameterCombination 属性 | 方法调用 |
---|---|
'exhaustive' (默认值) | 对所有的参数组合调用方法。如何您不指定 ParameterCombination 属性,则测试框架使用此默认组合。 |
'sequential' | 通过每个参数中的相应值调用方法。每个参数必须包含相同数量的值。 |
'pairwise' | 至少对每对参数值调用一次方法。虽然测试框架可保证至少为每对值创建一次测试,但您不应依赖该大小、顺序或特定组的测试套件元素。 |
例如,使用组合的方法属性 TestMethodSetup, ParameterCombination='sequential'
指定 MethodSetupParameter
属性块中定义的方法设置级别参数的顺序组合。
对于此示例,类设置级别参数化定义随机数生成器的类型。方法设置级别参数化定义随机数生成器的种子,测试级别参数化定义随机数输出的数据类型和大小。
在您的工作文件夹下的文件中,创建一个从 matlab.unittest.TestCase
继承的类。该类测试随机数生成的各个方面。
classdef TestRand < matlab.unittest.TestCase
定义用于参数化测试的属性。每个 properties
块对应于特定级别的参数化。
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
定义测试类和测试方法级别的设置方法。这些方法注册初始随机数生成器状态。该框架运行测试后,这些方法将恢复原始状态。ClassSetup
方法定义随机数生成器的类型,TestMethodSetup
为生成器提供种子。
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
使用 Test
和 ParameterCombination='sequential'
属性定义 methods
块。测试框架对每个对应的属性值调用这些方法一次。
methods (Test, ParameterCombination='sequential') function testSize(testCase,dim1,dim2,dim3) testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3]) end end
该方法可用于测试 dim1
、dim2
和 dim3
中的每个对应的参数的输出的大小。例如,要测试所有 'medium'
值,请使用 testCase.verifySize(rand(2,3,4),[2 3 4]);
。对于给定的 TestClassSetup
和 TestMethodSetup
参数化,该框架调用 testSize
方法三次 - 'small'
、'medium'
和 'large'
值各一次。
使用 Test
和 ParameterCombination='pairwise'
属性定义 methods
块。测试框架对每对属性值至少调用这些方法一次。
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
测试方法验证随机数生成器结果是否可重复。对于给定的 TestClassSetup
和 TestMethodSetup
参数化,该框架调用 testRepeatble
方法 10 次以确保测试每对 dim1
、dim2
和 dim3
。但是,如果参数组合属性是 Exhaustive,该框架调用该方法 3^3=27
次。
使用 Test
属性或未定义的参数组合定义 methods
块。该参数组合默认为 exhaustive。测试框架对每个属性值组合调用这些方法一次。
methods (Test) function testClass(testCase,dim1,dim2,type) testCase.verifyClass(rand(dim1,dim2,type), type) end end
该测试方法验证从 rand
输出的类是否与预期的类相同。对于给定的 TestClassSetup
和 TestMethodSetup
参数化,该框架调用 testClass
方法 3*3*2=18
次以确保测试每个 dim1
、dim2
和 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
在命令提示符下,基于 TestRand.m
类创建一个套件。
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.
该测试套件包含 279 个测试元素。对于给定的 TestClassSetup
和 TestMethodSetup
参数化,该框架创建 3+10+18=31
个测试元素。这 31 个元素被调用三次 - 每个 TestMethodSetup
参数化一次,从而为每个 TestClassSetup
参数化生成 3*31=93
个测试元素。存在三个 TestClassSetup
参数化,生成总计 3*93=279
个测试元素。
检查第一个测试元素的名称。
suite(1).Name
ans = 'TestRand[generator=twister]/[seed=value1]testClass(dim1=small,dim2=small,type=single)'
每个元素的名称是根据以下项的组合构造的:
测试类:TestRand
类设置属性和属性名:[generator=twister]
方法设置属性和属性名:[seed=value1]
测试方法名称:testClass
测试方法属性和属性名称:(dim1=small,dim2=small,type=single)
seed
属性的名称并不是特别有意义 (value1
)。测试框架提供此名称是因为 seed
属性值是数字。要使名称更有意义,请使用说明性更强的字段名称将 seed
属性定义为结构体。
在命令提示符下,创建一个选择器以选择用于测试 'twister'
生成器的 'single'
精度的测试元素。省略使用具有 'large'
名称的属性的测试元素。
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.
如果您首先生成完整套件,请使用 selectIf
方法构造与上面相同的测试套件。
suite = matlab.unittest.TestSuite.fromClass(?TestRand); suite2 = selectIf(suite,s);
运行测试套件。
suite2.run;
Running TestRand .......... .. Done TestRand __________
在命令提示符下,创建一个选择器,以便省略使用具有 'large'
或 'medium'
名称的属性的测试元素。将结果限制为来自 testRepeatable
方法的测试元素。
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)'
运行测试套件。
suite3.run;
Running TestRand ......... Done TestRand __________
在命令提示符下,通过 TestRand.m
运行所有使用参数名称 'double'
的测试元素。
runtests('TestRand','ParameterName','double');
Running TestRand .......... .......... .......... .......... .......... .......... .......... .......... . Done TestRand __________
matlab.unittest.selectors
| matlab.unittest.TestCase
| matlab.unittest.TestSuite