function did_pass=cosmo_run_tests(varargin)
% run unit and documentation tests
%
% did_pass=cosmo_run_tests(['verbose',v]['output',fn])
%
% Inputs:
% '-verbose' run with verbose output
% '-logfile',fn store output in a file named fn (optional, if omitted
% output is written to the terminal window)
% 'file.m' run tests in 'file.m'
% '-no_doc_test' skip doctest
% '-no_unit)test' skip unittest
%
% Examples:
% % run tests with defaults
% cosmo_run_tests
%
% % run with non-verbose output
% cosmo_run_tests('verbose',false);
%
% % explicitly set verbose output and store output in file
% cosmo_run_tests('verbose',true,'output','~/mylogfile.txt');
%
% Notes:
% - Doctest functionality was inspired by T. Smith.
% - Unit tests can be run using MOxUnit by N.N. Oosterhof (2015-2017),
% https://github.com/MOxUnit/MOxUnit
% - Documentation tests can be run usxing MOdox by N.N. Oosterhof (2017),
% https://github.com/MOdox/MOdox
%
% # For CoSMoMVPA's copyright information and license terms, #
% # see the COPYING file distributed with CoSMoMVPA. #
orig_pwd=pwd();
pwd_resetter=onCleanup(@()cd(orig_pwd));
[opt,test_locations,moxunit_args]=get_opt(varargin{:});
run_doctest=~opt.no_doc_test;
run_unittest=~opt.no_unit_test;
orig_path=path();
path_resetter=onCleanup(@()path(orig_path));
suite=MOxUnitTestSuite();
if run_doctest
doctest_suite=get_doctest_suite(test_locations);
suite=addFromSuite(suite,doctest_suite);
fprintf('doc test %s\n',str(doctest_suite));
end
if run_unittest
unittest_suite=get_unittest_suite(test_locations);
suite=addFromSuite(suite,unittest_suite);
fprintf('unit test %s\n',str(unittest_suite));
end
did_pass=moxunit_runtests(suite,moxunit_args{:});
function suite=get_doctest_suite(test_locations)
cosmo_check_external({'moxunit','modox'});
suite=MOdoxTestSuite();
suite=add_test_locations(suite,'doc',test_locations);
function suite=get_unittest_suite(test_locations)
cosmo_check_external({'moxunit'});
suite=MOxUnitTestSuite();
suite=add_test_locations(suite,'unit',test_locations);
function suite=add_test_locations(suite,type,test_locations)
if isempty(test_locations)
test_locations={get_default_dir(type)};
prefix=get_default_prefix(type);
else
prefix='';
end
pat=['^' prefix '.*\.m$'];
for k=1:numel(test_locations)
location=test_locations{k};
if isdir(location)
suite=addFromDirectory(suite,location,pat);
else
suite=addFromFile(suite,location);
end
end
function d=get_default_dir(name)
switch name
case 'root'
d=fileparts(fileparts(mfilename('fullpath')));
case 'unit'
d=fullfile(get_default_dir('root'),'tests');
case 'doc'
d=fullfile(get_default_dir('root'),'mvpa');
otherwise
assert(false);
end
function prefix=get_default_prefix(name)
s=struct();
s.unit='test_';
s.doc='cosmo_';
prefix=s.(name);
function [opt,test_locations,moxunit_args]=get_opt(varargin)
defaults=struct();
defaults.no_doc_test=false;
defaults.no_unit_test=false;
opt=defaults;
n_args=numel(varargin);
is_key_value_arg={'-cover',...
'-cover_xml_file',...
'-cover_html_dir',...
'-cover_json_file',...
'-junit_xml_file',...
'-cover_method',...
'-partition_index',...
'-partition_count',...
'-logfile'};
test_locations=cell(n_args,1);
moxunit_args=cell(n_args,1);
k=0;
while k<n_args
k=k+1;
arg=varargin{k};
switch arg
case '-no_doc_test'
opt.no_doc_test=true;
case '-no_unit_test'
opt.no_unit_test=true;
otherwise
is_option=~isempty(regexp(arg,'^-','once'));
if is_option
moxunit_args{k}=arg;
has_value=~isempty(strmatch(arg,is_key_value_arg,'exact'));
if has_value
if k==n_args
error('Missing value after key ''%s''',arg);
end
k=k+1;
arg=varargin{k};
moxunit_args{k}=arg;
end
else
test_locations{k}=get_location(arg);
end
end
end
moxunit_args=remove_empty_from_cell(moxunit_args);
test_locations=remove_empty_from_cell(test_locations);
function ys=remove_empty_from_cell(xs)
keep=~cellfun(@isempty,xs);
ys=xs(keep);
function full_path=get_location(location)
candidate_dirs={'',...
get_default_dir('unit'),...
get_default_dir('doc')};
suffixes={'','.m'};
n_dirs=numel(candidate_dirs);
n_suffixes=numel(suffixes);
for k=1:n_dirs
for j=1:1:n_suffixes
fn=sprintf('%s%s',location,suffixes{j});
full_path=fullfile(candidate_dirs{k},fn);
if exist(location,'file')
return;
end
end
end
error('Unable to find ''%s''',location);