Search code examples
matlabunit-testingplottestcase

Matlab UnitTest TestCase with optional plots of results?


While testing objects and functions of a project in Matlab using matlab.unittest.TestCase classes (new to 2013a), sometimes a plot is needed to visualise the actual/expected data.

I have so far used the following method but feel this isn't the best way:

classdef test1 < matlab.unittest.TestCase

properties
    var1=3; var2=5;    % sample variables
    graph_output = 0;  % boolean
end

methods(Test)
    function testfunction(testCase)
        my_result = my_fun(testCase.var1, testCase.var2);
        testCase.verifyEqual(my_result,expected_result)

        if testCase.graph_output
            plot(my_result)
        end
    end
end

In the command line, I use test_obj=test1 and then test_obj.graph_output=1 before using run(test_obj) to output graphs as well as testing the function.

A better way to do this would be to use a separate method. I have tried this by allocating my_result to the properties list, but after the test completes, matlab seems to re-initialise my_result making the output graph meaningless.

Does anyone know a way round this, or any better way of outputting test results on demand?


Solution

  • Usually when people are interested in looking at results from a specific test it's because something has gone wrong. This is a good opportunity to use custom diagnostics. Here is one that prints out a link to the MATLAB command window which plots the expected value against the actual value, as well as printing out links which will load the data from the test into the workspace.

    classdef test1 < matlab.unittest.TestCase
    
    methods(Test)
        function firstTest(testCase)
            import matlab.unittest.constraints.IsEqualTo;
    
            % Test should pass!
            actualValue = 1:10;
            expectedValue = 1:10;
    
            diagnostic = @()myPlotDiagnostic(actualValue, expectedValue);
    
            testCase.verifyThat(actualValue, IsEqualTo(expectedValue), diagnostic);
        end
    
        function secondTest(testCase)
            import matlab.unittest.constraints.IsEqualTo;
    
            % Test should fail with a diagnostic!
            actualValue = [1 2 3 4 12 6 7 8 9 10];
            expectedValue = 1:10;
    
            diagnostic = @()myPlotDiagnostic(actualValue, expectedValue);
    
            testCase.verifyThat(actualValue, IsEqualTo(expectedValue), diagnostic);
        end
    
        function thirdTest(testCase)
            import matlab.unittest.constraints.IsEqualTo;
    
            % Test should also fail with a diagnostic!
            actualValue = [1 2 3 4 -12 6 7 8 9 10];
            expectedValue = 1:10;
    
            diagnostic = @()myPlotDiagnostic(actualValue, expectedValue);
    
            testCase.verifyThat(actualValue, IsEqualTo(expectedValue), diagnostic);
        end
    end
    
    end
    
    function myPlotDiagnostic(actualValue, expectedValue)
    temporaryFile = tempname;
    save(temporaryFile, 'actualValue', 'expectedValue');
    fprintf('<a href="matlab:plot([%s], [%s], ''*r'')">Plot Data</a>\n', num2str(expectedValue), num2str(actualValue));
    fprintf('<a href="matlab:load(''%s'')">Load data into workspace</a>\n', temporaryFile);
    end
    

    Running this test will result in outputs which contain

    • Links which will load the actual and expected values into the workspace
    • Links which when clicked will produce the following graphs:

    enter image description here

    enter image description here

    These will of course only show up though if the test fails, but this is generally the desired behaviour anyway!

    N.B. I prefer to use the IsEqualTo syntax so that the tests read (almost) like English. But this is a style decision.