@@ -122,5 +122,82 @@ function testPackageToolboxShadowedRootFile(testCase)
122122 testCase .verifyEqual(fileread(packagedLicenseFile ), shadowText )
123123 testCase .verifyTrue(isfile(fullfile(pwd , ' code' , ' LICENSE' )))
124124 end
125+
126+ function testTestedWithBadgeCountsReleaseWithSkippedTests(testCase )
127+ % Tests filtered by an unmet assumption are reported as skipped
128+ % rather than failed, so the release is still tested with.
129+ writeTestResultsReport(pwd , " R2024a" , " Skipped" , 4 );
130+ writeTestResultsReport(pwd , " R2024b" );
131+
132+ matbox .tasks.createTestedWithBadgeforToolbox(" v1.2.3" , pwd );
133+
134+ badgeInfo = readTestedWithBadge(testCase , pwd , " v1.2.3" );
135+ testCase .verifyEqual(string(badgeInfo .message), " R2024a | R2024b" )
136+ testCase .verifyEqual(string(badgeInfo .color), " green" )
137+ end
138+
139+ function testTestedWithBadgeExcludesFailingRelease(testCase )
140+ % Errors and failures still disqualify a release, and the badge
141+ % turns orange once a single release is left out.
142+ writeTestResultsReport(pwd , " R2024a" , " Failures" , 1 );
143+ writeTestResultsReport(pwd , " R2024b" , " Skipped" , 2 );
144+
145+ matbox .tasks.createTestedWithBadgeforToolbox(" v1.2.3" , pwd );
146+
147+ badgeInfo = readTestedWithBadge(testCase , pwd , " v1.2.3" );
148+ testCase .verifyEqual(string(badgeInfo .message), " R2024b" )
149+ testCase .verifyEqual(string(badgeInfo .color), " orange" )
150+ end
151+
152+ function testTestedWithBadgeErrorsWhenNoReleasePassed(testCase )
153+ % Writing no badge at all would surface much later as a missing
154+ % file, so the task has to report the problem itself.
155+ writeTestResultsReport(pwd , " R2024a" , " Errors" , 1 );
156+ writeTestResultsReport(pwd , " R2024b" , " Failures" , 1 );
157+
158+ testCase .verifyError( ...
159+ @() matbox .tasks.createTestedWithBadgeforToolbox(" v1.2.3" , pwd ), ...
160+ " MATBOX:BadgeCreation:NoReleasePassed" )
161+ end
125162 end
126163end
164+
165+ function writeTestResultsReport(projectRootDirectory , releaseName , options )
166+ % writeTestResultsReport - Write a minimal JUnit-style report for one release
167+ %
168+ % The report holds a single test suite whose error, failure and skip counts
169+ % are given by the optional arguments. It mirrors the layout that the release
170+ % workflow produces by downloading one report artifact per MATLAB release.
171+
172+ arguments
173+ projectRootDirectory (1 ,1 ) string
174+ releaseName (1 ,1 ) string
175+ options.Errors (1 ,1 ) double = 0
176+ options.Failures (1 ,1 ) double = 0
177+ options.Skipped (1 ,1 ) double = 0
178+ end
179+
180+ reportFolder = fullfile(projectRootDirectory , " docs" , " reports" , " reports-" + releaseName );
181+ if ~isfolder(reportFolder )
182+ mkdir(reportFolder )
183+ end
184+
185+ reportXml = sprintf([...
186+ ' <?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n ' ...
187+ ' <testsuites>\n ' ...
188+ ' <testsuite errors="%d " failures="%d " name="ExampleTest" skipped="%d " tests="%d " time="1.0"/>\n ' ...
189+ ' </testsuites>\n ' ], ...
190+ options .Errors, options .Failures, options .Skipped, ...
191+ options .Errors + options .Failures + options .Skipped + 1 );
192+
193+ matbox .utility.filewrite(fullfile(reportFolder , " test-results.xml" ), reportXml );
194+ end
195+
196+ function badgeInfo = readTestedWithBadge(testCase , projectRootDirectory , versionNumber )
197+ % readTestedWithBadge - Read back the badge written for a given version
198+
199+ badgeFile = fullfile(projectRootDirectory , " .github" , " badges" , versionNumber , " tested_with.json" );
200+ testCase .assertTrue(isfile(badgeFile ), ...
201+ " Expected 'tested with' badge file was not created." )
202+ badgeInfo = jsondecode(fileread(badgeFile ));
203+ end
0 commit comments