6

在使用 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=test1and then test_obj.graph_output=1before usingrun(test_obj)来输出图形以及测试功能。

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

有谁知道解决这个问题的方法,或者有更好的按需输出测试结果的方法?

4

2 回答 2

10

更新:这在 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 开始,您可以编写自己的插件来监听这些传递的诊断信息,而不是使用 DiagnosticsValidationPlugin。实际上,在这个例子中,我们并没有使用这个插件来验证诊断是否没有错误,所以最好在考虑到这个特定目的的情况下编写一个自定义插件。

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

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

例如,当您在“详细”详细级别使用LoggingPlugin时,您只会看到这些图。

于 2013-07-09T21:33:10.410 回答
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

运行此测试将导致输出包含

  • 将实际值和预期值加载到工作区的链接
  • 单击时将生成以下图表的链接:

在此处输入图像描述

在此处输入图像描述

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

注意我更喜欢使用IsEqualTo语法,以便测试(几乎)像英语一样阅读。但这是一个风格决定。

于 2013-07-08T20:16:55.617 回答