Matlab UnitTest TestCase可选结果图?

时间:2013-07-08 14:14:07

标签: matlab unit-testing plot testcase

使用matlab.unittest.TestCase类(2013a新增)在Matlab中测试项目的对象和函数时,有时需要一个图来显示实际/预期的数据。

到目前为止,我使用了以下方法,但觉得这不是最好的方法:

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

在命令行中,我使用test_obj=test1然后使用test_obj.graph_output=1,然后使用run(test_obj)输出图形以及测试函数。

更好的方法是使用单独的方法。我已经通过将my_result分配给属性列表来尝试这一点,但在测试完成后,matlab似乎重新初始化my_result,使输出图形无意义。

有没有人知道这种方式,或者根据需要输出测试结果的更好方法?

2 个答案:

答案 0 :(得分:9)

更新:在R2017a中,现在更加精简,包含FigureDiagnosticScreenshotDiagnostic。在沿着这条路走得太远之前先看看它们!

原始答案

您不仅可以在失败条件下执行此操作,还可以通过自定义诊断和DiagnosticsValidationPlugin组合传递条件。您可以使用函数句柄快速完成此操作,但如果您希望经常对许多测试执行此操作,请考虑创建自己的Diagnostic子类:

classdef PlotDiagnostic < matlab.unittest.diagnostics.Diagnostic

    properties
        Title
        Actual
        Expected
    end

    methods
        function diag = PlotDiagnostic(title, actual, expected)
            diag.Title = title;
            diag.Actual = actual;
            diag.Expected = expected;
        end
        function diagnose(diag)
            diag.DiagnosticResult = sprintf('Generating plot with title "%s"', diag.Title);
            f = figure('Title', diag.Title);
            ax = axes('Parent', f);
            plot(ax, 1:numel(diag.Actual), diag.Actual, 'r', 1:numel(diag.Expected), diag.Expected','b');
        end
    end
end

然后你可以进行一次使用它的测试:

classdef FooTest < matlab.unittest.TestCase

    methods(Test)
        function testFails(testCase)
            actual = 1:10;
            expected = fliplr(actual);
            testCase.verifyEqual(actual, expected, PlotDiagnostic('Title1', actual, expected));
        end
        function testPasses(testCase)
            actual = 1:10;
            expected = actual;
            testCase.verifyEqual(actual, expected, PlotDiagnostic('Title2', actual, expected));
        end
    end
end

现在,一旦您将其作为测试诊断程序,您将在失败条件下看到它们。但是,你也可以使用DiagnosticsValidationPlugin在传递条件下看到它们,它甚至在传递条件时评估诊断,以确保诊断代码没有错误(因为有一个错误,所以不能从真正的失败中捕获诊断信息是非常蹩脚的。通常不执行的诊断代码)。这看起来像是:

>> import matlab.unittest.*;
>> runner = TestRunner.withNoPlugins;
>> runner.addPlugin(matlab.unittest.plugins.DiagnosticsValidationPlugin);
>> suite = TestSuite.fromClass(?FooTest);
>> runner.run(suite)

请注意,从R2014a开始,您可以write your own plugin收听这些传递诊断信息,而不是使用DiagnosticsValidationPlugin。实际上在这个例子中我们没有使用这个插件来验证诊断是没有错误的,所以最好编写一个具有这个特定目的的自定义插件。

此外,在R2014b中,您可以利用log method将其连接到不同的拨号盘。如果您愿意,可以致电:

testCase.log(Verbosity.Detailed, PlotDiagnostic('Title2', actual, expected));

然后,您只能在“详细”详细程度级别使用LoggingPlugin时看到图表。

答案 1 :(得分:6)

通常当人们有兴趣查看特定测试的结果时,这是因为出了问题。这是使用自定义诊断的好机会。这里打印出一个指向MATLAB命令窗口的链接,该窗口根据实际值绘制预期值,并打印出将测试数据加载到工作区的链接。

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

运行此测试将产生包含

的输出
  • 将实际值和期望值加载到工作区中的链接
  • 点击时的链接将生成以下图表:

enter image description here

enter image description here

这些当然只会在测试失败时出现,但这通常是理想的行为!

N.B。我更喜欢使用IsEqualTo语法,以便测试(几乎)像英语一样。但这是一种风格决定。