As a follow up to my previous question, I run into a new obstacle: how to generate stubs for functions in a toolbox?
I found Andy Campbell's solution for the non toolbox case. This does not work in my case because Matlab complains: package directories are not allowed in MATLAB path in Pathfixtures!
I also don't see how this concept will overwrite the import statements within the toolbox, e.g. in file2.
This is my setup:
+folder1/file1.m
+folder1/runtestsuite.m
+folder1/unittest_data/file1_testdata.mat
+folder1/+folder2/file2.m
+folder1/+folder2/unittest_data/overloads/file1.m
...
Let's say I want to stub file1 in file2. And file2 has as a first statement: import folder1.file1.
With
methods(Access=private)
function inject_file1_stub(testCase, answer)
import matlab.unittest.fixtures.PathFixture;
testCase.applyFixture(PathFixture(fullfile(testCase.path,'overloads')));
file1('', answer);
end
end
So currently I believe this concept is not applicable in my case, so how is this done correctly with matlab?
I know one can shadow an implementation of a function in a toolbox, if one adds another path with the same toolboxname and function to the path. For this I would have to recreate a subset of the current folder setup:
So my current idea for a fixture is
create temporary folder with tempdir
use mfilename to check what subset of the toolbox directories I have to recreate
generate folder structure
copy from the overload folder to the new toolbox system
Add this to path
Run tests
In teardown
remove the temporary folder
remove the entry from path
I have not implemented this yet, and seems a bit redundant knowing that there is a Pathfixture in matlab already.
Pointers to other toolboxes which show how they have solved these kind of problems are also welcome.
It is true that you can't add subfolders of packages to the path, but that doesn't mean you can't shadow these path functions. To do this you need to separate the test related content out of your source location. For example, if your source looks like:
<source-home>/+folder1/file1.m
<source-home>/+folder1/+folder2/file2.m
Then you can put your tests somewhere else so your structure would look something like:
<test-home>/file1Test.m
<test-home>/file2Test.m % could also put tests into packages if you want
<test-home>/overloads/+folder1/file1.m
<test-home>/overloads/+folder1/+folder2/file2.m
Then inside of file1Test and/or file2Test you would use a PathFixture to add:
<test-home>/overloads/
to the path.
Also, another thing to consider is defining an interface in your source code for these dependencies and leveraging dependency injection (with or without a DI framework) in order to get test specific behavior into your tests.
Related
I would like to use two versions of the same Matlab software package at the same time (I would like to compare their outputs for testing). The package modifies the path so that functions in subdirectories can be found. This seems problematic since the package assumes that it is the only copy running on the machine. The path is essentially a global variable which is unintentionally shared between the two copies of the code.
Example simplified code structure:
/main_code.m
/compare_results.m
/code_a/somefn.m
/code_a/submethods/
/code_b/somefn.m
/code_b/submethods/
Note that somefn.m adds the submethods directory to the path, and calls code from the submethods folder by relying on the path.
Example of code that I would like to run:
for i = 1:1000000
% Run version A:
result_a = code_a.somefn(i);
% Run version B:
result_b = code_b.somefn(i);
% Compare the output from the two versions:
compare_results(a,b);
end
One solution that I can think of is to manually update the Matlab path every time that I want to switch to a different version of the package. This seems like unnecessary coding overhead, and potentially a performance problem (due to switching the path so often).
Another solution might be to rewrite the code to be object oriented, so that the functions are attached to objects, and I can create objects of different versions. The problem with this is that in reality the code package contains hundreds of files, and I was not the original author so rewriting would be a huge task .
(Yet another option would be to change directory all the time, so that the code to run is always in the current directory. This would be so much of a headache due to the number of subfolders that I do not think this is a serious solution. It also has potential performance overhead drawbacks similar to always changing the path.)
Is there a cleaner way to handle this? Can I somehow specify the folder of the code that I want to run? What is the best way to design such a code package so that this problem does not come up?
Just create packages, which can contain functions with the same names: Packages Create Namespaces
Basically create two folders named, say, +package1 and +package2. The "+" in the folder name is important. Then place your functions under both of them, say, foo.m. Then, you can call each separately without messing with MATLAB path as:
>> package1.foo
>> package2.foo
You can use private functions. Change the directory structure as:
/main_code.m
/compare_results.m
/+code_a/somefn.m
/+code_a/private/
/+code_b/somefn.m
/+code_b/private/
Each somefn has access to the functions contained in its private sub-folder. So there is no need to create global variable and to add private sub-folders to the path.
Let us assume, I want to use a foreign Matlab library with a structure like this:
folderName
play.m
run.m
open.m
If I simply add folderName to my Matlab path variable, it will easily yield name conflicts. I don't want to rename the files, to be able to obtain new releases of the example library (the package concept is not used in the example library). Renaming would need to modify the code as well, if there are calls from one library function to the other.
How do I write local wrappers, which wrap the functions from that example library? My wrappers could then have my desired names and input parameters.
Clarification: How do I use an external library (toolbox) without name conflicts, without renaming and without modifying each function?
Rename files: Makes it hard to update the external library.
Simply put them in a package folder: This will break internal library function calls.
You want to use a package, which will establish a namespace, such that things in the package, are then qualified with the package name. You can find more information here: http://www.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html
I have a Simulink model, the purpose of which is automated code generation.
My model uses S-functions (developed by another party), which has hard-coded assumptions about the path. For instance, several external data files are needed, which are referenced in the S-function via a relative path like ..\Bin\data\datafile.bin. This makes it necessary to set MATLAB's current working directory to a specific path before the model can be run.
I can automatically check and set the correct path via model callback functions. However, all model callback functions only seem to be related to the simulation process, not the build process. That means that I can run the model irrespective of what directory I'm in, but when I try to build the model, it always fails unless I manually navigate MATLAB back to the correct directory.
Needless to say, that's quite annoying. So I was wondering if there is something like a "preBuildFcn" callback fnuction, a function that is run before starting the build process? Any other solution (that does not involve modifying the S-function) is also very welcome.
There are plenty of hooks into the build process of Simulink / Embedded Coder ('entry', 'before_tlc', 'after_tlc', 'before_make', 'after_make', 'exit', and 'error'). I assume you want an 'entry' hook.
All you need to do is write an M-function with the name your_system_target_file name_make_rtw_hook, as explained in the documentation Customize Build Process with STF_make_rtw_hook File.
In case you can't open the online documentation (login required), here is the path to the HTML in your MATLAB installation: MATLAB root\help\rtw\ug\customizing-the-target-build-process-with-the-stf-make-rtw-hook-file.html
I am not sure whether building simulink models is sufficiently similar to building regular MATLAB programs, but here is what I used in the past:
Set up the project manually
Build the project programmatically
The program that is used to build the project should be able to set the path or do other custom things.
I have created a small Modelica library of my own. The way I have created it is in a single file. But I would like to make it a proper Modelica Library, as in the one with multiple directories for each subpackages.
So this is what i followed. File > New Modelica Class > Specialization - Package > Unchecked Save contents in one file. I copied the entire package code from the single file library, pasted it here and saved it. while doing so, I've noticed that the library lost most of its extends clauses, few models went missing.
Have I followed the correct procedure to create the library or did I do something wrong?
Can anyone point me towards the right direction?
#MSK, I cannot help you with OpenModelica as I work with Dymola. I did however recently split a single-file library (called package in Modelica) into several files manually. I did this so that the library hierarchy is represented in the file system hierarchy (i.e. several subfolders and .mo files in a library folder). For 35,000 lines of code this took roughly 10 hours. Just follow these steps:
create folder with same name as library
in this folder, create a text file "package.mo"
"package.mo" has to start with the statement
within ;
package [name of your package, i.e. the folder name...without the brackets];
now you want to create a subclass within this package. To do this create another folder containing a text file called "package.mo"
start this "package.mo" with
within [name of your package];
and declare the model as usual.
continue all the way down your library hierarchy
at the lowest hierarchy level you no longer need to create folders. You can simply create a .mo with the name of the lowest level class. As usual, start this file with
within [name of your package].[subclass1].[subclass2];
For an example of implementation please refer to the Physiolibrary found at https://www.modelica.org/libraries or the Modelica Standard Library which also uses this structure.
We have a lot of MATLAB code in my lab. The problem is there's really no way to organize it. Since all the functions have to be in the same folder to be called (or you have to add a bunch of folders to MATLAB's path environment variable), it seems that we're doomed have loads of files in the same folder, all in the global namespace. Is there a better way to organize our files and functions? I really wish there were some sort of module system...
MATLAB has a notion of packages which can be nested and include both classes and functions.
Just make a directory somewhere on your path with a + as the first character, like +mypkg. Then, if there is a class or function in that directory, it may be referred to as mypkg.mything. You can also import from a package using import mypkg.mysubpkg.*.
The one main gotcha about moving a bunch of functions into a package is that functions and classes do not automatically import the package they live in. This means that if you have a bunch of functions in different m-files that call each other, you may have to spend a while dropping imports in or qualifying function calls. Don't forget to put imports into subfunctions that call out as well. More info:
http://www.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html
I don't see the problem with having to add some folder to Matlab's search path. I have modified startup.m so that it recursively looks for directories in my Matlab startup directory, and adds them to the path (it also runs svn update on everything). This way, if I change the directory structure, Matlab is still going to see all the functions the next time I start it.
Otherwise, you can look into object-oriented code, where you store all the methods in a #objectName folder. However, this may lead to a lot of re-writing code that can be avoided by updating the path (there is even a button add with subfolders if you add the folder to the path from the File menu) and doing a bit of moving code.
EDIT
If you would like to organize your code so that some functions are only visible to the functions that call them directly (and if you don't want to re-write in OOP), you put the calling functions in a directory, and within this directory, you create a subdirectory called private. The functions in there will only be visible to the functions in the parent directory. This is very useful if you have to overload some built-in Matlab functions for a subset of your code.
Another way to organize & reuse code is using matlab's object-oriented features. Each Object is customarily in a folder that begins with an "#" and has the file(s) for that class inside. (though the newer syntax does not require this for a class defined in a single file.) Using private folders inside class folders, matlab even supports private class members. Matlab's new class notation is relatively fully-featured, but even the old syntax is useful.
BTW, my startup.m that examines a well-known location that I do my SVN checkouts into, and adds all of the subfolders onto my path automatically.
The package system is probably the best. I use the class system (#ClassName folder), but I actually write objects. If you're not doing that, it's silly just to write a bunch of static methods. One thing that can be helpful is to put all your matlab code into a folder that isn't on the matlab path. Then you can selectively add just the code you need to the path.
So say you have two projects, stored in "c:\matlabcode\foo" and "c"\matlabcode\bar", that both use common code stored in "c:\matlabcode\common," you might have a function "setupPaths.m" like this:
function setupPaths(projectName)
basedir = fullfile('c:', 'matlabcode');
addpath(genpath(fullfile(basedir, projectName)));
switch (projectName)
case {'foo', 'bar'}
addpath(genpath(fullfile(basedir, 'common')));
end
Of course you could extend this. An obvious extension would be to include a text file in each directory saying what other directories should be added to the path to use the functions in that directory.
Another useful thing if you share code is to set up a "user specific/LabMember" directory structure, where you have different lab members save code they are working on. That way you have access to their code if you need it, but don't get clobbered when they write a function with the same name as one of yours.