Skip to content
Merged
Show file tree
Hide file tree
Changes from 32 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://learn.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner?view=azure-devops
#>

$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://learn.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner?view=azure-devops
#
#===============================================================================

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)
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ For starter workflows, use the [`ci-configuration-examples`](https://github.com/

# Workflows

The repository contains examples for packaging and distributing a toolbox, as well as building and uploading Python<sup>&reg;</sup> packages.
The repository contains examples for packaging and distributing a toolbox, building and uploading Python<sup>&reg;</sup> packages, and running tests across multiple build agents.

- **Package and Distribute Toolbox**: Using a matrix build across multiple platforms, compile, link, and test your C source files to produce a binary MEX file per operating system. Then, bundle the resulting binaries into a toolbox and distribute it as a GitHub release.

Expand All @@ -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**: Use the [parallel strategy](https://learn.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner?view=azure-devops) in Azure DevOps to run tests across multiple agents and speed up the testing process. For configuration details, see the example in [`AzureDevOps/ParallelStrategy.yml`](https://github.com/mathworks/advanced-ci-configuration-examples/blob/main/AzureDevOps/ParallelStrategy.yml)

Copy link
Member

Choose a reason for hiding this comment

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

Hi @Vahila, can you terminate this paragraph with a period?

<br>

## Get Started
Expand Down