Use External Parameters in Parameterized Test

You can inject variable inputs into your existing class-based test. To provide test data that is defined outside the test file and that should be used iteratively by the test (via parameterized testing), create a Parameter and use the 'ExternalParameters' option to TestSuite creation methods such as TestSuite.fromClass.

Create the following function to test. The function accepts an array, vectorizes the array, removes 0, Nan, and Inf, and then sorts the array.

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

Create the following parameterized test for the cleanData function. The test repeats each of the four test methods for the two data sets that are defined in the properties block.

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

Create and run a parameterized test suite. View the results. The framework runs the eight parameterized tests using the data defined in the test file.

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.19182    {1×1 struct}
    {'TestClean/classCheck(Data=needsCleaning)' }    true      false       false       0.0037433    {1×1 struct}
    {'TestClean/sortCheck(Data=clean)'          }    true      false       false       0.0030112    {1×1 struct}
    {'TestClean/sortCheck(Data=needsCleaning)'  }    true      false       false       0.0023779    {1×1 struct}
    {'TestClean/finiteCheck(Data=clean)'        }    true      false       false        0.044825    {1×1 struct}
    {'TestClean/finiteCheck(Data=needsCleaning)'}    true      false       false       0.0031761    {1×1 struct}
    {'TestClean/noZeroCheck(Data=clean)'        }    true      false       false         0.73055    {1×1 struct}
    {'TestClean/noZeroCheck(Data=needsCleaning)'}    true      false       false       0.0070594    {1×1 struct}

Create a data set external to the test file.

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

Create a parameter with the external data set. The fromData method accepts the name of the parameterized property from the properties block in TestClean and the new data as a cell array (or struct).

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

Create a new test suite and view the suite element names. The fromClass method accepts the new parameter.

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

  4×1 cell array

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

Using the external parameter, the framework creates four suite elements. Since the parameters are defined as a cell array, MATLAB generates the parameter name (value1). Also, it appends the characters #ext to the end of the parameter name, indicating the parameter is defined externally.

To assign meaningful parameter names (instead of valueN), define the parameter using a struct. View the suite element names and run the tests.

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
__________

Create another data set that is stored in an ASCII-delimited file.

B = rand(3);
B(2,4) = 0;
dlmwrite('myFile.dat',B)
clear B

Create a parameter with the stored data set and A.

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

To run the tests using parameters defined in the test file and externally, concatenate test suites. View the suite element names and run the tests.

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
__________

See Also

|

Related Topics