Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab: Improper index matrix reference (or outsmarting matlab)

I want to be able to write jasmine-like tests in Matlab. So something like

expect(myfibonacci(0)).toBe(0);
expect(myfibonacci(5)).toBe(15);
expect(myfibonacci(10)).toBe(55);

There are two strategies I tried to implement this:

(1) the first strategy uses structs

expect = @(actual_value) struct('toBe', @(expected_value) assert(actual_value == expected_value));

(The real implementation will not just call assert)

However this does not work:

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

% this will work:
x = expect(1);
x.toBe(1);

(2) The second strategy I tried is using a class:

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

At first glance this looks fine: You can run in the console

expect(1).toBe(1);

However, running this not in the console but in a script gives

??? 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);

Is here any way to make this idea work in matlab at all?

like image 247
manuels Avatar asked Sep 09 '13 09:09

manuels


2 Answers

In the latest versions of MATLAB (13a/13b) there's a unit testing framework built in that looks very similar to what you're attempting. Instead of

expect(myfibonacci(0)).toBe(0);

you would write

import matlab.unittest.constraints.IsEqualTo
testCase.verifyThat(myfibonacci(0), IsEqualTo(0))

(You could also/instead have assumeThat, assertThat, or fatalAssertThat).

If for some reason you wish to implement your own framework, note the small difference in your syntaxes - you have a dot whereas MathWorks have a comma between myfibonacci(0) and the test condition.

In MATLAB you can't index into the result of a subscripted expression like that (well, you could, but you would have to overload subsref, and that's a world of pain, trust me). So the way they've done it is to introduce the test comparison conditions as a separate package, and apply them as a separate input argument rather than as a method with the dot syntax.

Take a look at the documentation for the new unit testing framework to find out more about either the framework itself, or (if you'd prefer to roll your own) the syntaxes they have designed as a comparison to yours.

like image 192
Sam Roberts Avatar answered Nov 15 '22 11:11

Sam Roberts


Your class definition works fine if you create a function instead of script

So instead of testscript.m containing

expect(myfibonacci(0)).toBe(0);
expect(myfibonacci(5)).toBe(15);
expect(myfibonacci(10)).toBe(55);

you need a function testfunc.m containing

function testfunc
expect(myfibonacci(0)).toBe(0);
expect(myfibonacci(5)).toBe(15);
expect(myfibonacci(10)).toBe(55);
like image 37
Mohsen Nosratinia Avatar answered Nov 15 '22 12:11

Mohsen Nosratinia