diff --git a/AzureDevOps/DistributeTests.ps1 b/AzureDevOps/DistributeTests.ps1 new file mode 100644 index 0000000..c91c6ae --- /dev/null +++ b/AzureDevOps/DistributeTests.ps1 @@ -0,0 +1,43 @@ +<# +.SYNOPSIS + Distribute tests across multiple agents in VSTS pipeline +.DESCRIPTION + This script divides test files across multiple agents for faster execution. It searches for files matching a specific pattern (for example, `test*`) and assigns them based on the agent number. + For example, if there are multiple files [test1..test10] and 2 agents: + - Agent 1 runs tests from odd-numbered files. + - Agent 2 runs tests from even-numbered files. + For detailed slicing information, see https://docs.microsoft.com/en-us/vsts/pipelines/test/parallel-testing-any-test-runner +#> + +$tests = Get-ChildItem .\tests\ -Filter *.m -File # Search for test files matching the specified pattern +$totalAgents = [int]$Env:SYSTEM_TOTALJOBSINPHASE # Standard VSTS variable containing the number of parallel jobs +$agentNumber = [int]$Env:SYSTEM_JOBPOSITIONINPHASE # Current job position +$testCount = $tests.Count + +# Handle cases where the pipeline runs without parallel configuration (single agent) +if ($totalAgents -eq 0) { + $totalAgents = 1 +} +if (!$agentNumber -or $agentNumber -eq 0) { + $agentNumber = 1 +} + +Write-Host "Total agents: $totalAgents" +Write-Host "Agent number: $agentNumber" +Write-Host "Total tests: $testCount" + +$testsToRun= @() +# Slice test files so each agent gets a unique set of files to execute +For ($i=$agentNumber; $i -le $testCount;) { + $file = $tests[$i-1] + + $fileName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name) + $testsToRun += "$fileName/*" + $i = $i + $totalAgents + } + +# Join all test files into a space-separated string +$testFiles = $testsToRun -Join " " +Write-Host "Tests to run $testFiles" +# Write files into a variable for execution in a subsequent task +Write-Host "##vso[task.setvariable variable=MATLABTestFiles;]$testFiles" \ No newline at end of file diff --git a/AzureDevOps/DistributeTests.sh b/AzureDevOps/DistributeTests.sh new file mode 100644 index 0000000..ab0437d --- /dev/null +++ b/AzureDevOps/DistributeTests.sh @@ -0,0 +1,52 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: distribute_tests.sh +# +# USAGE: ./distribute_tests.sh +# +# DESCRIPTION: This script divides test files across multiple agents for faster execution. It searches for files matching a specific pattern (for example, `test*`) and assigns them based on the agent number. +# For example, if there are multiple files [test1..test10] and 2 agents: +# - Agent 1 runs tests from odd-numbered files. +# - Agent 2 runs tests from even-numbered files. +# For detailed slicing information, see https://docs.microsoft.com/en-us/vsts/pipelines/test/parallel-testing-any-test-runner +# +#=============================================================================== + +tests=() +# Search for test files matching the specified pattern +while IFS= read -r file; do + tests+=("$file") +done < <(find ./tests -type f -name "*.m" | sort) + +totalAgents=${SYSTEM_TOTALJOBSINPHASE} # Standard VSTS variable containing the number of parallel jobs +agentNumber=${SYSTEM_JOBPOSITIONINPHASE} # Current job position +testCount=${#tests[@]} + +# Handle cases where the pipeline runs without parallel configuration (single agent) +if [ $totalAgents -eq 0 ]; then + totalAgents=1 +fi +if [ -z $agentNumber ]; then + agentNumber=1 +fi + +echo "Total agents: $totalAgents" +echo "Agent number: $agentNumber" +echo "Total tests: $testCount" + +testsToRun=() +# Slice test files so each agent gets a unique set of files +for (( i=agentNumber; i<=testCount; i+=totalAgents )); do + file="${tests[i-1]}" + + fileName=$(basename "$file" .m) + testsToRun+=("${fileName}/*") +done + +# Join all test files into a space-separated string +testFiles="${testsToRun[*]}" +echo "Tests to run $testFiles" + +# Write files into a variable for execution in a subsequent task +echo "##vso[task.setvariable variable=MATLABTestFiles;]$testFiles" \ No newline at end of file diff --git a/AzureDevOps/ParallelStrategy.yml b/AzureDevOps/ParallelStrategy.yml new file mode 100644 index 0000000..ce72d0f --- /dev/null +++ b/AzureDevOps/ParallelStrategy.yml @@ -0,0 +1,84 @@ +jobs: + - job: ParallelWindows + # Specify 'parallel' strategy to run tests in parallel + strategy: + parallel: 2 + pool: + vmImage: windows-latest + steps: + # Install MATLAB and required products + - task: InstallMATLAB@1 + inputs: + products: MATLAB_Compiler_SDK MATLAB_Test + + - task: RunMATLABBuild@1 + inputs: + tasks: mex buildPythonPackage + env: + MLM_LICENSE_TOKEN: $(MLM_LICENSE_TOKEN) + + - powershell: .\AzureDevOps\DistributeTests.ps1 + displayName: 'PowerShell script to distribute tests' + + - task: RunMATLABTests@1 + inputs: + selectByName: $(MATLABTestFiles) + sourceFolder: src + env: + MLM_LICENSE_TOKEN: $(MLM_LICENSE_TOKEN) + + - job: ParallelLinux + # Specify 'parallel' strategy to run tests in parallel + strategy: + parallel: 2 + pool: + vmImage: ubuntu-latest + steps: + # Install MATLAB and required products + - task: InstallMATLAB@1 + inputs: + products: MATLAB_Compiler_SDK MATLAB_Test + + - task: RunMATLABBuild@1 + inputs: + tasks: mex buildPythonPackage + env: + MLM_LICENSE_TOKEN: $(MLM_LICENSE_TOKEN) + + - bash: chmod +x ./AzureDevOps/DistributeTests.sh && ./AzureDevOps/DistributeTests.sh + displayName: 'Bash script to distribute tests' + + - task: RunMATLABTests@1 + inputs: + selectByName: $(MATLABTestFiles) + sourceFolder: src + env: + MLM_LICENSE_TOKEN: $(MLM_LICENSE_TOKEN) + + - job: ParallelMac + # Specify 'parallel' strategy to run tests in parallel + strategy: + parallel: 2 + pool: + vmImage: macOS-latest + steps: + # Install MATLAB and required products + - task: InstallMATLAB@1 + inputs: + products: MATLAB_Compiler_SDK MATLAB_Test + + - task: RunMATLABBuild@1 + inputs: + tasks: mex buildPythonPackage + env: + MLM_LICENSE_TOKEN: $(MLM_LICENSE_TOKEN) + + - bash: chmod +x ./AzureDevOps/DistributeTests.sh && ./AzureDevOps/DistributeTests.sh + displayName: 'Bash script to distribute tests' + + - task: RunMATLABTests@1 + inputs: + selectByName: $(MATLABTestFiles) + sourceFolder: src + env: + MLM_LICENSE_TOKEN: $(MLM_LICENSE_TOKEN) \ No newline at end of file diff --git a/README.md b/README.md index 18ea2c7..e3cac22 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ The repository contains examples for packaging and distributing a toolbox, as we | GitHub Actions| [`.github/workflows/CrossPlatformBuilder.yml`](https://github.com/mathworks/advanced-ci-configuration-examples/blob/main/.github/workflows/CrossPlatformBuilder.yml) | | Jenkins | [`Jenkins/CrossPlatformBuilder/Jenkinsfile`](https://github.com/mathworks/advanced-ci-configuration-examples/blob/main/Jenkins/CrossPlatformBuilder/Jenkinsfile) | +- **Run Tests across Multiple Agents**: Using parallel strategy in Azure DevOps, run tests across multiple agents to speed up the testing process. [`AzureDevOps/ParallelStrategy.yml`](https://github.com/mathworks/advanced-ci-configuration-examples/blob/main/AzureDevOps/ParallelStrategy.yml) has an example of running tests on multiple agents. +
## Get Started