Main Content

在参数化测试中使用外部参数

您可以将变量输入插入到基于类的现有测试中。要提供在测试文件外定义且需要由测试迭代使用(通过参数化测试)的测试数据,请创建一个由 Parameter 实例组成的数组,然后结合 ExternalParameters 名称-值参量使用 TestSuite 创建方法,例如 fromClass

创建 cleanData 函数。该函数接受数组,对数组进行向量化,删除 0NaNInf,然后对数组进行排序。

function Y = cleanData(X)
    Y = X(:);         % Vectorize array
    Y = rmmissing(Y); % Remove NaN
    % Remove 0 and Inf
    idx = (Y==0 | Y==Inf);
    Y = Y(~idx);
    % If array is empty, set to eps
    if isempty(Y)
        Y = eps;
    end
    Y = sort(Y);      % Sort vector
end

创建一个参数化测试来测试 cleanData 函数。该测试对 properties 块中定义的两个数据集重复使用四个 Test 方法。

classdef TestClean < matlab.unittest.TestCase
    properties (TestParameter)
        Data = struct("clean",[5 3 9;1 42 5;32 5 2], ...
            "needsCleaning",[1 13;NaN 0;Inf 42]);
    end
    methods (Test)
        function classCheck(testCase,Data)
            act = cleanData(Data);
            testCase.assertClass(act,"double")
        end
        function sortCheck(testCase,Data)
            act = cleanData(Data);
            testCase.verifyTrue(issorted(act))
        end
        function finiteCheck(testCase,Data)
            import matlab.unittest.constraints.IsFinite
            act = cleanData(Data);
            testCase.verifyThat(act,IsFinite)
        end
        function noZeroCheck(testCase,Data)
            import matlab.unittest.constraints.EveryElementOf
            import matlab.unittest.constraints.IsEqualTo
            act = cleanData(Data);
            testCase.verifyThat(EveryElementOf(act),~IsEqualTo(0))
        end
    end    
end

运行测试。该框架使用测试文件中定义的数据运行八个参数化测试。

import matlab.unittest.TestSuite
suite1 = TestSuite.fromClass(?TestClean);
results = suite1.run;
table(results)
Running TestClean
........
Done TestClean
__________


ans =

  8×6 table

                        Name                         Passed    Failed    Incomplete    Duration       Details   
    _____________________________________________    ______    ______    __________    _________    ____________

    {'TestClean/classCheck(Data=clean)'         }    true      false       false         0.66469    {1×1 struct}
    {'TestClean/classCheck(Data=needsCleaning)' }    true      false       false       0.0066959    {1×1 struct}
    {'TestClean/sortCheck(Data=clean)'          }    true      false       false       0.0039298    {1×1 struct}
    {'TestClean/sortCheck(Data=needsCleaning)'  }    true      false       false        0.003343    {1×1 struct}
    {'TestClean/finiteCheck(Data=clean)'        }    true      false       false        0.055924    {1×1 struct}
    {'TestClean/finiteCheck(Data=needsCleaning)'}    true      false       false       0.0017951    {1×1 struct}
    {'TestClean/noZeroCheck(Data=clean)'        }    true      false       false         0.90772    {1×1 struct}
    {'TestClean/noZeroCheck(Data=needsCleaning)'}    true      false       false        0.007801    {1×1 struct}

在测试文件外部创建数据集。

A = [NaN 2 0;1 Inf 3];

从外部数据集创建一个由 Parameter 实例组成的数组。fromData 方法接受来自 TestCleanproperties 块的参数化属性的名称,以及元胞数组(或结构体)形式的新数据。

import matlab.unittest.parameters.Parameter
newData = {A};
param = Parameter.fromData("Data",newData);

使用外部参数创建一个新测试套件。框架将字符 #ext 追加到参数名称的末尾,表示参数是在外部定义的。

suite2 = TestSuite.fromClass(?TestClean,"ExternalParameters",param);
{suite2.Name}'
ans =

  4×1 cell array

    {'TestClean/classCheck(Data=2x3_double#ext)' }
    {'TestClean/sortCheck(Data=2x3_double#ext)'  }
    {'TestClean/finiteCheck(Data=2x3_double#ext)'}
    {'TestClean/noZeroCheck(Data=2x3_double#ext)'}

要完全控制套件中的参数名称,请使用结构体定义参数。然后,运行测试。

newData = struct("commandLineData",A);
param = Parameter.fromData("Data",newData);
suite2 = TestSuite.fromClass(?TestClean,"ExternalParameters",param);
{suite2.Name}'
results = suite2.run;
ans =

  4×1 cell array

    {'TestClean/classCheck(Data=commandLineData#ext)' }
    {'TestClean/sortCheck(Data=commandLineData#ext)'  }
    {'TestClean/finiteCheck(Data=commandLineData#ext)'}
    {'TestClean/noZeroCheck(Data=commandLineData#ext)'}

Running TestClean
....
Done TestClean
__________

再创建一个数据集,并将其存储在 ASCII 分隔的文件中。

B = rand(3);
B(2,4) = 0;
writematrix(B,"myFile.dat")
clear B

从存储的数据集和 A 创建参数,然后创建一个测试套件。

newData = struct("commandLineData",A,"storedData",readmatrix("myFile.dat"));
param2 = Parameter.fromData("Data",newData);
suite3 = TestSuite.fromClass(?TestClean,"ExternalParameters",param2);

要使用测试文件中定义的参数以及在外部定义的参数运行测试,请串联测试套件。查看套件元素名称并运行测试。

suite = [suite1 suite3];
{suite.Name}'
results = suite.run;
ans =

  16×1 cell array

    {'TestClean/classCheck(Data=clean)'               }
    {'TestClean/classCheck(Data=needsCleaning)'       }
    {'TestClean/sortCheck(Data=clean)'                }
    {'TestClean/sortCheck(Data=needsCleaning)'        }
    {'TestClean/finiteCheck(Data=clean)'              }
    {'TestClean/finiteCheck(Data=needsCleaning)'      }
    {'TestClean/noZeroCheck(Data=clean)'              }
    {'TestClean/noZeroCheck(Data=needsCleaning)'      }
    {'TestClean/classCheck(Data=commandLineData#ext)' }
    {'TestClean/classCheck(Data=storedData#ext)'      }
    {'TestClean/sortCheck(Data=commandLineData#ext)'  }
    {'TestClean/sortCheck(Data=storedData#ext)'       }
    {'TestClean/finiteCheck(Data=commandLineData#ext)'}
    {'TestClean/finiteCheck(Data=storedData#ext)'     }
    {'TestClean/noZeroCheck(Data=commandLineData#ext)'}
    {'TestClean/noZeroCheck(Data=storedData#ext)'     }

Running TestClean
........
Done TestClean
__________

Running TestClean
........
Done TestClean
__________

另请参阅

|

相关主题