diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..58c6d20 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,68 @@ +name: MATLAB Build + +# Controls when the action will run. +on: + push: + branches: [ release ] + pull_request: + branches: [ release ] + workflow_dispatch: + +jobs: + test: + strategy: + fail-fast: false + matrix: + MATLABVersion: [R2023a,R2023b] + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + # Sets up MATLAB on the GitHub Actions runner + - name: Setup MATLAB + uses: matlab-actions/setup-matlab@v1 + with: + release: ${{ matrix.MATLABVersion }} + + # Run SmokeTests + - name: Run SmokeTests + uses: matlab-actions/run-command@v1 + with: + command: openProject(pwd); results = runtests(fullfile("SoftwareTests","SmokeTests.m")); assertSuccess(results); + + # Run FunctionTests + - name: Run FunctionTests + uses: matlab-actions/run-command@v1 + with: + command: openProject(pwd); results = runtests(fullfile("SoftwareTests","FunctionTests.m")); assertSuccess(results); + + # Upload the test results as artifact + - name: Upload TestResults + uses: actions/upload-artifact@v3.1.3 + with: + name: TestResults + path: ./SoftwareTests/TestResults_${{ matrix.MATLABVersion }}.txt + + # Download the test results from artifact + - name: Download TestResults + uses: actions/download-artifact@v2.1.1 + with: + name: TestResults + path: ./SoftwareTests/ + + # Create the test results badge + - name: Run CreateBadge + uses: matlab-actions/run-command@v1 + with: + command: openProject(pwd); results = runtests(fullfile("SoftwareTests","CreateBadge.m")); + + # Commit the JSON for the MATLAB releases badge + - name: Commit changed files + continue-on-error: true + run: | + git config user.name "${{ github.workflow }} by ${{ github.actor }}" + git config user.email "<>" + git commit Images/TestedWith.json -m "Update CI badges ${{ github.ref_name }}" + git fetch + git push diff --git a/.gitignore b/.gitignore index ecf9aff..fc63c3f 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ codegen/ # Project settings Utilities/ProjectSettings.mat + +# Test results +SoftwareTests/TestResults_* diff --git a/SoftwareTests/CreateBadge.m b/SoftwareTests/CreateBadge.m new file mode 100644 index 0000000..9e0a708 --- /dev/null +++ b/SoftwareTests/CreateBadge.m @@ -0,0 +1,82 @@ +% Run these tests with runMyTests +% All tests so far are on code expected to run without errors +% If/when we end up with a version that _should_ error, +% please add it to this set of examples +classdef CreateBadge < matlab.unittest.TestCase + + properties + rootProject + results + end + + + methods (TestClassSetup) + + function setUpPath(testCase) + + try + project = currentProject; + testCase.rootProject = project.RootFolder; + cd(testCase.rootProject) + catch + error("Load project prior to run tests") + end + + testCase.log("Running in " + version) + + end % function setUpPath + + function readResults(testCase) + Release = string([]); + Passed = []; + testCase.results = table(Release,Passed); + + ResultFiles = dir("SoftwareTests"+filesep+"TestResults_*"); + for kFiles = 1:size(ResultFiles) + Results = readtable(fullfile(ResultFiles(kFiles).folder,ResultFiles(kFiles).name),... + Delimiter=",",TextType="string"); + Release = Results.Version(1); + Passed = all(Results.Status == "passed"); + testCase.results(end+1,:) = table(Release,Passed); + end + end + + end % methods (TestClassSetup) + + methods(Test) + + function writeBadge(testCase) + + % Create JSON + badgeInfo = struct; + badgeInfo.schemaVersion = 1; + badgeInfo.label = "tested with"; + badgeInfo.message = ""; + + % Check that results exist: + if size(testCase.results,1) == 0 + badgeInfo.message = "None"; + badgeInfo.color = "failed"; + else + for i = 1:size(testCase.results,1) + if testCase.results.Passed(i) + if badgeInfo.message ~= "" + badgeInfo.message = badgeInfo.message + " | "; + end + badgeInfo.message = badgeInfo.message + string(testCase.results.Release(i)); + end + end + badgeInfo.color = "success"; + end + + % Write JSON file out + badgeJSON = jsonencode(badgeInfo); + fid = fopen(fullfile("Images","TestedWith.json"),"w"); + fwrite(fid,badgeJSON); + fclose(fid); + + end + + end + +end \ No newline at end of file diff --git a/SoftwareTests/SmokeTests.m b/SoftwareTests/SmokeTests.m index 53fadc0..467a0c2 100644 --- a/SoftwareTests/SmokeTests.m +++ b/SoftwareTests/SmokeTests.m @@ -45,6 +45,8 @@ function setUpResults(testCase) function smokeTest(testCase) myFiles = testCase.results.Name; + fid = fopen(fullfile("SoftwareTests","TestResults_"+release_version+".txt"),"w"); + fprintf(fid,"Version,File,Status,ElapsedTime\n"); for kTest = 1:length(myFiles) try disp("Running " + myFiles(kTest)) @@ -53,14 +55,17 @@ function smokeTest(testCase) testCase.results.Time(kTest) = toc; disp("Finished " + myFiles(kTest)) testCase.results.Passed(kTest) = true; + fprintf(fid,"%s,%s,%s,%s\n",release_version,myFiles(kTest),"passed",testCase.results.Time(kTest)); catch ME testCase.results.Time(kTest) = toc; disp("Failed " + myFiles(kTest) + " because " + ... newline + ME.message) testCase.results.Message(kTest) = ME.message; + fprintf(fid,"%s,%s,%s,%s\n",release_version,myFiles(kTest),"failed",testCase.results.Time(kTest)); end - clearvars -except kTest testCase myFiles + clearvars -except kTest testCase myFiles fid end + fclose(fid); struct2table(testCase.results) end