Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions AzureDevOps/DistributeTests.ps1
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the link include learn. instead of docs? Here is what I am seeing in my browser:

https://learn.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner?view=azure-devops

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's best to avoid redirects as much as possible.

#>

$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"
52 changes: 52 additions & 0 deletions AzureDevOps/DistributeTests.sh
Original file line number Diff line number Diff line change
@@ -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"
84 changes: 84 additions & 0 deletions AzureDevOps/ParallelStrategy.yml
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggesting some edits:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter link is broken. Please make sure it gets fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you are adding this paragraph, you also need to update line 17 to be inclusive of the new example. Something like this:

The repository contains examples for packaging and distributing a toolbox, building and uploading Python® packages, and running tests across multiple build agents.


<br>

## Get Started
Expand Down