Files
imdd_silas/Tests/generateTests.m
2026-03-24 17:23:02 +01:00

124 lines
3.7 KiB
Matlab

function summary = generateTests(options)
%GENERATETESTS Generate placeholder tests for class files without tests.
arguments
options.force (1, 1) logical = false
options.verbose (1, 1) logical = true
end
testsRoot = fileparts(mfilename('fullpath'));
repoRoot = fileparts(testsRoot);
classesRoot = fullfile(repoRoot, 'Classes');
classFiles = collectMFiles(classesRoot);
classInfos = struct('className', {}, 'relativeDir', {}, 'classFile', {});
baseNameCounts = containers.Map('KeyType', 'char', 'ValueType', 'double');
for idx = 1:numel(classFiles)
classFile = fullfile(classFiles(idx).folder, classFiles(idx).name);
if ~isClassFile(classFile)
continue
end
[relativeDir, className] = relativeClassInfo(classFile, classesRoot);
classInfos(end + 1) = struct( ... %#ok<AGROW>
'className', className, ...
'relativeDir', relativeDir, ...
'classFile', classFile);
key = lower(className);
if isKey(baseNameCounts, key)
baseNameCounts(key) = baseNameCounts(key) + 1;
else
baseNameCounts(key) = 1;
end
end
generated = 0;
skippedExisting = 0;
for idx = 1:numel(classInfos)
info = classInfos(idx);
key = lower(info.className);
testClassName = buildTestClassName( ...
info.className, info.relativeDir, baseNameCounts(key) > 1);
testDir = fullfile(testsRoot, info.relativeDir);
testFile = fullfile(testDir, [testClassName, '.m']);
if ~options.force
if isfile(testFile)
skippedExisting = skippedExisting + 1;
continue
end
end
if ~isfolder(testDir)
mkdir(testDir);
end
createTestFile(testClassName, info.className, info.classFile, testFile);
generated = generated + 1;
end
summary = struct( ...
'generated', generated, ...
'skippedExisting', skippedExisting, ...
'classCount', numel(classInfos));
if options.verbose
fprintf(['Generated %d placeholder tests, skipped %d existing tests, ', ...
'tracked %d class files.\n'], ...
summary.generated, summary.skippedExisting, summary.classCount);
end
end
function tf = isClassFile(filePath)
source = fileread(filePath);
tf = contains(source, 'classdef');
end
function [relativeDir, className] = relativeClassInfo(classFile, classesRoot)
relativePath = strrep(classFile, [classesRoot, filesep], '');
[relativeDir, className] = fileparts(relativePath);
end
function testClassName = buildTestClassName(className, relativeDir, hasDuplicateBaseName)
if ~hasDuplicateBaseName
testClassName = [className, '_test'];
else
if isempty(relativeDir)
prefix = 'root';
else
prefix = regexprep(relativeDir, '[^A-Za-z0-9]+', '_');
prefix = regexprep(prefix, '^_+|_+$', '');
end
testClassName = [prefix, '_', className, '_test'];
end
if ~isletter(testClassName(1))
testClassName = ['T_', testClassName];
end
end
function files = collectMFiles(rootFolder)
pathString = genpath(rootFolder);
folders = regexp(pathString, pathsep, 'split');
folders = folders(~cellfun('isempty', folders));
files = dir(fullfile(rootFolder, '*.m'));
files = files([]); % empty struct with dir() fields
for idx = 1:numel(folders)
currentFiles = dir(fullfile(folders{idx}, '*.m'));
if isempty(currentFiles)
continue
end
currentFiles = currentFiles(~[currentFiles.isdir]);
files = [files; currentFiles]; %#ok<AGROW>
end
end