Matlab:不正确的索引矩阵参考(或超越matlab)

man*_*els 6 oop syntax matlab unit-testing

我希望能够在Matlab中编写类似jasmine的测试.所以像

expect(myfibonacci(0)).toBe(0);
expect(myfibonacci(5)).toBe(15);
expect(myfibonacci(10)).toBe(55);
Run Code Online (Sandbox Code Playgroud)

我试图实现这两个策略:

(1)第一种策略使用结构

expect = @(actual_value) struct('toBe', @(expected_value) assert(actual_value == expected_value));
Run Code Online (Sandbox Code Playgroud)

(真正的实现不只是调用assert)

但是这不起作用:

expect(1).toBe(1); % this triggers a syntax error
??? Improper index matrix reference.

% this will work:
x = expect(1);
x.toBe(1);
Run Code Online (Sandbox Code Playgroud)

(2)我尝试的第二个策略是使用一个类:

classdef expect
properties (Hidden)
    actual_value
end

methods
    function obj = expect(actual_value)
        obj.actual_value = actual_value;
    end

    function obj = toBe(obj, expected_value)
        assert(obj.actual_value == expected_value);
    end
end
end
Run Code Online (Sandbox Code Playgroud)

乍一看,这看起来很好:你可以在控制台中运行

expect(1).toBe(1);
Run Code Online (Sandbox Code Playgroud)

但是,不是在控制台中运行,而是在脚本中运行

??? Static method or constructor invocations cannot be indexed.
Do not follow the call to the static method or constructor with
any additional indexing or dot references.

Error in ==> test at 1
expect(1).toBe(1);
Run Code Online (Sandbox Code Playgroud)

有没有办法让这个想法在matlab中运行?

Sam*_*rts 7

在最新版本的MATLAB(13a/13b)中,内置了一个单元测试框架,看起来非常类似于您正在尝试的内容.代替

expect(myfibonacci(0)).toBe(0);
Run Code Online (Sandbox Code Playgroud)

你会写的

import matlab.unittest.constraints.IsEqualTo
testCase.verifyThat(myfibonacci(0), IsEqualTo(0))
Run Code Online (Sandbox Code Playgroud)

(你也/替代有assumeThat,assertThatfatalAssertThat).

如果由于某种原因您希望实现自己的框架,请注意语法中的细微差别 - 您有一个点,而MathWorks myfibonacci(0)在测试条件之间有逗号.

在MATLAB中,你无法索引这样的下标表达式的结果(嗯,你可以,但你必须超载subsref,这是一个痛苦的世界,相信我).因此,他们完成它的方式是将测试比较条件作为单独的包引入,并将它们作为单独的输入参数应用,而不是作为带有点语法的方法.

查看新单元测试框架的文档,以了解有关框架本身的更多信息,或者(如果您更愿意自己编写)他们设计的语法作为与您的比较.


seb*_*ian 2

下面是一个带有重载 subsref 方法的示例实现。我猜也可以只用一个类来完成,但这会使 subsref 重载更加难看。

classdef Tester < handle
    methods
        function obj = Tester()
        end

        function [varargout] = subsref(this,S)

            if S(1).type(1) =='('
                tv = TestValue(S(1).subs{:});
            end

            if numel(S) > 1
                try
                    [varargout{1:nargout}] = builtin('subsref', tv, S(2:end));
                catch me
                    me.throwAsCaller();
                end
            else
                varargout{1} = tv;
            end

        end
    end
end
Run Code Online (Sandbox Code Playgroud)

classdef TestValue 
    properties (Hidden)
        value;
    end
    methods
        function this = TestValue(value)
            this.value = value;
        end

        function toBe(this, v)
            assert( isequal(this.value, v) );
        end
    end
end
Run Code Online (Sandbox Code Playgroud)

结果是:

>> expect(1).toBe(1)
>> expect(1).toBe(2)
Error using TestValue/toBe (line 13)
Assertion failed.
Run Code Online (Sandbox Code Playgroud)