Search code examples
matlabunit-testingparameterized-unit-test

Creating parametrized Matlab unittest with complicated properties


I'm trying to create a parametrized Matlab unittest where the TestParameter properties are generated "dynamically" by some code (e.g., with a for loop).

As a simplified example, suppose my code is

classdef partest < matlab.unittest.TestCase
    properties (TestParameter)
        level = struct('level1', 1, 'level2', 2, 'level3', 3, 'level4', 4)
    end

    methods (Test)
        function testModeling(testCase, level)
            fprintf('Testing level %d\n', level);
        end
    end
end

but in my real code, I have 100 levels. I tried to put this in a separate method, like

classdef partest < matlab.unittest.TestCase
    methods (Static)
        function level = getLevel()
            for i=1:100
               level.(sprintf('Level%d', i)) = i;
            end
        end
    end

    properties (TestParameter)
        level = partest.getLevel()
    end

    methods (Test)
        function testModeling(testCase, level)
            fprintf('Testing level %d\n', level);
        end
    end
end

but that does not work; I get the error (Matlab 2014b):

>> runtests partest
Error using matlab.unittest.TestSuite.fromFile (line 163)
The class partest has no property or method named 'getLevel'.

I could move the getLevel() function to another file, but I'd like to keep it in one file.


Solution

  • Same here (R2015b), it looks like a TestParameter property cannot be initialized with a static function call...

    Fortunately the solution is quite simple, use a local function instead:

    partest.m

    classdef partest < matlab.unittest.TestCase
        properties (TestParameter)
            level = getLevel()
        end
    
        methods (Test)
            function testModeling(testCase, level)
                fprintf('Testing level %d\n', level);
            end
        end
    end
    
    function level = getLevel()
        for i=1:100
           level.(sprintf('Level%d', i)) = i;
        end
    end
    

    (Note that all the above code is contained in one file partest.m).

    Now this should work:

    >> run(matlab.unittest.TestSuite.fromFile('partest.m'))
    

    Note:

    Being a local function, it won't be visible outside the class. If you also need to expose it, just add a static function acting as a simple wrapper:

    classdef partest < matlab.unittest.TestCase
        ...
    
        methods (Static)
            function level = GetLevelFunc()
                level = getLevel();
            end
        end
    end
    
    function level = getLevel()
        ...
    end