diff --git a/build-test-publish.pipeline.yml b/build-test-publish.pipeline.yml index a33ff971..f6cb0c23 100644 --- a/build-test-publish.pipeline.yml +++ b/build-test-publish.pipeline.yml @@ -1,4 +1,4 @@ -name: 1.13$(Rev:.r) +name: 1.14$(Rev:.r) trigger: - master diff --git a/integ-test-promote-template.yml b/integ-test-promote-template.yml index cf50b902..bfd9108e 100644 --- a/integ-test-promote-template.yml +++ b/integ-test-promote-template.yml @@ -217,10 +217,16 @@ jobs: testResultsJUnit: test-results/matlab/selectbyfolder.xml selectByFolder: tests/filteredTest - task: MathWorks.matlab-azure-devops-extension-dev.RunMATLABTests.RunMATLABTests@${{ version }} - displayName: Run MATLAB tests filter by folder + displayName: Run MATLAB tests filter by tag inputs: testResultsJUnit: test-results/matlab/selectbytag.xml selectByTag: FILTERED + - task: MathWorks.matlab-azure-devops-extension-dev.RunMATLABTests.RunMATLABTests@${{ version }} + displayName: Run MATLAB tests filter by name + inputs: + testResultsJUnit: test-results/matlab/selectbyname.xml + selectByName: "filtertest/* mytest/StartupTest" + sourceFolder: src - bash: | set -e grep -q FirstTest test-results/matlab/results.xml @@ -240,6 +246,11 @@ jobs: grep -v FirstTest test-results/matlab/selectbytag.xml grep -v simpleTest test-results/matlab/selectbytag.xml displayName: Verify test filtered by tag name + - bash: | + set -e + grep -q StartupTest test-results/matlab/selectbyname.xml + grep -v simpleTest test-results/matlab/selectbyname.xml + displayName: Verify test filtered by name - bash: | echo 'diary console.log' >> startup.m displayName: Set up diary for logging diff --git a/overview.md b/overview.md index 44ea4f32..c98f9955 100644 --- a/overview.md +++ b/overview.md @@ -228,6 +228,7 @@ Input | Description ------------------------- | --------------- `sourceFolder` |

(Optional) Location of the folder containing source code, specified as a path relative to the project root folder. The specified folder and its subfolders are added to the top of the MATLAB search path. If you specify `sourceFolder` and then generate a coverage report, the task uses only the source code in the specified folder and its subfolders to generate the report. You can specify multiple folders using a colon-separated or semicolon-separated list.

**Example:** `sourceFolder: source`
**Example:** `sourceFolder: source/folderA; source/folderB`

`selectByFolder` |

(Optional) Location of the folder used to select test suite elements, specified as a path relative to the project root folder. To create a test suite, the task uses only the tests in the specified folder and its subfolders. You can specify multiple folders using a colon-separated or semicolon-separated list.

**Example:** `selectByFolder: test`
**Example:** `selectByFolder: test/folderA; test/folderB`

+`selectBynName` |

(Optional) Names of the tests to run, specified as a list of test names separated by spaces. If you specify this input, the task runs only the tests with the specified names. You can use the wildcard character (`*`) to match any number of characters and the question mark character (`?`) to match a single character. For example, specify `selectByName: ExampleTest/*` to select all the tests whose name starts with `ExampleTest/`.

For a given test file, the name of a test uniquely identifies the smallest runnable portion of the test content. The test name includes the namespace name, filename (excluding the extension), procedure name, and information about parameterization.

**Example:** `selectByName: ExampleTest/testA`
**Example:** `selectByName: ExampleTest/testA ExampleTest/testB(array=3x3_double)`

`selectByTag` |

(Optional) Test tag used to select test suite elements. To create a test suite, the task uses only the test elements with the specified tag.

**Example:** `selectByTag: Unit`

`strict` |

(Optional) Option to apply strict checks when running tests, specified as `false` or `true`. By default, the value is `false`. If you specify a value of `true`, the task generates a qualification failure whenever a test issues a warning.

**Example:** `strict: true`

`useParallel` |

(Optional) Option to run tests in parallel, specified as `false` or `true`. By default, the value is `false` and tests run in serial. If the test runner configuration is suited for parallelization, you can specify a value of `true` to run tests in parallel. This input requires a Parallel Computing Toolbox license.

**Example:** `useParallel: true`

