Awesome
MP-Test
MP-Test is a set of functions for implementing unit testing in MATLAB or
GNU Octave. It was initially developed for MATPOWER, and is used by
MATPOWER, MATPOWER Interior Point Solver (MIPS), MP-Opt-Model
and MATPOWER Optimal Scheduling Tool (MOST). It also includes a
function have_feature
for detecting support for optional functionality.
Installation
Note to MATPOWER users: MP-Test is included when you install MATPOWER. There is generally no need to install it separately. You can skip directly to step 3 to verify.
Installation and use of MP-Test requires familiarity with the basic operation of MATLAB or Octave, including setting up your MATLAB/Octave path.
-
Clone the repository or download and extract the zip file of the MP-Test distribution from the MP-Test project page to the location of your choice. The files in the resulting
mptest
ormptestXXX
directory, whereXXX
depends on the version of MP-Test, should not need to be modified, so it is recommended that they be kept separate from your own code. We will use<MPTEST>
to denote the path to this directory. -
Add the following directories to your MATLAB/Octave path:
<MPTEST>/lib
<MPTEST>/lib/t
-
At the MATLAB/Octave prompt, type
test_mptest
to run the test suite and verify that MP-Test is properly installed and functioning. The result should resemble the following:
>> test_mptest
t_test_fcns.......ok
t_have_feature....ok
All tests successful (29 of 29)
Elapsed time 0.14 seconds.
Usage
- Write test functions of the following form, where
t_ok
,t_is
,t_str_match
, andt_file_match
are used to test for specific conditions or matches.
function mptest_ex1(quiet)
if nargin < 1
quiet = 0;
end
t_begin(4, quiet);
t_ok(pi > 3, 'size of pi');
if have_feature('octave')
t_ok(1, 'Octave-only test foo');
t_ok(1, 'Octave-only test bar');
else
t_skip(2, 'foo and bar tests require Octave');
end
t_is(2+2, 4, 12, '2+2 still equals 4');
t_end;
- Then run your test function:
>> mptest_ex1
1..4
ok 1 - size of pi
skipped 2..3 - foo and bar tests require Octave
ok 4 - 2+2 still equals 4
All tests successful (2 passed, 2 skipped of 4)
Elapsed time 0.00 seconds.
- If you have several test functions, create a function to run them all as follows:
function test_everything_ex1(verbose)
if nargin < 1
verbose = 0;
end
tests = {};
tests{end+1} = 'mptest_ex1';
tests{end+1} = 't_test_fcns';
t_run_tests( tests, verbose );
- Run all of your tests at once. The output may look something like:
>> test_everything_ex1
mptest_ex1.....ok (2 of 4 skipped)
t_test_fcns....ok
All tests successful (7 passed, 2 skipped of 9)
Elapsed time 0.06 seconds.
Documentation
The primary sources of documentation for MP-Test are this section of
this README file and the built-in help
command. As with the built-in
functions and toolbox routines in MATLAB and Octave, you can type help
followed by the name of a command or M-file to get help on that
particular function.
Testing Functions
-
t_begin — begin running tests
t_begin(num_of_tests, quiet)
Initializes the global test counters, setting everything up to execute
num_of_tests
tests usingt_ok
andt_is
. Ifquiet
is true, it will not print anything for the individual tests, only a summary whent_end
is called. -
t_end — finish running tests and print statistics
t_end
Checks the global counters that were updated by calls to
t_ok
,t_is
andt_skip
and prints out a summary of the test results. -
t_ok — test whether a condition is true
ok = t_ok(expr, msg)
Increments the global test count and if the
expr
is true it increments the passed tests count, otherwise increments the failed tests count. Prints'ok'
or'not ok'
followed by themsg
, unlesst_begin
was called with inputquiet
equal true. Intended to be called between calls tot_begin
andt_end
. -
t_is — test if two (scalar, vector, matrix) values are identical, to some tolerance
ok = t_is(got, expected, prec, msg)
Increments the global test count and if the maximum difference between corresponding elements of
got
andexpected
is less than 10^(-prec
) then it increments the passed tests count, otherwise increments the failed tests count. Prints'ok'
or'not ok'
followed by themsg
, unlesst_begin
was called with inputquiet
equal true. The input values can be real or complex, and they can be scalar, vector, or 2-d or higher matrices. Ifgot
is a vector or matrix andexpected
is a scalar orNaN
, all elements must match the scalar. Intended to be called between calls tot_begin
andt_end
.Optionally returns a true or false value indicating whether or not the test succeeded.
NaN
values are considered to be equal to each other. -
t_str_match — test if two strings match, with optional replacements
ok = t_str_match(got, expected, msg) ok = t_str_match(got, expected, msg, reps)
This is equivalent to
t_ok(strcmp(got, expected), msg)
, with the option to apply replacements togot
, and optionally toexpected
, as specified byreps
before comparing.The
reps
argument is a cell array of replacement specs, applied sequentially, where each replacement spec is a cell array of the following form:
{original, replacement}
{original, replacement, re}
{original, replacement, re, both}
Theoriginal
andreplacement
arguments are passed directly as the 2nd and 3rd arguments toregexprep
(or tostrrep
ifre
is present and false). The replacement applies togot
only, unlessboth
is present and true, in which case it also applies toexpected
. -
t_file_match — test if the contents of two text files match
ok = t_file_match(got_fname, exp_fname, msg) ok = t_file_match(got_fname, exp_fname, msg, reps) ok = t_file_match(got_fname, exp_fname, msg, reps, del_got_fname)
Uses
t_str_match()
on the contents of two text files whose names/paths are given ingot_fname
andexp_fname
. If both files exist and the contents match, the test passes.It ignores any differences in line ending characters and, like
t_str_match()
, can apply replacements to the contents ofgot_fname
, and optionallyexp_fname
, as specified byreps
before comparing.See t_str_match above for a description of the
reps
argument.If
del_got_fname
is present and true it will delete the file named ingot_fname
if the test passes. -
t_skip — skip a number of tests
t_skip(cnt, msg)
Increments the global test count and skipped tests count. Prints
'skipped x..y : '
followed by themsg
, unlesst_begin
was called with inputquiet
equal true. Intended to be called between calls tot_begin
andt_end
. -
t_run_tests — run a series of tests
all_ok = t_run_tests(test_names, verbose)
Runs a set of tests whose names are given in the cell array
test_names
. If the optional parameterverbose
is true, it prints the details of the individual tests. Optionally returns anall_ok
flag, equal to 1 if all tests pass (and the number matches the expected number), 0 otherwise.
Other Functions
-
have_feature — test for optional functionality, with version information
TorF = have_feature(tag) TorF = have_feature(tag, toggle) ver_str = have_feature(tag, 'vstr') ver_num = have_feature(tag, 'vnum') date = have_feature(tag, 'date') info = have_feature(tag, 'all') have_feature(tag, 'clear_cache') have_feature('all', 'clear_cache')
Returns the availability, version and release information for optional functionality. All information is cached, and the cached values returned on subsequent calls. If the functionality exists, an attempt is made to determine the release date and version number. The second argument defines which value is returned, as follows:
''
,'av'
or <none> — 1 = optional functionality is available, 0 = not available'vstr'
— version number as a string (e.g.'3.11.4'
)'vnum'
— version number as numeric value (e.g. 3.011004)'date'
— release date as a string (e.g.'21-Sep-2020'
)'all'
— struct with fields named'av'
(for "availability"),'vstr'
,'vnum'
and'date'
, and values corresponding to the above, respectively.
For functionality that is not available, all calls with a string-valued second argument (except
''
or'av'
) will return an empty value.Alternatively, the availability status of the optional functionality specified by
tag
can be toggled OFF or ON by callinghave_feature
with a numeric second argumenttoggle
with one of the following values:- 0 — turn OFF availability of the optional functionality
- 1 — turn ON availability of the optional functionality (if available)
- -1 — toggle the ON/OFF availability state of the optional functionality
Note that this affects only the availability status returned by
have_feature
and nothing else.Finally, passing
'clear_cache'
as the second argument will cause the cached information to be cleared for the specifiedtag
or, if the first argument is'all'
, for all optional functionality. When calling with'clear_cache'
no return value is defined.Example:
if have_feature('matlab') disp(['Running MATLAB version ', have_feature('matlab', 'vstr')]) else disp(['Running Octave version ', have_feature('octave', 'vstr')]) end
-
mptestver — prints or returns MP-Test version info
v = mptestver v = mptestver('all')
Returns the current MP-Test version numbers. If called with an argument, returns a struct with the fields
Name
,Version
,Release
andDate
(all char arrays). Callingmptestver
without assigning the return value prints the version and release date of the current installation of MP-Test.
Private Functions
The following are private functions that implement detection of specific
optional functionality. They are not intended to be called directly, but
rather are used to extend the capabilities of have_feature
(see above).
-
have_feature_matlab — feature detection function for MATLAB
This function implements the
'matlab'
tag forhave_feature
to detect whether the code is running under MATLAB. -
have_feature_octave — feature detection function for GNU Octave
This function implements the
'octave'
tag forhave_feature
to detect whether the code is running under GNU Octave.
Contributing
Please see our contributing guidelines for details on how to contribute to the project or report issues.
License
MP-Test is distributed under the 3-clause BSD license.
Acknowledgments
This material is based upon work supported in part by the Consortium for Electric Reliability Technology Solutions (CERTS) and the Office of Electricity Delivery and Energy Reliability, Transmission Reliability Program of the U.S. Department of Energy under the National Energy Technology Laboratory Cooperative Agreement No. DE-FC26-09NT43321 and by the National Science Foundation under Grant Nos. 0532744, 1642341 and 1931421. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the funding agencies.