我已经创建了一些单元测试,我生成一些时间序列数据并运行两个不同的估计,使用生成的数据大致相等。当我直观地检查结果时,看起来大多数数据点都能正常工作但有一些较大的错误。
现在,我使用verifyEqual
进行比较设置以测试它们是否匹配。为了解决这个问题,我必须将verifyEqual
的容差增加到比我认为合理的更大。我想设置一个测试,我检查数组中95%以上的元素是否满足给定的容差。
例如,以下测试失败:
array1 = (1:100)';
array2 = array1 + rand(100, 1) ./ 100 + [zeros(4,1); .5; zeros(95,1)];
testCase = matlab.unittest.TestCase.forInteractiveUse;
testCase.verifyEqual(array1, array2, 'AbsTol', 0.01)
在这种情况下,我很好,有一个元素超出了容忍度,但是如果超过5个元素失败,我会担心。
是否有更好的方法在Matlab单元测试框架内运行此测试而不是testCase.verifyLessThanOrEqual(sum(abs(array1 - array2) >= 0.01), 5)
,即提供信息性故障输出的方法?
答案 0 :(得分:2)
目前测试框架中没有公差来提供此功能,但我认为它是一个有趣且好的用例。我将创建一个增强请求以提供这样的容差。
然而,与此同时,您可以创建自己的容差来执行此操作。 Here是描述如何执行此操作的文档。基本上它涉及编写supports
方法,该方法传递一个值并确定容差是否可以应用于该值。然后,您需要实现一个satisfiedBy
方法,该方法将两个值进行比较并确定它们是否在容差范围内。最后,您需要实现一个getDiagnosticFor
方法来返回一个诊断,为您提供所有信息输出。这里有一些东西可以帮助你入门:
classdef ForgivingAbsoluteTolerance < matlab.unittest.constraints.Tolerance
properties
% QualityRequired - percent of the compared array that needs to be
% within the specified tolerance
QualityRequired = 0.95;
AbsTolValue;
end
methods
function tolerance = ForgivingAbsoluteTolerance(absTol, quality)
tolerance.AbsTolValue = absTol;
if nargin > 1
tolerance.QualityRequired = quality;
end
end
function tf = supports(~, value)
tf = isnumeric(value);
end
function tf = satisfiedBy(tolerance, actual, expected)
withinTolerance = findWithinTolerance(actual, expected, tolerance.AbsTolValue);
tf = nnz(withinTolerance) >= numel(expected)*tolerance.QualityRequired;
end
function diag = getDiagnosticFor(tolerance, actual, expected)
import matlab.unittest.diagnostics.StringDiagnostic;
withinTolerance = findWithinTolerance(actual, expected, tolerance.AbsTolValue);
numValuesOutsideTolerance = nnz(~withinTolerance);
str = [...
num2str(numValuesOutsideTolerance) ' values were found outside of the tolerance value of ' num2str(tolerance.AbsTolValue), newline, ...
'The tolerance''s quality of ' num2str(tolerance.QualityRequired) ' allows ' num2str(floor(numel(expected)*(1-tolerance.QualityRequired))) ' elements to be outside of the tolerance.', newline, ...
' Failing Indices: ' mat2str(find(~withinTolerance))];
diag = StringDiagnostic(str);
end
end
end
function mask = findWithinTolerance(actual,expected, tolerance)
mask = abs(expected - actual) <= tolerance;
mask = mask(:).'; % make a row for better mat2str output
end
这只是一个开始。通过更多的时间/精力,您可以更好地进行诊断。但是,一旦你写了这个,你可以通过发出以下调用来重复使用它:
testCase.verifyThat(array1, IsEqualTo(array2, 'Within', ));
>> array1 = (1:100)';
>> array2 = array1 + rand(100, 1) ./ 100 + [zeros(4,1); .5; zeros(95,1)];
>> testCase = matlab.unittest.TestCase.forInteractiveUse;
>> testCase.verifyThat(array1, IsEqualTo(array2, 'Within', ForgivingAbsoluteTolerance(0.01)))
Interactive verification passed.
>> % now let's see a failing one.
>> array2 = array1 + rand(100, 1) ./ 100 + [zeros(4,1); ones(6,1)*.5; zeros(90,1)];
>> testCase.verifyThat(array1, IsEqualTo(array2, 'Within', ForgivingAbsoluteTolerance(0.01)))
Interactive verification failed.
---------------------
Framework Diagnostic:
---------------------
IsEqualTo failed.
--> NumericComparator failed.
--> The values are not equal using "isequaln".
--> 6 values were found outside of the tolerance value of 0.01
The tolerance's quality of 0.95 allows 5 elements to be outside of the tolerance.
Failing Indices: [5 6 7 8 9 10]
Actual double:
100x1 double
Expected double:
100x1 double
>>