diff --git a/integ-test-promote-template.yml b/integ-test-promote-template.yml index 474a8501..0d6f19be 100644 --- a/integ-test-promote-template.yml +++ b/integ-test-promote-template.yml @@ -219,10 +219,24 @@ 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 + condition: not(eq(${{ version }}, '0')) + - task: MathWorks.matlab-azure-devops-extension-dev.RunMATLABTests.RunMATLABTests@${{ version }} + displayName: Run MATLAB tests filter by name with multiple spaces + inputs: + testResultsJUnit: test-results/matlab/selectbynamewithmultiplespaces.xml + selectByName: "filtertest/* mytest/StartupTest" + sourceFolder: src + condition: not(eq(${{ version }}, '0')) - bash: | set -e grep -q FirstTest test-results/matlab/results.xml @@ -254,6 +268,20 @@ 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 -q simpleTest test-results/matlab/selectbyname.xml + ! grep -q FirstTest test-results/matlab/selectbyname.xml + displayName: Verify test filtered by name + condition: not(eq(${{ version }}, '0')) + - bash: | + set -e + grep -q StartupTest test-results/matlab/selectbynamewithmultiplespaces.xml + grep -q simpleTest test-results/matlab/selectbynamewithmultiplespaces.xml + ! grep -q FirstTest test-results/matlab/selectbynamewithmultiplespaces.xml + displayName: Verify test filtered by name with multiple spaces + condition: not(eq(${{ version }}, '0')) - bash: | echo 'diary console.log' >> startup.m displayName: Set up diary for logging diff --git a/overview.md b/overview.md index 7ddeb020..99661383 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 6e94c0eb..61caf9c9 100644 --- a/tasks/run-matlab-tests/v1/main.ts +++ b/tasks/run-matlab-tests/v1/main.ts @@ -15,6 +15,7 @@ async function run() { SourceFolder: taskLib.getInput("sourceFolder"), SelectByFolder: taskLib.getInput("selectByFolder"), SelectByTag: taskLib.getInput("selectByTag"), + SelectByName: taskLib.getInput("selectByName"), CoberturaModelCoverage: taskLib.getInput("modelCoverageCobertura"), HTMLModelCoverage: taskLib.getInput("modelCoverageHTML"), SimulinkTestResults: taskLib.getInput("testResultsSimulinkTest"), diff --git a/tasks/run-matlab-tests/v1/scriptgen.ts b/tasks/run-matlab-tests/v1/scriptgen.ts index 76249d94..a945f580 100644 --- a/tasks/run-matlab-tests/v1/scriptgen.ts +++ b/tasks/run-matlab-tests/v1/scriptgen.ts @@ -14,12 +14,22 @@ export interface IRunTestsOptions { HTMLModelCoverage?: 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',` + @@ -34,6 +44,7 @@ export function generateCommand(options: IRunTestsOptions): string { `'HTMLModelCoverage','${options.HTMLModelCoverage || ""}',` + `'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 f6316ca3..448c898e 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 that match 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 1323108b..34907634 100644 --- a/tasks/run-matlab-tests/v1/test/scriptgen.test.ts +++ b/tasks/run-matlab-tests/v1/test/scriptgen.test.ts @@ -18,6 +18,7 @@ export default function suite() { HTMLModelCoverage: "", SelectByTag: "", SelectByFolder: "", + SelectByName: "", Strict: false, UseParallel: false, OutputDetail: "", @@ -38,6 +39,7 @@ export default function suite() { assert(actual.includes("'HTMLModelCoverage',''")); 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',''")); @@ -45,7 +47,7 @@ export default function suite() { const expected = `genscript('Test', 'JUnitTestResults','', 'CoberturaCodeCoverage','','HTMLCodeCoverage','', 'SourceFolder','', 'PDFTestReport','', 'HTMLTestReport','', 'SimulinkTestResults','', - 'CoberturaModelCoverage','', 'HTMLModelCoverage','', 'SelectByTag','', 'SelectByFolder','', + 'CoberturaModelCoverage','', 'HTMLModelCoverage','', 'SelectByTag','', 'SelectByFolder','', 'SelectByName',{}, 'Strict',false, 'UseParallel',false, 'OutputDetail','', 'LoggingLevel','')` .replace(/\s+/g, ""); assert(actual.replace(/\s+/g, "").includes(expected)); @@ -64,6 +66,7 @@ export default function suite() { HTMLModelCoverage: "test-results/modelcoverageHTML", SelectByTag: "FeatureA", SelectByFolder: "test/tools;test/toolbox", + SelectByName: "tTestA/* tTestB/*", Strict: true, UseParallel: true, OutputDetail: "Detailed", @@ -84,6 +87,7 @@ export default function suite() { assert(actual.includes("'HTMLModelCoverage','test-results/modelcoverageHTML'")); 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'")); @@ -93,7 +97,7 @@ export default function suite() { 'CoberturaCodeCoverage','code-coverage/coverage.xml','HTMLCodeCoverage','code-coverage/coverageHTML', 'SourceFolder','source', 'PDFTestReport','test-results/pdf-results.pdf', 'HTMLTestReport','test-results/html-resultsHTML', 'SimulinkTestResults','test-results/simulinkTest.mldatx', 'CoberturaModelCoverage','test-results/modelcoverage.xml', 'HTMLModelCoverage','test-results/modelcoverageHTML', '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));