function ts = testcollect(files,recursive)
% TESTCOLLECT Collects tests in a set of testset from files
%
% This function allows to create a complex test set from files and
% directories. The structure of the test set is defined from the directory
% arganization and from the filenames organization.
%
% Params
% ------
% IN:
% files = A string related to an m file, or to a directory, or a
% cell containing strings. (def=pwd)
% recursive = True to introspect recursively listed directories
% (def=true)
% Check for params:
if nargin<1 files=pwd; end
if nargin<2 recursive=true; end
% Get the name:
if isa(files,'char')
[path,name,ext] = fileparts(files);
else
name = 'Main';
end
% The testset can be created with a single call:
ts = CollectTests(files,recursive,name);
% ------------------------ LOCAL FUNCTIONS ------------------------
% Collects tests from a cell of strings:
function ts = CollectTests(files,recursive,name)
% Check if the set of files is reduced to a single filename:
if isa(files,'char')
% Is it a directory?
if isdir(files)
% A directory must be treated a part!
ts = CollectFromDir(files,recursive);
else
% A single file must be managed:
ts = CollectFromFile(files);
end
elseif isa(files,'cell')
% Iteratively collects in a new testset:
tests = cell(1,numel(files));
for ind=1:numel(files)
% A single testset is created:
tests{ind} = CollectTests(files{ind},recursive, ...
sprintf('%s%3.3d',name,ind));
end
% Now a testset can be generated:
ts = testset(name,name,tests);
else
% Cannot be of other types!
error('Cell or filename required for testset collectioning!');
end
% -----------------------------------------------------------------
% Inspect a directory:
function ts = CollectFromDir(dirname,recursive)
% Obtain filenames in the directory:
files = dirfiles(dirname);
% Iterating on files and generating the filenames cell:
c = {};
for ind=1:size(files,2)
% Skipping bad files:
[path,name,ext] = fileparts(files{ind});
if strcmp([name,ext],'.') || strcmp([name,ext],'..') || ...
(not(recursive) && isdir(files{ind})) || ...
not(isdir(files{ind}) || strcmpi(ext,'.m'))
continue;
end
% Collecting:
c = {c{:},files{ind}};
end
% All is collected... now the testset can be generated:
[path,name,ext] = fileparts(dirname);
ts = CollectTests(c,recursive,name);
% -----------------------------------------------------------------
% Inspect a file:
function ts = CollectFromFile(filename)
% To generate a testset from a file a set of informations must be
% collected:
% The name of the test is the filename:
[path,name,ext] = fileparts(filename);
% The file have to exist:
fp = fopen(filename);
if fp<0 error(['Cannot find the file "',filename,'"!']); end
% The first line is read:
L = fgetl(fp);
% The file cannot be empty:
if ~ischar(L) error('Empty tests file!'); end
% If the first line is comment... than it is the description:
if L(1)=='%'
desc = strtrim(L(2:numel(L)));
L = fgetl(fp);
else
desc = '<nodesc>';
end
% Iterating to collect functions:
lnames = {};
ldescs = {};
lfuncs = {};
callSetUp = 0;
callShoutDown = 0;
callReset = 0;
callDone = 0;
while ischar(L)
% Get the index of the word 'function'
pos = regexp(L, '^function\>');
% Check the line to see if this is a function:
if numel(pos)==1 && pos==1
% This is a function, check the name:
pos = regexp(L, '\<MUnitTest_');
if numel(pos)>0
% This is a test, get the name:
lname = L(pos(1):numel(L));
pos = regexp(lname, '\W');
if numel(pos)>0
lname = lname(1:pos(1)-1);
end
pos = findstr(lname, '_');
lname = lname(pos+1:numel(lname));
% The description can be the following line:
L = fgetl(fp);
if isa(L,'char') && L(1)=='%'
ldesc = strtrim(L(2:numel(L)));
L = fgetl(fp);
else
ldesc = '<nodesc>';
end
% Generating the function name:
lfunc = ['MUnitTest_',lname];
% Collecting:
lnames = {lnames{:},lname};
ldescs = {ldescs{:},ldesc};
lfuncs = {lfuncs{:},lfunc};
% Skip the line read:
continue;
elseif numel(regexp(L, '\<MUnitSetUp\>'))>0
% Memorize the function name:
callSetUp = 'MUnitSetUp';
elseif numel(regexp(L, '\<MUnitShoutDown\>'))>0
% Memorize the function name:
callShoutDown = 'MUnitShoutDown';
elseif numel(regexp(L, '\<MUnitReset\>'))>0
% Memorize the function name:
callReset = 'MUnitReset';
elseif numel(regexp(L, '\<MUnitDone\>'))>0
% Memorize the function name:
callDone = 'MUnitDone';
end
end
% Another line is read:
L = fgetl(fp);
end
% Close the file:
fclose(fp);
% At least a single test is required:
if numel(lnames)==0
error('At least a test function is required!');
end
% Generating the function handlers:
[path,testfunc,ext] = fileparts(filename);
% Generating tests callbacks:
if isa(callReset,'char')
% Generating the handler:
eval(['callReset = ',testfunc,'(callReset);']);
end
if isa(callDone,'char')
% Generating the handler:
eval(['callDone = ',testfunc,'(callDone);']);
end
% Generating tests:
tests = cell(1,numel(lnames));
for ind=1:numel(tests)
% Creating the test:
eval(['lfunc = ',testfunc,'(lfuncs{ind});']);
tests{ind} = testunit(lfunc,{},lnames{ind},ldescs{ind});
% Adding the callbacks:
if isa(callReset,'function_handle')
tests{ind} = addCallback(tests{ind},callReset,1);
end
if isa(callDone,'function_handle')
tests{ind} = addCallback(tests{ind},callDone,2);
end
end
% Generating the testset:
ts = testset(name,desc,tests);
% Generating the callbacks:
if isa(callSetUp,'char')
% Adding the callback:
eval(['callSetUp = ',testfunc,'(callSetUp);']);
ts = addCallback(ts,callSetUp,3);
end
if isa(callShoutDown,'char')
% Adding the callback:
eval(['callShoutDown = ',testfunc,'(callShoutDown);']);
ts = addCallback(ts,callShoutDown,4);
end