- name
- rebalance-ui-test-categories
- description
- Rebalances a UI-test umbrella category into additive method-level CI shards using historical Azure DevOps test durations.
- metadata
- {"author":"dotnet-maui","version":"1.0"}
- compatibility
- Requires PowerShell 7 and Azure CLI with the azure-devops extension.
# Rebalance UI Test Categories
Use this skill when a category in `maui-pr-uitests` needs multiple ordinary
matrix legs and each leg must fit a target duration.
## Rules
- Historical Azure test results are required. Never substitute source test
counts for timing evidence.
- Use one method-level
`[ShardedTestCategory(UITestCategories.Category, shard: N)]` attribute. It
exposes both the umbrella and exactly one numbered shard category to NUnit.
Never put sharded categories on a class.
- Use a conservative per-test/platform p80 of recent valid run totals.
- Aggregate measured fixed job overhead with nearest-rank p80.
- Reserve a configurable safety margin (2 minutes by default), so every
projection is strictly below `TargetMinutes - SafetyMarginMinutes`.
- Assignment is deterministic multidimensional longest-processing-time
scheduling over individual methods and cohesive ordered fixtures. It
minimizes the worst projected platform/shard duration.
- Fail if one test plus overhead exceeds the target or if `-MaxShards` cannot
satisfy the target.
- Applying a category maintains the analyzer's reusable shard-prefix set,
preserving previously registered umbrellas, and performs mandatory
plan-to-source validation after editing.
- Before splitting methods from one fixture across shards, ensure fixture setup
independently reaches the state required by every selected method. Never rely
on an `Order(1)` test to initialize the remaining shard.
- Dedicated configuration stages that use `testConfigurationArgs`, such as
`ios_ui_tests_mono_cv1`, reuse the numbered shard filters but remain outside
ordinary category-matrix projection data. Their samples and overhead are
recorded separately so they cannot make ordinary shard projections look
artificially cheaper.
## Commands
Gather, plan, report, and apply in one operation:
```powershell
pwsh .github/skills/rebalance-ui-test-categories/scripts/Rebalance-UITestCategories.ps1 `
-Mode All -Category CollectionView -TargetMinutes 60 `
-SafetyMarginMinutes 2 -BuildId 1561395,1563447 `
-UnmeasuredTestPolicy ClassPlatformMax `
-OutputPath artifacts/CollectionView-rebalance.json -Apply
```
Use `-RecentBuildCount N` instead of `-BuildId` to query recent completed builds
from pipeline definition 313. To work offline, explicitly pass
`-EvidencePath path/to/evidence.json`; absence of Azure access or an evidence
file is an error.
Use `-MinimumShards N -MaxShards N` when rebalancing an existing matrix without
changing its job count.
Separate deterministic phases are also available:
```powershell
# Azure -> evidence JSON
... -Mode Gather -Category CollectionView -BuildId 1563447 `
-OutputPath artifacts/CollectionView-evidence.json
# Evidence -> assignment report
... -Mode Plan -Category CollectionView `
-EvidencePath artifacts/CollectionView-evidence.json `
-OutputPath artifacts/CollectionView-plan.json
# Existing report -> source/YAML/constants
... -Mode Apply -Category CollectionView `
-PlanPath artifacts/CollectionView-plan.json -Apply
```
Review the JSON report's `projectedShardMinutes`, `fixedOverheadMinutes`,
`safetyMarginMinutes`, separately recorded configuration-stage evidence,
unmatched evidence, and source mapping before accepting the result.
The planner fails when active source tests have no historical sample. For a
known-complete historical run where such methods were not reported, the
explicit `-UnmeasuredTestPolicy ClassPlatformMax` option conservatively imputes
the maximum measured method duration from the same class/platform (falling
back to the platform-wide maximum) and records every imputation in the report.
عرض على GitHub