How to make internal/helper functions testable? - matlab

Suppose that I have some function Foo that uses two internal helper functions bar and baz.
Is there a way to organize the code so that bar and baz remain "out of sight", but at the same time can be unit-tested? (Preferably, the unit tests for bar and baz would be in the same suite as the unit tests for the main function Foo.)

There are a few options to achieve this.
First, does Foo need to be a function? If it is a class then you can implement bar and baz as Hidden and Access='protected' which is pretty tightly locked down. Then you can create a test specific subclass that accesses bar and baz for testing. You can also scope the access to the test to further lock it from others view if desired.
If you do want Foo to be a function then you still have options. One of those is to somehow get a function handle to the private local functions to your tests. You can do this through some special calling syntax of Foo that returns these functions to a test when called. This however, modifies the production code in a potentially confusing way, and it essentially inserts test logic into production. I would prefer hiding these functions by putting them into a package so that they are not in the global namespace. The name of the package can indicate that they are off limits and not part of your supported interface.
Finally, one option is to simply use the public interface in order to test these functions. Clearly they are called from the function in some scenario. You may want to consider writing a test through the front door of your interface. One benefit of this is that you would then be able to change the implementation of your local function structure easily without modifying your test. The private functions are private because by definition they are part of your implementation, not your interface. If you find it complex enough to require its own test independent from the interface of Foo then it should probably just be broken out into another package function or class as described above in order to unit test it.

Not the most elegant way to do it but then Matlab is not the most practical language to build modules in a single code file.
One way to do it is to have a higher level level function which transfer the input arguments to the function you choose:
function out = fooModule( FunctionCalled , varargin)
%// This main function only transfer the input argument to the function chosen
switch FunctionCalled
case 'main'
out = foo(varargin) ;
case 'bar'
out = mBar(varargin) ;
case 'baz'
out = mBaz(varargin) ;
end
end
function outFoo = foo(varargin)
%// your main FOO code
%// which can call the helper function if necessary
end
function outbar = mBar(varargin)
%// your code
end
function outbaz = mBaz(varargin)
%// your code
end
You can even embed the FunctionCalled parameter into varargin if you want to compact things. This would also allow to test the type of the first argument. So for example if the first argument is not a string (calling one of the helper function) then forward the execution directly to the main foo function without having to call it explicitly (so the helper functions remain 'out of sight' if not called explicitly).
Otherwise, a completely different approach, you could consider writing a class.

Related

MATLAB set class `size` (overload operation upon class)

classdef Dog
end
d=Dog(); can size(d) be controlled? Is there some property to set or method to overload?
Ultimately I have like d.data = [1, 2, 3] and want length(d) == 3. I'm aware I can make d.length(). As an aside, is there a list of MATLAB "magic methods", i.e. functions that control interaction with classes, like subsref?
In MATLAB, don't think of class method as similar to class methods in other languages. Really, what they are is overloaded versions of a function.
size(d) is the same as d.size() (which is the same as d.size, parentheses are not needed to call a function), if d is an object of a custom class and size is overloaded for that class.
So, you can define function size in the methods section of your classdef, to overload size for your class. You can also create a size.m file within a #Dog/ directory to accomplish the same thing.
For example, if you create a file #char/size.m with a function definition inside, you will have overloaded size for char arrays.
The above is true for any function. Some functions, when overloaded, can cause headaches. For example be careful when overloading numel, as it could cause indexed assignment expressions to fail. size is used by the whos command to display variable information, as well as by the similar functionality in the GUI, so it is important to have it behave in the expected way.
The object behavior that you might want to change that is not obviously a function, relates to operators. Each operator is also defined by a function (including end in indexing!). See the docs for a full list.

How to get the calling subclass' name in a superclass' static function?

