Copilot instructions
.github/instructions/integration-tests.instructions.mdGuidance for GitHub Copilot when working with .NET MAUI integration tests
Copilot instructions
Quality
92/100
Scores the file, not the repository.Length
1,180 words
27 headings · 7 code blocksRepository
23k
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.123456# .NET MAUI Integration Tests Guidelines78Integration tests validate end-to-end functionality by creating, building, and running .NET MAUI projects using templates and the local workload.910## Test Framework1112These integration tests use **NUnit** as the test framework.1314## CI Infrastructure1516All integration tests run on **Azure DevOps agents** via the stage template `eng/pipelines/arcade/stage-integration-tests.yml`.1718- **Windows tests**: Run on Windows 1ES pools19- **macOS tests**: Run on Azure Pipelines hosted images20 - General macOS tests: `macOS-15` (ARM64/Apple Silicon)21 - `RunOnAndroid`: `macOS-15` (via MacOSPool)22 - `RunOniOS_*`: Each iOS test runs in **two separate lanes**:23 - **ARM64 lane** (`MacOSPoolArm64`): `macOS-15` with Apple Silicon24 - **MacOSPool lane** (`MacOSPool`): For comparison testing2526### Test Retry2728Integration tests are configured with **automatic retry on failure** (`retryCountOnTaskFailure: 1`). If a test fails, Azure DevOps will automatically retry it once before reporting failure.2930**Log Preservation**: Logs from each attempt are saved to separate folders (`attempt-1/`, `attempt-2/`, etc.) so that both the original run and retry logs are preserved for debugging. This uses the `SYSTEM_JOBATTEMPT` environment variable provided by Azure DevOps.3132### Individual iOS Test Lanes3334iOS tests are split into individual jobs for faster debugging and parallel execution. Each test runs on both ARM64 and MacOSPool for comparison:3536| Test | Description | Timeout |37|------|-------------|---------|38| `RunOniOS_MauiDebug` | MAUI app, Debug config | 45 min |39| `RunOniOS_MauiRelease` | MAUI app, Release config | 45 min |40| `RunOniOS_MauiReleaseTrimFull` | MAUI app, Release, full trim | 45 min |41| `RunOniOS_BlazorDebug` | Blazor app, Debug config | 45 min |42| `RunOniOS_BlazorRelease` | Blazor app, Release config | 45 min |43| `RunOniOS_MauiNativeAOT` | MAUI app, NativeAOT | 45 min |4445**Note**: `RunOniOS_BlazorReleaseTrimFull` is temporarily disabled due to [ASP.NET Core issue #63951](https://github.com/dotnet/aspnetcore/issues/63951).4647### MacOSPool Lane Conditions4849The **MacOSPool lanes** (non-ARM64 comparison tests) only run under specific conditions:50511. **Non-PR builds** on branches: `main`, `net*.0`, `release/*`, or `inflight/*`522. **PR builds** where the target branch is: `net*.0`, `release/*`, or `inflight/*`5354This ensures MacOSPool comparison tests don't run on regular PR builds targeting `main`, saving CI resources while still running them for release-related branches.5556## Test Categories5758Tests are organized by categories (defined in `Utilities/Categories.cs`) that map to CI jobs:5960| Category | Purpose | Platform |61|----------|---------|----------|62| `Build` | Basic template build tests | All |63| `WindowsTemplates` | Windows-specific scenarios | Windows |64| `macOSTemplates` | macOS-specific scenarios | macOS |65| `Blazor` | Blazor hybrid templates | All |66| `MultiProject` | Multi-project templates | All |67| `AOT` | Native AOT compilation | macOS |68| `RunOnAndroid` | Build, install, run on Android emulator | macOS |69| `RunOniOS` | iOS simulator tests (class-level category on `AppleTemplateTests`) | macOS |70| `Samples` | Sample project builds | All |7172**Note**: The `RunOniOS` category is applied at the **class level** on `AppleTemplateTests`. Individual test methods don't need their own category attribute.7374## Writing Integration Tests7576### Basic Pattern7778```csharp79[Test]80[Category(Categories.Build)]81[TestCase("maui", DotNetCurrent, "Debug")]82[TestCase("maui", DotNetCurrent, "Release")]83public void Build(string id, string framework, string config)84{85 var projectDir = TestDirectory;86 var projectFile = Path.Combine(projectDir, $"{Path.GetFileName(projectDir)}.csproj");8788 // Create from template89 Assert.IsTrue(DotnetInternal.New(id, projectDir, framework),90 $"Unable to create template {id}.");9192 // Build93 Assert.IsTrue(DotnetInternal.Build(projectFile, config, properties: BuildProps),94 $"Project failed to build.");95}96```9798### Device Test Pattern (iOS)99100```csharp101[Test]102[Category(Categories.RunOniOS)]103[TestCase("maui", "Release", DotNetCurrent, RuntimeVariant.Mono, null)]104public void RunOniOS(string id, string config, string framework, RuntimeVariant rv, string? trimMode)105{106 // Create and build107 Assert.IsTrue(DotnetInternal.New(id, projectDir, framework));108 Assert.IsTrue(DotnetInternal.Build(projectFile, config,109 framework: $"{framework}-ios",110 properties: buildProps,111 runtimeIdentifier: TestEnvironment.IOSSimulatorRuntimeIdentifier));112113 // Run with XHarness (omit UDID to let XHarness control simulator lifecycle)114 Assert.IsTrue(XHarness.RunAppleForTimeout(appPath, resultDir, TestSimulator.XHarnessID));115}116```117118### Platform Guards119120```csharp121if (!TestEnvironment.IsMacOS)122 Assert.Ignore("Running Apple templates is only supported on macOS.");123124if (!TestEnvironment.IsWindows)125 Assert.Ignore("Running Windows templates is only supported on Windows.");126```127128## Key Classes129130| Class | Purpose |131|-------|---------|132| `BaseBuildTest` | Base class with `TestDirectory`, `BuildProps`, lifecycle methods |133| `BaseTemplateTests` | Extends BaseBuildTest with template-specific setup |134| `DotnetInternal` | Wraps `dotnet` CLI using local SDK (`.dotnet/dotnet`) |135| `XHarness` | Runs apps on devices/simulators |136| `Simulator` | iOS simulator management (boot, shutdown, UDID) |137| `TestEnvironment` | Platform detection, paths, `IOSSimulatorRuntimeIdentifier` |138| `FileUtilities` | File manipulation helpers |139140## Template IDs141142- `maui` - .NET MAUI App143- `maui-blazor` - .NET MAUI Blazor Hybrid App144- `maui-blazor-web` - .NET MAUI Blazor Web Solution145- `mauilib` - .NET MAUI Class Library146- `maui-multiproject` - .NET MAUI Multi-Project App147148## Running Tests Locally149150### 🚨 ALWAYS Use the Skill151152**When asked to run integration tests, ALWAYS use the `run-integration-tests` skill:**153154```powershell155# macOS examples156pwsh .github/skills/run-integration-tests/scripts/Run-IntegrationTests.ps1 -Category "macOSTemplates" -SkipBuild -SkipInstall -SkipXcodeVersionCheck157pwsh .github/skills/run-integration-tests/scripts/Run-IntegrationTests.ps1 -Category "RunOniOS" -SkipBuild -SkipInstall -SkipXcodeVersionCheck158pwsh .github/skills/run-integration-tests/scripts/Run-IntegrationTests.ps1 -Category "RunOnAndroid" -SkipBuild -SkipInstall159160# Windows examples161pwsh .github/skills/run-integration-tests/scripts/Run-IntegrationTests.ps1 -Category "WindowsTemplates" -SkipBuild -SkipInstall162pwsh .github/skills/run-integration-tests/scripts/Run-IntegrationTests.ps1 -Category "Build" -SkipBuild -SkipInstall163```164165The skill handles:166- ✅ Environment variable setup (`MAUI_PACKAGE_VERSION`, `SKIP_XCODE_VERSION_CHECK`)167- ✅ Cross-platform support (Windows and macOS)168- ✅ Test results in TRX format169- ✅ Proper error reporting170171See `.github/skills/run-integration-tests/SKILL.md` for full documentation.172173---174175### Prerequisites (Manual Setup)176177If the skill reports missing prerequisites, provision the local SDK:1781791. **Provision the local SDK and workloads** - The `.dotnet/` folder must contain a fully provisioned .NET SDK with MAUI workloads. Run:180181```bash182 # Step 0: Restore repo-local tools (Cake, etc.) from .config/dotnet-tools.json183 dotnet tool restore184185 # Step 1: Download the .NET SDK (creates .dotnet/dotnet binary)186 dotnet cake --target=dotnet187188 # Step 2: Install MAUI workloads into the local SDK (takes ~5 minutes)189 dotnet cake --target=dotnet-local-workloads190```191192 **Verification**: After provisioning, verify the setup:193```bash194 # Check dotnet binary exists195 ls .dotnet/dotnet196197 # Check MAUI workloads are installed198 ls .dotnet/packs/Microsoft.Maui.Sdk199```200201### Environment Variables (Reference)202203The skill sets these automatically, but for manual runs:204205| Variable | Required | Purpose |206|----------|----------|---------|207| `MAUI_PACKAGE_VERSION` | Yes | Version of MAUI packages being tested |208| `IOS_TEST_DEVICE` | No | iOS simulator target (e.g., `ios-simulator-64_18.5`) |209| `SKIP_XCODE_VERSION_CHECK` | No | Set to `true` to bypass Xcode version validation |210211### Manual Run Commands (Fallback Only)212213**⚠️ Only use these if the skill is unavailable:**214215```bash216# Set environment first217export MAUI_PACKAGE_VERSION=$(ls .dotnet/packs/Microsoft.Maui.Sdk | head -1)218export SKIP_XCODE_VERSION_CHECK=true219220# Run specific category221dotnet test src/TestUtils/src/Microsoft.Maui.IntegrationTests \222 --filter "Category=Build"223224# Run specific test225dotnet test src/TestUtils/src/Microsoft.Maui.IntegrationTests \226 --filter "FullyQualifiedName~AppleTemplateTests.RunOniOS"227```228229## Common Pitfalls230231| Issue | Solution |232|-------|----------|233| Template not found | Verify workloads installed, `MAUI_PACKAGE_VERSION` set |234| Xcode version mismatch | Set `SKIP_XCODE_VERSION_CHECK=true` |235| Device/simulator not found | Verify `IOS_TEST_DEVICE` or emulator is running |236| XHarness timeout on iOS | Expected behavior - app runs until timeout |237| Architecture mismatch | Use `TestEnvironment.IOSSimulatorRuntimeIdentifier` |238239## Best Practices240241### DO242- Use `BuildProps` from base class for isolation243- Apply `[Category]` at the **class level** when all tests share the same category244- Check platform with `TestEnvironment.Is*` before platform-specific tests245- Use `TestEnvironment.IOSSimulatorRuntimeIdentifier` for iOS builds246- Include meaningful assertion messages247248### DON'T249- Hardcode paths - use `TestDirectory`, `TestEnvironment` helpers250- Add `[Category]` to each test method when the class has a category251- Skip platform guards for platform-specific tests252- Hardcode iOS runtime identifiers (arm64 vs x64)253
Also in dotnet/maui
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| dotnet/maui.github/instructions/collectionview-handler-detection.instructions.md · 23k | Copilot instructions | stylegitdo-not | 73/100 | 3 days ago | |
| dotnet/maui.github/copilot-instructions.md · 23k | Copilot instructions | setuptestlint-formatstyle+6 | 76/100 | 3 days ago | |
| dotnet/maui.github/instructions/android.instructions.md · 23k | Copilot instructions | buildstyle | 70/100 | 3 days ago | |
| dotnet/maui.github/instructions/ci-copilot-pipeline-security.instructions.md · 23k | Copilot instructions | gitsecuritydeploymentdo-not+1 | 76/100 | 3 days ago | |
| dotnet/maui.github/instructions/collectionview-android.instructions.md · 23k | Copilot instructions | stylearchperformanceagent-behaviour | 52/100 | 3 days ago | |
| dotnet/maui.github/instructions/collectionview-ios.instructions.md · 23k | Copilot instructions | styleperformance | 48/100 | 3 days ago | |
| dotnet/maui.github/instructions/collectionview-windows.instructions.md · 23k | Copilot instructions | stylearch | 52/100 | 3 days ago | |
| dotnet/maui.github/instructions/handler-patterns.instructions.md · 23k | Copilot instructions | styledo-not | 55/100 | 3 days ago | |
| dotnet/maui.github/instructions/helix-device-tests.instructions.md · 23k | Copilot instructions | setupbuildtestarch | 74/100 | 3 days ago | |
| dotnet/maui.github/instructions/layout-system.instructions.md · 23k | Copilot instructions | archapiperformancedo-not | 55/100 | 3 days ago | |
| dotnet/maui.github/instructions/performance-hotpaths.instructions.md · 23k | Copilot instructions | styleperformancedo-not | 55/100 | 3 days ago | |
| dotnet/maui.github/instructions/public-api.instructions.md · 23k | Copilot instructions | apido-not | 59/100 | 3 days ago | |
| dotnet/maui.github/instructions/safe-area-ios.instructions.md · 23k | Copilot instructions | stylegit | 43/100 | 3 days ago | |
| dotnet/maui.github/instructions/sandbox.instructions.md · 23k | Copilot instructions | buildteststyletesting-strategy+4 | 81/100 | 3 days ago | |
| dotnet/maui.github/instructions/templates.instructions.md · 23k | Copilot instructions | buildteststylearch+1 | 92/100 | 3 days ago | |
| dotnet/maui.github/instructions/threading-async.instructions.md · 23k | Copilot instructions | styleui | 48/100 | 3 days ago | |
| dotnet/maui.github/instructions/uitests.instructions.md · 23k | Copilot instructions | setupbuildteststyle+5 | 79/100 | 3 days ago | |
| dotnet/maui.github/instructions/xaml-unittests.instructions.md · 23k | Copilot instructions | teststyledocs | 70/100 | 3 days ago |
Diff against .github/instructions/collectionview-handler-detection.instructions.md Diff against .github/copilot-instructions.md Diff against .github/instructions/android.instructions.md Diff against .github/instructions/ci-copilot-pipeline-security.instructions.md Diff against .github/instructions/collectionview-android.instructions.md Diff against .github/instructions/collectionview-ios.instructions.md Diff against .github/instructions/collectionview-windows.instructions.md Diff against .github/instructions/handler-patterns.instructions.md Diff against .github/instructions/helix-device-tests.instructions.md Diff against .github/instructions/layout-system.instructions.md Diff against .github/instructions/performance-hotpaths.instructions.md Diff against .github/instructions/public-api.instructions.md Diff against .github/instructions/safe-area-ios.instructions.md Diff against .github/instructions/sandbox.instructions.md Diff against .github/instructions/templates.instructions.md Diff against .github/instructions/threading-async.instructions.md Diff against .github/instructions/uitests.instructions.md Diff against .github/instructions/xaml-unittests.instructions.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| dotnet/roslyn.github/instructions/Compiler.instructions.md · 21k | Copilot instructions | buildteststylearch+3 | 99/100 | 3 days ago | |
| dotnet/roslyn.github/copilot-instructions.md · 21k | Copilot instructions | buildteststylearch+3 | 97/100 | 3 days ago | |
| ardalis/CleanArchitecture.github/copilot-instructions.md · 18k | Copilot instructions | buildteststylearch+4 | 96/100 | 3 days ago | |
| dotnet/maui.github/instructions/templates.instructions.md · 23k | Copilot instructions | buildteststylearch+1 | 92/100 | 3 days ago | |
| we-promise/sure.github/copilot-instructions.md · 9.3k | Copilot instructions | setuptestlint-formatstyle+10 | 88/100 | 2 days ago | |
| microsoft/WSL.github/copilot-instructions.md · 33k | Copilot instructions | setupbuildtestlint-format+7 | 88/100 | 3 days ago | |
| PowerShell/PowerShell.github/instructions/start-native-execution.instructions.md · 55k | Copilot instructions | buildstylearchgit+1 | 86/100 | 3 days ago | |
| hackiftekhar/IQKeyboardManager.github/copilot-instructions.md · 17k | Copilot instructions | setupbuildtestarch+5 | 85/100 | 3 days ago |