diff --git a/tasks/run-matlab-tests/v1/main.ts b/tasks/run-matlab-tests/v1/main.ts index ed0bdb0f..1f155327 100644 --- a/tasks/run-matlab-tests/v1/main.ts +++ b/tasks/run-matlab-tests/v1/main.ts @@ -14,6 +14,7 @@ async function run() { SourceFolder: taskLib.getInput("sourceFolder"), SelectByFolder: taskLib.getInput("selectByFolder"), SelectByTag: taskLib.getInput("selectByTag"), + SelectByName: taskLib.getInput("SelectByName"), CoberturaModelCoverage: taskLib.getInput("modelCoverageCobertura"), SimulinkTestResults: taskLib.getInput("testResultsSimulinkTest"), PDFTestReport: taskLib.getInput("testResultsPDF"), diff --git a/tasks/run-matlab-tests/v1/scriptgen.ts b/tasks/run-matlab-tests/v1/scriptgen.ts index 68d6e3c8..6a578deb 100644 --- a/tasks/run-matlab-tests/v1/scriptgen.ts +++ b/tasks/run-matlab-tests/v1/scriptgen.ts @@ -11,12 +11,22 @@ export interface IRunTestsOptions { CoberturaModelCoverage?: string; SelectByTag?: string; SelectByFolder?: string; + SelectByName?: string; Strict?: boolean; UseParallel?: boolean; OutputDetail?: string; LoggingLevel?: string; } +// Function to convert space separated names to cell array of character vectors +export function getSelectByNameAsCellArray(input?: string): string { + if (!input || !input.trim()) { + return "{}"; + } + const items = input.split(/\s+/).filter(Boolean).map((s) => `'${s}'`); + return `{${items.join(", ")}}`; +} + export function generateCommand(options: IRunTestsOptions): string { return `addpath('${path.join(__dirname, "scriptgen")}');` + `testScript = genscript('Test',` + @@ -28,6 +38,7 @@ export function generateCommand(options: IRunTestsOptions): string { `'CoberturaModelCoverage','${options.CoberturaModelCoverage || ""}',` + `'SelectByTag','${options.SelectByTag || ""}',` + `'SelectByFolder','${options.SelectByFolder || ""}',` + + `'SelectByName',${getSelectByNameAsCellArray(options.SelectByName)},` + `'Strict',${options.Strict || false},` + `'UseParallel',${options.UseParallel || false},` + `'OutputDetail','${options.OutputDetail || ""}',` + diff --git a/tasks/run-matlab-tests/v1/task.json b/tasks/run-matlab-tests/v1/task.json index ef9cc098..8f51b809 100644 --- a/tasks/run-matlab-tests/v1/task.json +++ b/tasks/run-matlab-tests/v1/task.json @@ -57,6 +57,15 @@ "required": false, "helpMarkDown": "Test tag used to select test suite elements. To create a test suite, the task uses only the test elements with the specified tag." }, + { + "name": "selectByName", + "type": "string", + "label": "By name", + "defaultValue": "", + "groupName": "filterTests", + "required": false, + "helpMarkDown": "Test name used to select test suite elements. To create a test suite, the task uses only the test elements with the specified name." + }, { "name": "strict", "type": "boolean", diff --git a/tasks/run-matlab-tests/v1/test/scriptgen.test.ts b/tasks/run-matlab-tests/v1/test/scriptgen.test.ts index d89e4921..da98e949 100644 --- a/tasks/run-matlab-tests/v1/test/scriptgen.test.ts +++ b/tasks/run-matlab-tests/v1/test/scriptgen.test.ts @@ -15,6 +15,7 @@ export default function suite() { CoberturaModelCoverage: "", SelectByTag: "", SelectByFolder: "", + SelectByName: "", Strict: false, UseParallel: false, OutputDetail: "", @@ -32,6 +33,7 @@ export default function suite() { assert(actual.includes("'CoberturaModelCoverage',''")); assert(actual.includes("'SelectByTag',''")); assert(actual.includes("'SelectByFolder',''")); + assert(actual.includes("'SelectByName',{}")); assert(actual.includes("'Strict',false")); assert(actual.includes("'UseParallel',false")); assert(actual.includes("'OutputDetail',''")); @@ -39,7 +41,7 @@ export default function suite() { const expected = `genscript('Test', 'JUnitTestResults','', 'CoberturaCodeCoverage','', 'SourceFolder','', 'PDFTestReport','', 'SimulinkTestResults','', - 'CoberturaModelCoverage','', 'SelectByTag','', 'SelectByFolder','', + 'CoberturaModelCoverage','', 'SelectByTag','', 'SelectByFolder','', 'SelectByName',{}, 'Strict',false, 'UseParallel',false, 'OutputDetail','', 'LoggingLevel','')` .replace(/\s+/g, ""); assert(actual.replace(/\s+/g, "").includes(expected)); @@ -55,6 +57,7 @@ export default function suite() { CoberturaModelCoverage: "test-results/modelcoverage.xml", SelectByTag: "FeatureA", SelectByFolder: "test/tools;test/toolbox", + SelectByName: "tTestA/* tTestB/*", Strict: true, UseParallel: true, OutputDetail: "Detailed", @@ -72,6 +75,7 @@ export default function suite() { assert(actual.includes("'CoberturaModelCoverage','test-results/modelcoverage.xml'")); assert(actual.includes("'SelectByTag','FeatureA'")); assert(actual.includes("'SelectByFolder','test/tools;test/toolbox'")); + assert(actual.includes("'SelectByName',{'tTestA/*', 'tTestB/*'}")); assert(actual.includes("'Strict',true")); assert(actual.includes("'UseParallel',true")); assert(actual.includes("'OutputDetail','Detailed'")); @@ -81,7 +85,7 @@ export default function suite() { 'CoberturaCodeCoverage','code-coverage/coverage.xml', 'SourceFolder','source', 'PDFTestReport','test-results/pdf-results.pdf', 'SimulinkTestResults','test-results/simulinkTest.mldatx', 'CoberturaModelCoverage','test-results/modelcoverage.xml', 'SelectByTag','FeatureA', - 'SelectByFolder','test/tools;test/toolbox', 'Strict',true, 'UseParallel',true, 'OutputDetail','Detailed', + 'SelectByFolder','test/tools;test/toolbox', 'SelectByName',{'tTestA/*', 'tTestB/*'}, 'Strict',true, 'UseParallel',true, 'OutputDetail','Detailed', 'LoggingLevel','Detailed' )` .replace(/\s+/g, ""); assert(actual.replace(/\s+/g, "").includes(expected));