Skip to content

Commit a16d4e9

Browse files
committed
Updated for initial release. Ready for release on github/FEX.
1 parent 16b3de7 commit a16d4e9

24 files changed

+551
-0
lines changed

SoftwareTests/CheckTestResults.m

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
classdef CheckTestResults < matlab.unittest.TestCase
2+
3+
properties (SetAccess = protected)
4+
end
5+
6+
properties (ClassSetupParameter)
7+
Project = {currentProject()};
8+
end
9+
10+
properties (TestParameter)
11+
Version
12+
end
13+
14+
15+
methods (TestParameterDefinition,Static)
16+
17+
function Version = GetResults(Project)
18+
RootFolder = Project.RootFolder;
19+
Version = dir(fullfile(RootFolder,"public","TestResults*.txt"));
20+
Version = extractBetween([Version.name],"TestResults_",".txt");
21+
end
22+
23+
end
24+
25+
methods (TestClassSetup)
26+
27+
function SetUpSmokeTest(testCase,Project)
28+
try
29+
currentProject;
30+
catch
31+
error("Project is not loaded.")
32+
end
33+
end
34+
35+
end
36+
37+
methods(Test)
38+
39+
function CheckResults(testCase,Version)
40+
File = fullfile("public","TestResults_"+Version+".txt");
41+
Results = readtable(File,TextType="string");
42+
if ~all(Results.Passed)
43+
error("Some of the tests did not pass.")
44+
end
45+
end
46+
47+
end
48+
49+
end

SoftwareTests/FunctionTests.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
classdef FunctionTests < matlab.unittest.TestCase
2+
3+
% https://www.mathworks.com/help/matlab/matlab_prog/use-parameters-in-class-based-tests.html
4+
5+
methods(Test)
6+
7+
end % methods
8+
9+
end % classdef

