使用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
,使输出图形无意义。
有没有人知道这种方式,或者根据需要输出测试结果的更好方法?
答案 0 :(得分:9)
更新:在R2017a中,现在更加精简,包含FigureDiagnostic和ScreenshotDiagnostic。在沿着这条路走得太远之前先看看它们!
原始答案
您不仅可以在失败条件下执行此操作,还可以通过自定义诊断和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
运行此测试将产生包含
的输出
这些当然只会在测试失败时出现,但这通常是理想的行为!
N.B。我更喜欢使用IsEqualTo
语法,以便测试(几乎)像英语一样。但这是一种风格决定。