在 Matlab UnitTest 诊断中同时使用字符串和函数?

Using both strings and functions in Matlab UnitTest diagnostics?

testCase.verifyEqual方法here请参考文档。文档说只能使用其中一个诊断功能。我的要求是同时需要两个诊断 - 字符串和函数句柄。以下是我正在努力实现的简单示例,

classdef testArrays < matlab.unittest.TestCase
    methods (Test)
        function testArraysEquality(testCase)
            a = 1:10;
            b = 1:10;
            incrementFunc = @(x)x+1;
            failureCount;
            for i=1:length(a)
                 testCase.verifyEqual(a(i),b(i),'AbsTol',10e-3,['Test failed array element# ' num2str(i) ' failure count ' num2str(incrementFunc(failureCount))]);
            end
            disp([num2str(failureCount) ' out of ' num2str(length(a)) ' test cases failed']);
        end
    end
end

问题是匿名函数不存储值。另一方面,使用下面显示的 'assignin' 功能,可以递增和存储该值,但不能返回以在 disp() 中使用。有什么解决方法吗?

incrementFunc1 = @(x) assignin('caller', inputname(1), x+1);

您只需向 verifyEqual 提供诊断数组,即可在 MATLAB 单元测试框架中包含多种(以及多种类型)诊断。您实际上可以按如下方式明确地执行此操作:

import matlab.unittest.diagnostics.StringDiagnostic;
import matlab.unittest.diagnostics.FunctionHandleDiagnostic;
testCase.verifyEqual(a,e, [StringDiagnostic('some string'), FunctionHandleDiagnostic(@() someFunction)]);

但是,提供了 Diagnostic.join 方法以简化操作:

import matlab.unittest.diagnostics.Diagnostic;
testCase.verifyEqual(a,e, Diagnostic.join('some string', @() someFunction)); 

为了进行增量调用,您可能需要将失败的侦听器添加到测试用例中,以便正确增量。请注意 people/plugins 实际上可以添加侦听器并在除了失败案例之外的通过案例中执行这些诊断。因此,您的诊断消息不应假定每次调用它们时都处于失败状态。这不仅适用于您的递增代码,还适用于您提供的消息。我建议不要说:

Test failed array element# 3 failure count 2

你应该说:

Tested array element# 3 failure count 2

框架诊断会让您知道它是否失败。无论如何,外卖,不要依赖调用诊断来确定故障计数。然后怎样呢?查看“事件”部分 here。您应该明确监听验证失败事件,以便将该信息添加到您的诊断中。

对于第一个解决方案,我不确定您为什么需要为每次失败提供失败计数。这似乎会非常冗长。如果你不需要,那么你可以这样做:

classdef testArrays < matlab.unittest.TestCase
    methods (Test)
        function testArraysEquality(testCase)
            a = 1:10;
            b = 1:10;
            failureCount = 0;
            testCase.addlistener('VerificationFailed', @incrementFailureCount);
            function incrementFailureCount(varargin)
                % This is a nested function & has the scope and can see/modify
                % the failureCount variable. This could also be done with a
                % property on the class ans a method that increments it
                failureCount = failureCount + 1;
            end
            for i=1:length(a)
                 testCase.verifyEqual(a(i),b(i),'AbsTol',10e-3,['Tested array element # ' num2str(i)]);
            end
            % I suggest using log instead of disp. If you want it to show up most of the time you can
            % log it at Terse (1) verbosity. However, if you don't want to see it you can turn it off.
            testCase.log(1, sprintf('%d out of %d test cases failed', failureCount, length(a)));
        end
    end
end

这样够好吗?如果你真的想在诊断中显示每次故障的故障计数,你可以稍微复杂一点,需要另一个嵌套函数(或 属性 访问)。

classdef testArrays < matlab.unittest.TestCase
    methods (Test)
        function testArraysEquality(testCase)
            import matlab.unittest.diagnostics.Diagnostic;

            a = 1:10;
            b = 1:10;
            failureCount = 0;
            testCase.addlistener('VerificationFailed', @incrementFailureCount);
            function incrementFailureCount(varargin) 
                failureCount = failureCount + 1;
            end
            function displayFailureCount
                fprintf(1, 'Failure Count: %d', failureCount);
            end
            for i=1:length(a)
                 testCase.verifyEqual(a(i),b(i),'AbsTol',10e-3, ...
                     Diagnostic.join(...
                         ['Tested array element #' num2str(i)], ...
                         @displayFailureCount));
            end
            testCase.log(1, sprintf('%d out of %d test cases failed', failureCount, length(a)));
        end
    end
end

这是否有助于您完成您想要做的事情?