SoftwareTests/PostSmokeTest.m

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
function PostSmokeTest(ShowReport)
2+
arguments
3+
ShowReport (1,1) logical = false;
4+
end
5+
6+
import matlab.unittest.plugins.TestRunnerPlugin;
7+
8+
% Create the runner:
9+
Runner = matlab.unittest.TestRunner.withTextOutput;
10+
11+
% Create report folder:
12+
Folder = fullfile(currentProject().RootFolder,"public");
13+
if ~isfolder(Folder)
14+
mkdir(Folder)
15+
end
16+
17+
% Add HTML plugin:
18+
Plugin = matlab.unittest.plugins.TestReportPlugin.producingHTML(Folder,...
19+
"IncludingPassingDiagnostics",true,...
20+
"IncludingCommandWindowText",false,...
21+
"LoggingLevel",matlab.automation.Verbosity(1));
22+
Runner.addPlugin(Plugin);
23+
24+
25+
% Create Test Suite
26+
Suite = testsuite("CheckTestResults");
27+
28+
% Run the test suite
29+
Results = Runner.run(Suite);
30+
31+
32+
% Format the results in a table and save them
33+
Results = table(Results');
34+
Version = extractBetween(string(Results.Name),"Version=",")");
35+
Passed = Results.Passed;
36+
37+
% Add link to other report
38+
File = fileread(fullfile("public","index.html"));
39+
for iVer = 1:length(Version)
40+
File = replace(File,"Version="+Version(iVer),...
41+
sprintf('<a href="%s/index.html">%s</a>',Version(iVer),"Version="+Version(iVer)));
42+
end
43+
writelines(File,fullfile("public","index.html"),"WriteMode","overwrite");
44+
45+
% Format the JSON file
46+
Badge = struct;
47+
Badge.schemaVersion = 1;
48+
Badge.label = "Test Status";
49+
if all(Passed)
50+
Badge.color = "success";
51+
Badge.message = join("R"+Version," | ");
52+
elseif any(Passed)
53+
Badge.color = "yellowgreen";
54+
Badge.message = join("R")
55+
elseif all(~Passed)
56+
Badge.color = "critical";
57+
Badge.message = join("R"+Version," | ");
58+
end
59+
Badge = jsonencode(Badge);
60+
writelines(Badge,fullfile("Images","TestedWith.json"));
61+
62+
if ShowReport
63+
web(fullfile(Folder,"index.html"))
64+
end
65+
66+
end

SoftwareTests/RunAllTests.m

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
function RunAllTests(ShowReport)
2+
arguments
3+
ShowReport (1,1) logical = false;
4+
end
5+
6+
import matlab.unittest.plugins.TestReportPlugin;
7+
8+
% Create a runner
9+
Runner = matlab.unittest.TestRunner.withTextOutput;
10+
Folder = fullfile(currentProject().RootFolder,"public",version("-release"));
11+
if ~isfolder(Folder)
12+
mkdir(Folder)
13+
else
14+
rmdir(Folder,'s')
15+
mkdir(Folder)
16+
end
17+
Plugin = TestReportPlugin.producingHTML(Folder,...
18+
"IncludingPassingDiagnostics",true,...
19+
"IncludingCommandWindowText",true,...
20+
"LoggingLevel",matlab.automation.Verbosity(1));
21+
Runner.addPlugin(Plugin);
22+
23+
24+
% Create the test suite with SmokeTest and Function test if they exist
25+
Suite = testsuite("SmokeTests");
26+
Suite = [Suite testsuite("FunctionTests")];
27+
Suite = [Suite testsuite("SolnSmokeTests")];
28+
29+
% Run the test suite
30+
Results = Runner.run(Suite);
31+
32+
if ShowReport
33+
web(fullfile(Folder,"index.html"))
34+
end
35+
36+
% Format the results in a table and save them
37+
ResultsTable = table(Results')
38+
writetable(ResultsTable,fullfile(currentProject().RootFolder,...
39+
"public","TestResults_"+version("-release")+".txt"));
40+
41+
% Assert success of test
42+
assertSuccess(Results);
43+
44+
end

SoftwareTests/SmokeTests.m

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
classdef SmokeTests < matlab.unittest.TestCase
2+
3+
properties
4+
RootFolder
5+
sparedEditors % Files already open when the test starts
6+
end % properties
7+
8+
properties (ClassSetupParameter)
9+
Project = {currentProject()};
10+
end % ClassSetupParameter
11+
12+
properties (TestParameter)
13+
File;
14+
end % TestParameter
15+
16+
methods (TestParameterDefinition,Static)
17+
18+
function File = RetrieveFile(Project) %#ok<INUSD>
19+
% Retrieve student template files:
20+
RootFolder = currentProject().RootFolder;
21+
File = dir(fullfile(RootFolder,"Scripts","*.mlx"));
22+
File = {File.name};
23+
end
24+
25+
end % Static TestParameterDefinition
26+
27+
methods (TestClassSetup)
28+
29+
function SetUpSmokeTest(testCase,Project) %#ok<INUSD>
30+
% Navigate to project root folder:
31+
testCase.RootFolder = Project.RootFolder;
32+
cd(testCase.RootFolder)
33+
34+
% Close the StartUp app if still open:
35+
delete(findall(groot,'Name','StartUp App'))
36+
37+
% Log MATLAB version:
38+
testCase.log("Running in " + version)
39+
end
40+
41+
end % TestClassSetup
42+
43+
methods(TestMethodSetup)
44+
function recordEditorsToSpare(testCase)
45+
testCase.sparedEditors = matlab.desktop.editor.getAll;
46+
testCase.sparedEditors = {testCase.sparedEditors.Filename};
47+
end
48+
end % TestMethodSetup
49+
50+
methods(TestMethodTeardown)
51+
function closeOpenedEditors_thenDeleteWorkingDir(testCase)
52+
openEditors = matlab.desktop.editor.getAll;
53+
for editor=openEditors(1:end)
54+
if any(strcmp(editor.Filename, testCase.sparedEditors))
55+
continue;
56+
end
57+
% if not on our list, close the file
58+
editor.close();
59+
end
60+
end
61+
end % TestMethodTeardown
62+
63+
methods(Test)
64+
65+
function SmokeRun(testCase,File)
66+
67+
% Navigate to project root folder:
68+
cd(testCase.RootFolder)
69+
FileToRun = string(File);
70+
71+
% Pre-test:
72+
PreFiles = CheckPreFile(testCase,FileToRun);
73+
run(PreFiles);
74+
75+
% Run SmokeTest
76+
disp(">> Running " + FileToRun);
77+
try
78+
run(fullfile("Scripts",FileToRun));
79+
catch ME
80+
81+
end
82+
83+
% Post-test:
84+
PostFiles = CheckPostFile(testCase,FileToRun);
85+
run(PostFiles)
86+
87+
% Log every figure created during run:
88+
Figures = findall(groot,'Type','figure');
89+
Figures = flipud(Figures);
90+
if ~isempty(Figures)
91+
for f = 1:size(Figures,1)
92+
if ~isempty(Figures(f).Number)
93+
FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png');
94+
log(testCase,1,FigDiag);
95+
end
96+
end
97+
end
98+
99+
% Close all figures and Simulink models
100+
close all force
101+
if any(matlab.addons.installedAddons().Name == "Simulink")
102+
bdclose all
103+
end
104+
105+
% Rethrow error if any
106+
if exist("ME","var")
107+
if ~any(strcmp(ME.identifier,KnownIssuesID))
108+
rethrow(ME)
109+
end
110+
end
111+
112+
end
113+
114+
end % Test Methods
115+
116+
117+
methods (Access = private)
118+
119+
function Path = CheckPreFile(testCase,Filename)
120+
PreFile = "Pre"+replace(Filename,".mlx",".m");
121+
PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile);
122+
if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles"))
123+
mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles"))
124+
end
125+
if ~isfile(PreFilePath)
126+
writelines("% Pre-run script for "+Filename,PreFilePath)
127+
writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append');
128+
writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append');
129+
writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append');
130+
writelines(" ",PreFilePath,'WriteMode','append');
131+
end
132+
Path = PreFilePath;
133+
end
134+
135+
function Path = CheckPostFile(testCase,Filename)
136+
PostFile = "Post"+replace(Filename,".mlx",".m");
137+
PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile);
138+
if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles"))
139+
mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles"))
140+
end
141+
if ~isfile(PostFilePath)
142+
writelines("% Post-run script for "+Filename,PostFilePath)
143+
writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append');
144+
writelines(" ",PostFilePath,'WriteMode','append');
145+
end
146+
Path = PostFilePath;
147+
end
148+
149+
end % Private Methods
150+
151+
end % Smoketests

0 commit comments

Comments
 (0)