创建高级参数化测试
此示例演示如何创建在 TestClassSetup、TestMethodSetup 和 Test methods 块中被参数化的测试。示例测试类测试随机数生成。
创建 TestRand 测试类
在当前文件夹的一个文件中创建 TestRand 类来测试随机数生成的各个方面。定义用于参数化测试的属性。
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 end
在 TestRand 类中,每个 properties 块对应于一个特定级别的参数化。类设置级别的参数化定义随机数生成器的类型。方法设置级别参数化定义随机数生成器的种子,测试级别参数化定义随机值的数据类型和大小。
定义测试类和测试方法设置方法
定义测试类和测试方法级别的设置方法。这些方法注册初始随机数生成器状态。该框架运行测试后,这些方法将恢复原始状态。classSetup 方法定义随机数生成器的类型,methodSetup 方法为生成器提供种子。
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 end
用顺序参数组合定义测试方法
在具有 Test 和 ParameterCombination = 'sequential' 特性的 methods 代码块中定义 testSize 方法。
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 end
该方法可用于测试 dim1、dim2 和 dim3 中的每个对应的参数值的输出的大小。对于给定的 TestClassSetup 和 TestMethodSetup 参数化值,该框架调用 testSize 方法三次 - 分别针对 'small'、'medium' 和 'large' 值调用一次。例如,要用所有 'medium' 值进行测试,框架使用 testCase.verifySize(rand(2,3,4),[2 3 4])。
使用成对参数组合定义测试方法
在具有 Test 和 ParameterCombination = 'pairwise' 特性的 methods 代码块中定义 testRepeatable 方法。
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 end
该方法验证随机数生成器结果是否可重复。对于给定的 TestClassSetup 和 TestMethodSetup 参数化值,该框架调用 testRepeatable 方法 10 次,以确保由 dim1、dim2 和 dim3 指定的每对参数值都经过测试。如果参数组合以穷举方式提供,该框架将调用该方法 3³ = 27 次。
使用穷举参数组合定义测试方法
在具有 Test 特性的 methods 代码块中定义 testClass 方法。由于未指定 ParameterCombination 特性,默认情况下参数组合以穷举方式提供。
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
该方法验证从 rand 输出的类是否与预期的类相同。对于给定的 TestClassSetup 和 TestMethodSetup 参数化值,该框架调用 testClass 方法 3×3×2 = 18 次,以确保 dim1、dim2 和 type 参数值的每个组合都经过测试。
基于测试类创建套件
在命令提示符下,基于 TestRand 类创建一个套件。
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.
对于给定的 TestClassSetup 和 TestMethodSetup 参数化值,该框架创建 3+10+18 = 31 个测试元素。对每个 TestMethodSetup 参数化值都调用这 31 个元素,会为每个 TestClassSetup 参数化值生成 3×31 = 93 个测试元素。由于共有三个 TestClassSetup 参数化值;因此,该套件共有 3×93 = 279 个测试元素。
查询第一个测试元素的名称。
suite(1).Name
ans =
'TestRand[generator=twister]/[seed=0]testClass(dim1=small,dim2=small,type=single)'第一个元素的名称由以下各部分组成:
测试类 -
TestRand类设置属性和参数名称 -
[generator=twister]方法设置属性和参数名称 -
[seed=0]测试方法名称 -
testClass测试方法属性和参数名称 -
(dim1=small,dim2=small,type=single)
运行使用选择器创建的套件
在命令提示符下,创建一个选择器以选择用于测试 '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.
如果您首先基于 TestRand 类生成完整套件,则可以使用 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=0]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=twister]/[seed=123]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=twister]/[seed=4294967295]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=combRecursive]/[seed=0]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=combRecursive]/[seed=123]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=combRecursive]/[seed=4294967295]testRepeatable(dim1=small,dim2=small,dim3=small)'}
{'TestRand[generator=multFibonacci]/[seed=0]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=multFibonacci]/[seed=123]testRepeatable(dim1=small,dim2=small,dim3=small)' }
{'TestRand[generator=multFibonacci]/[seed=4294967295]testRepeatable(dim1=small,dim2=small,dim3=small)'}运行测试套件。
suite3.run;
Running TestRand ......... Done TestRand __________
运行所有双精度测试
在命令提示符下,运行 TestRand 类中使用 'double' 参数名称的所有测试元素。
runtests('TestRand','ParameterName','double');
Running TestRand .......... .......... .......... .......... .......... .......... .......... .......... . Done TestRand __________
另请参阅
matlab.unittest.TestSuite | matlab.unittest.TestCase | matlab.unittest.selectors.HasParameter