Suppose we have
Check.m:
classdef Check < handle
methods (Static)
function doStuff()
if isCalledFromAssertSubclass
% do this stuff only if called as Assert.doStuff(), not if called as Check.doStuff()
end
% do other stuff
end
end
end
and Assert.m:
classdef Assert < Check
% nop
end
As written in the comment, I would like to have that Check.doStuff() executes only the "do other stuff" line and that Assert.doStuff() executes the if isCalledFromAssertSubclass block as well.
I want to use static methods, so that I don't neet to create an Assert object whenever I need an assert. Using a global assert object is also very ugly and needs a global assert line in each function I want to use an assert. Likewise for checks.
So there are two problems:
Since these are static classes, there is no chance of using class(obj) or any other non-static class property or function.
dbstack is not inheritance aware and always returns Check as calling class, also for Assert.doStuff.
I did find a working solution, which uses a combination of dbstack and dbtype to read the line where the call came from, i.e. the line where it says Assert.doStuff(). However it involves two debug functions which probably should not be used in productive code and more importent, dbtype is very slow (in my case, 30 our of 70 seconds!).
I could use a package instead (directory +Check with function files in there) and create a symlink +Assert -> +Check. Then I could check the file name, but that's a) not portable, b) quite ugly and c) also somewhat slow (I suppose).
Is there any faster method for this?
Why not overload the static method for Assert, and have it call the parent's method when it's done? This is the normal way of using inheritance: you don't want the parent, Check, to know anything about its child, Assert.
This is what it would look like:
classdef Assert < Check
methods (Static)
function doStuff()
% do some stuff
Check.doStuff()
end
end
end
As #Wolfie suggests in a comment, the above works as long as Check.doStuff is not sealed. A sealed method cannot be overloaded. See the documentation.

define help for variable in Matlab

