创建高级参数化测试
此示例演示如何创建在 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