Skip to content

Commit 44c9617

Browse files
committed
Added GitHub workflow
1 parent 7426cd7 commit 44c9617

19 files changed

+255
-7
lines changed

.github/workflows/mvc-ci.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: MVC Application Continuous Integration
2+
3+
# Controls when the workflow will run.
4+
on: [push, workflow_dispatch]
5+
# Triggers the workflow on push request events and for manual runs from the Actions tab in GitHub.
6+
7+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel.
8+
jobs:
9+
10+
# Run the default tasks in the MVC project build file.
11+
run-MVC-build:
12+
13+
# Define the job strategy.
14+
strategy:
15+
16+
# Set up the job strategy matrix to define the different job configurations.
17+
matrix:
18+
19+
# List of platforms on which to run the tests.
20+
platform: [ ubuntu-latest, windows-latest, macos-latest ]
21+
22+
# List of MATLAB releases over which to run the tests.
23+
matlab-version: [ R2024b ]
24+
25+
# Specify the platform that the job will run on.
26+
runs-on: ${{ matrix.platform }}
27+
28+
# Don't fail the entire run if one job fails.
29+
continue-on-error: true
30+
31+
# Steps define a sequence of tasks to be executed as part of the job.
32+
steps:
33+
34+
# Check out the repository under $GITHUB_WORKSPACE, so that the job can access it.
35+
- name: Check out the repository
36+
uses: actions/checkout@v4
37+
38+
# For Linux jobs, start a display server on the runner.
39+
- name: Start a display server for jobs running on Linux.
40+
if: ${{ matrix.platform == 'ubuntu-latest' }}
41+
run: |
42+
sudo apt-get install -y xvfb
43+
Xvfb :99 &
44+
echo "DISPLAY=:99" >> $GITHUB_ENV
45+
46+
# Set up MATLAB on the runner.
47+
- name: Set up MATLAB on the runner.
48+
uses: matlab-actions/setup-matlab@v2
49+
with:
50+
# The tests require only base MATLAB.
51+
products: MATLAB
52+
release: ${{ matrix.matlab-version }}
53+
54+
# Run the default tasks in the MVC project build file.
55+
- name: Run the default tasks in the MVC project build file.
56+
uses: matlab-actions/run-build@v2

buildfile.m

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
function plan = buildfile()
2+
%BUILDFILE Example MVC application build file.
3+
4+
% Copyright 2025 The MathWorks, Inc.
5+
6+
% Define the build plan.
7+
plan = buildplan( localfunctions() );
8+
9+
% Set the archive task to run by default.
10+
plan.DefaultTasks = "archive";
11+
12+
% Add a test task to run the unit tests for the project. Generate and save
13+
% a coverage report.
14+
projectRoot = plan.RootFolder;
15+
testsFolder = fullfile( projectRoot, "tests" );
16+
codeFolder = fullfile( projectRoot, "code" );
17+
plan("test") = matlab.buildtool.tasks.TestTask( testsFolder, ...
18+
"Strict", true, ...
19+
"Description", "Assert that all project tests pass.", ...
20+
"SourceFiles", codeFolder, ...
21+
"CodeCoverageResults", "reports/Coverage.html", ...
22+
"OutputDetail", "verbose" );
23+
24+
% The test task depends on the check task.
25+
plan("test").Dependencies = "check";
26+
27+
% The archive task depends on the test task.
28+
plan("archive").Dependencies = "test";
29+
30+
end % buildfile
31+
32+
function checkTask( context )
33+
% Check the source code and project for any issues.
34+
35+
% Set the project root as the folder in which to check for any static code
36+
% issues.
37+
projectRoot = context.Plan.RootFolder;
38+
codeIssuesTask = matlab.buildtool.tasks.CodeIssuesTask( projectRoot, ...
39+
"IncludeSubfolders", true, ...
40+
"Configuration", "factory", ...
41+
"Description", ...
42+
"Assert that there are no code issues in the project.", ...
43+
"WarningThreshold", 0 );
44+
codeIssuesTask.analyze( context )
45+
46+
% Update the project dependencies.
47+
prj = currentProject();
48+
prj.updateDependencies()
49+
50+
% Run the checks.
51+
checkResults = table( prj.runChecks() );
52+
53+
% Log any failed checks.
54+
passed = checkResults.Passed;
55+
notPassed = ~passed;
56+
if any( notPassed )
57+
disp( checkResults(notPassed, :) )
58+
else
59+
fprintf( "** All project checks passed.\n\n" )
60+
end % if
61+
62+
% Check that all checks have passed.
63+
assert( all( passed ), "buildfile:ProjectIssue", ...
64+
"At least one project check has failed. " + ...
65+
"Resolve the failures shown above to continue." )
66+
67+
end % checkTask
68+
69+
function archiveTask( ~ )
70+
% Archive the project.
71+
72+
proj = currentProject();
73+
projectRoot = proj.RootFolder;
74+
exportName = fullfile( projectRoot, "MVC.mlproj" );
75+
proj.export( exportName )
76+
77+
end % archiveTask
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location="1" type="DIR_SIGNIFIER"/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location="workflows" type="File"/>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info>
3+
<Category UUID="FileClassCategory">
4+
<Label UUID="design"/>
5+
</Category>
6+
</Info>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location="runMVCTests.m" type="File"/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location="1" type="DIR_SIGNIFIER"/>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info>
3+
<Category UUID="FileClassCategory">
4+
<Label UUID="design"/>
5+
</Category>
6+
</Info>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location="mvc-ci.yml" type="File"/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location=".github" type="File"/>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info>
3+
<Category UUID="FileClassCategory">
4+
<Label UUID="design"/>
5+
</Category>
6+
</Info>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Info location="buildfile.m" type="File"/>