In Matlab, it is easy to generate "help" for a function, as follows.
function out = foo()
% helpful information about foo
end
When we execute help foo, we get "helpful information about foo".
However, suppose we would like to define help for a variable, probably as a definition. How could we do such a thing? It would be nice if we could do something like
x = 3; % m ... position
help x
and get "m ... position". However, I don't believe such functionality exists.
The only reasonable way I see around this is to define every variable as a struct with keys value and description.
x.value = 3;
x.description = 'm/s ... position';
This requires we define every variable as a struct, which is kind of annoying and, I worry (should I?), unperformant (it's simulation code and these variables are accessed repeatedly).
Is there another solution I'm not considering? Should I be worried about making every variable a struct?
Your code should be self-documenting. Instead of variable name x, use position.
Furthermore, all variables should be local, so you can easily look for its definition (with comment) within the function you are editing.
Variables declared further away (with larger scope within the function) should have longer, more self-explanatory names than variables with a smaller scope (e.g. use within a short loop.
There are only two three cases where variables are declared outside the function’s scope:
Class properties. You can actually document these.
In a script, you have access to variables that already existed before the script started. A good reason not to use scripts or depend on the base namespace in larger projects.
Global variables. You should never use global variables for many reasons. Just don’t.

MATLAB: Script with all my functions

Maybe it's a basic question but here I go. I would like to have a .m with all the functions that will be accessed by other scripts and functions.
I tried just doing a script with all the functions and call it in other functions code.
And I got and error. Could you please explain me how can I solve this?
I'm trying this, which gives me no error, and does what I want it to do, still, is it a good way to do it? Any suggestions?
function PruebasLlamaFuncion
funcionFEM=#PruebasTodasFunciones;
a=funcionFEM('OVERPOWER',1,5)
b=funcionFEM('POWEROVERWELMING',2)
end
...
function a=f(nombre,varargin)
f=str2func(nombre)
a=f(varargin{1:end});
end
function d=OVERPOWER(J,c)
d=J*c;
end
function e=POWEROVERWELMING(J)
e=J;
end
Function placement
Matlab, unlike a number of other languages, permits a single file to contain only one main function that is visible to the rest of the system. The main function is the first function. (Documentation)
Any functions that are defined after the main function body are called local functions. These functions each create their own separate workspace (scope) and can be called by one another and, of course, by the main function.
Any functions that are defined within the main function body are called nested functions. These functions have their own workspace but are also able to access and change the variables of their parent function under certain conditions. Nested functions at the same nesting level can call each other and local functions, but local functions cannot call nested functions since they are out of scope.
Workarounds
There are several options available to you depending on how you would like to proceed.
At the risk of giving too many options but desiring to be exhaustive, I'll put the list from what I would do first to what I would do last.
For most things, I would recommend 1 or 2.
The other options are more for creating libraries/APIs, but I included them to show what can be done.
Define Function1 and Function2 in separate m-files on the Matlab path or in the present working directory to call them normally.
Wrap the main body of your work (the one calling the functions) in a function itself and define the other functions as local functions or nested functions. Example:
function output = main(a,b,c)
Result=Function1(a,b,c);
Result2=Function2(b,d);
...
% You can define Function1 and Function2 here for nested functions
end
% Or you can define Function1 and Function2 here for local functions
You can get a bit more fancy and have a function that returns function handles (pointers) to the local or nested functions and then use the (in the example) struct to call the functions in another script:
function Functions = GetFunctions()
Functions.F1 = #(a,b,c) Function1(a,b,c);
Functions.F2 = #(a,b) Function2(a,b);
% You can define Function1 and Function2 here for nested functions
end
% Or you can define Function1 and Function2 here for local functions
If you have R2013b or above, you can do the same thing as above using the localfunctions function to create a cell array of handles to all local functions (in this case, the definitions are required to be outside the main function body).
function Functions = GetFunctions()
Functions = localfunctions(); % R2013b+ only
end
% Define Function1 and Function2 here for local functions
You can also create a class with static functions:
classdef Functions
methods(Static)
% Define Function1 and Function2 here and call them just like the struct above.
end
end
I hope that makes sense and hopefully helps.
I think you're misunderstanding something. A script is for calling a series of functions/other scripts in sequence. If you just want your functions to be accessible in other code, you only need to make sure they're on the path. You would never need a "script containing all the functions". You may be thinking of local functions, but these are the exact opposite of what you want (they can't be called from outside the function where they're defined or other local functions in the same file).
e.g. if Function1 and Function2 are on your path, you could write a script like this, perhaps as a demo for how to use those two functions:
a = 0;
b = 1;
c = 2;
d = 'Unicorns';
Result=Function1(a,b,c);
Result2=Function2(b,d);
It does not and should not have any function definitions in it. If your script can't find the functions, use addpath (see docs), to put the folder where these function files reside into your path. The m files should be given the same name, e.g. the following needs to go in a file called myfunc.m
function result = myfunc(a,b,c)
Functions in your working directory can also be called even if that directory isn't on your path.

Is self-reference possible in MATLAB?

As noted here, functions in packages, as well as static methods in classes, still need to use a packagename.functionname syntax or import packagename.* for each function (since the imports are part of the function workspace and not global). This means that changing the package/class name later on can become a tedious nuisance.
Is there any way to do something like import this.*, i.e. a package/class name agnostic method to access all functions/static methods in the same package/class?
So... doesn't this require importthis to also be imported? Or is importthis a function you always have in your path?
It seems hardly more complex to just paste an "import this" block with this at the top of each function, and then you don't have to worry about importthis being in your path. I tend to feel that reliance on path is dangerous.
"Import This" block
%% Import own package
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end) '.*']);
You can even put it in a try/catch block to make sure it's in a package directory, and decide what to do if it's not.
%% Import own package
try
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end)'.*']);
catch err
if ~strcmp(err.identifier,'MATLAB:UndefinedFunction'), rethrow(err); end
end
I recently ran into a similar problem and found the following solution for packages. However it is VERY hacky.
You create a function called import this with an optional argument.
function to_eval = importthis(exclude_list)
if nargin == 0
exclude_list = [];
end
var_name = genvarname('A', exclude_list); %avoid shadowing
to_eval = ['[~,'...
, var_name...
, ']=fileparts(fileparts(mfilename(''fullpath'')));'... %get containing dir
, 'eval([''import '','...
, var_name...
, '(2:end),''.*'']);'... %remove '+'
, 'clear '... %clean up
, var_name
];
end
This function returns a string which can then be evaled that imports the "this" package. So in your package functions you would put the following near the top:
function B = myfunc(A)
eval(importthis);
%function body
end
You can also pass who to importhis, leaving your function's namespace clean.
function B = myfunc(A)
eval(importthis(who));
%function body
end
I can't decide whether I should feel proud or discusted by what I did.
This probably is not a bounty worthy answer but as you do not have any answers I thought I would post it anyway! You can invoke static methods via an instance of the class which you would only need to define once. You can invoke functions via a function handle but this would require one handle per function.
Using these techniques you could define all your static method and function references in one place. Then you would use these references throughout your package. Then if you decided to change the package name at a later point you would only need to update these references which are all stored in one place.
See:
Calling Static Methods
You can also invoke static methods using an instance of the class,
like any method:
obj = MyClass;
value = obj.pi(.001);
function_handle (#)
The following example creates a function handle for the humps function
and assigns it to the variable fhandle.
fhandle = #humps;