tests/runMVCTests.m

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
function varargout = runMVCTests()
2+
%RUNMVCTESTS Run the MVC application tests and generate a test report.
3+
%
4+
% results = runMVCTests() runs all MVC application tests and returns the
5+
% results.
6+
7+
% Copyright 2025 The MathWorks, Inc.
8+
9+
nargoutchk( 0, 1 )
10+
11+
% Record the current folder (the tests directory).
12+
testsFolder = fileparts( mfilename( "fullpath" ) );
13+
14+
% Create the test suite from the project.
15+
suite = testsuite( testsFolder );
16+
17+
% Record text output.
18+
runner = testrunner( "textoutput", ...
19+
"LoggingLevel", "Verbose", ...
20+
"OutputDetail", "Verbose" );
21+
22+
% Add a code coverage plugin.
23+
report = matlab.unittest.plugins.codecoverage.CoverageReport( ...
24+
testsFolder, "MainFile", "Coverage.html" );
25+
codeFolder = fullfile( fileparts( testsFolder ), "code" );
26+
plugin = matlab.unittest.plugins.CodeCoveragePlugin.forFolder( ...
27+
codeFolder, "Producing", report );
28+
runner.addPlugin( plugin )
29+
30+
% Add a diagnostics recording plugin for the test report.
31+
plugin = matlab.unittest.plugins.DiagnosticsRecordingPlugin( ...
32+
"IncludingPassingDiagnostics", true, ...
33+
"LoggingLevel", "Verbose", ...
34+
"OutputDetail", "Verbose" );
35+
runner.addPlugin( plugin )
36+
37+
% Run the tests.
38+
results = runner.run( suite );
39+
40+
% Generate the test report.
41+
results.generatePDFReport( "TestResults.pdf", ...
42+
"Title", "MVC Application Test Results" )
43+
44+
if nargout == 1
45+
varargout{1} = results;
46+
end % if
47+
48+
end % runMVCTests
49+

tests/tComponent.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,18 @@ function createComponent( testCase )
6868

6969
end % methods ( TestMethodSetup )
7070

71+
methods ( Test, TestTags = "validHandle" )
72+
73+
function tComponentIsValidHandle( testCase )
74+
75+
% The component should be a valid handle object.
76+
testCase.verifyTrue( ...
77+
isvalid( testCase.ApplicationComponent ), ...
78+
"The " + testCase.ComponentType + " constructor did " + ...
79+
"not create a valid handle object." )
80+
81+
end % tComponentIsValidHandle
82+
83+
end % methods ( Test )
84+
7185
end % classdef

tests/tModel.m

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function setupModel( testCase )
3737

3838
end % methods ( TestMethodSetup )
3939

40-
methods ( Test )
40+
methods ( Test, TestTags = "validHandle" )
4141

4242
function tModelIsValidHandle( testCase )
4343

@@ -48,6 +48,10 @@ function tModelIsValidHandle( testCase )
4848

4949
end % tModelIsValidHandle
5050

51+
end % methods ( Test, TestTags = "validHandle" )
52+
53+
methods ( Test, TestTags = "initialValue" )
54+
5155
function tInitialDataPropertyIsEmptyDouble( testCase )
5256

5357
% The model's Data property should initialize to an empty 0x1
@@ -61,6 +65,10 @@ function tInitialDataPropertyIsEmptyDouble( testCase )
6165

6266
end % tInitialDataPropertyIsEmptyDouble
6367

68+
end % methods ( Test, TestTags = "initialValue" )
69+
70+
methods ( Test, TestTags = ["controlMethods", "dataGeneration"] )
71+
6472
function tRandomMethodGeneratesDoubleVector( testCase )
6573

6674
% The random method should generate a 20 x 1 vector of doubles.
@@ -99,7 +107,11 @@ function tResetMethodRestoresEmptyVector( testCase )
99107

100108
end % tResetMethodRestoresEmptyVector
101109

102-
function tRandomMethodRaisesDataChangedEvent( testCase )
110+
end % methods ( Test, TestTags = ["controlMethods", "dataGeneration"] )
111+
112+
methods ( Test, TestTags = "eventNotification" )
113+
114+
function tRandomMethodNotifiesDataChangedEvent( testCase )
103115

104116
% Verify that calling random() notifies the 'DataChanged'
105117
% event.
@@ -110,11 +122,11 @@ function tRandomMethodRaisesDataChangedEvent( testCase )
110122
"did not cause the model to notify the " + ...
111123
"'DataChanged' event." )
112124

113-
end % tRandomMethodRaisesDataChangedEvent
125+
end % tRandomMethodNotifiesDataChangedEvent
114126

115-
function tResetMethodRaisesDataChangedEvent( testCase )
127+
function tResetMethodNotifiesDataChangedEvent( testCase )
116128

117-
% Verify that calling reest() notifies the 'DataChanged'
129+
% Verify that calling reset() notifies the 'DataChanged'
118130
% event.
119131
constraint = NotifiesEvent( ...
120132
testCase.ApplicationModel, "DataChanged" );
@@ -123,8 +135,8 @@ function tResetMethodRaisesDataChangedEvent( testCase )
123135
"did not cause the model to notify the " + ...
124136
"'DataChanged' event." )
125137

126-
end % tResetMethodRaisesDataChangedEvent
138+
end % tResetMethodNotifiesDataChangedEvent
127139

128-
end % methods ( Test )
140+
end % methods ( Test, TestTags = "eventNotification" )
129141

130142
end % classdef

0 commit comments

Comments
 (0)