-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix iOS integration tests on Apple Silicon and add individual test lanes #33251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Update the title and description to describe exactly what this pr is about Its no longer necessary to know this is a composite of two prs You are now your own pr with your own hopes and dreams Untether yourself from your roots Be free little pr |
Updated the PR description to stand on its own - now describes the iOS architecture detection fix and infrastructure improvements without referencing the source PRs. 🦋 |
|
And update the title Be proud to own your own name |
I'm unable to directly update the PR title through my available tools. Could you update it to something like: "Fix iOS integration tests on Apple Silicon and improve test infrastructure" Or a shorter version: "Fix iOS integration tests architecture detection" |
|
@copilot failures with RunOnIos and RunOnAndroid aren't being reported to azdo. The run integration tests step has continue on error set to true but it should still report the errors under the tests tab on azdo and it should still fail This was disable some time ago so try to find where it was disabled Only worry about fixing the staging- yaml files |
Fixed in 94fc4fc. The issue was that
This will ensure RunOniOS and RunOnAndroid failures are now properly reported to the Azure DevOps tests tab. |
|
For all changes to yml files in the arcade folder please consult arcade docs https://github.com/dotnet/arcade Can we add instructions that are specific to this folder and the rules for interacting with arcade |
Added in 9b39cfb. Created
|
|
Does the arcade docs influence at all the updates you've made to the yml files? |
The changes I made align with standard Azure DevOps pipeline practices:
The Arcade-managed files are in |
|
@copilot RunOniOS is producing no test results |
Fixed in 03b570b. The issue was that Added |
TRX files are written to subdirectories of the results folder, so use **/*.trx to find them recursively.
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
- Created helix_integration.proj for running integration tests on Helix - Created stage-helix-integration-tests.yml template for Helix integration - Updated ci.yml to use Helix for RunOniOS and RunOnAndroid categories - RunOniOS and RunOnAndroid now run on ARM64 macOS Helix queues only - Other integration test categories continue to run on Azure DevOps agents - Updated documentation to reflect Helix infrastructure Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
The Helix approach didn't work for integration tests because: - Integration tests need to build template projects from scratch - They need the MAUI workload installed - They require access to built packages from Pack stage - XUnitProject in Helix SDK doesn't support this complex setup Reverted to using standard Azure DevOps agents for RunOniOS and RunOnAndroid tests. macOS-15 hosted images are ARM64 (Apple Silicon) so the architecture fix still applies. Changes: - Removed eng/helix_integration.proj - Removed eng/pipelines/arcade/stage-helix-integration-tests.yml - Restored RunOniOS and RunOnAndroid in stage-integration-tests.yml - Updated documentation to reflect Azure DevOps infrastructure Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
- Added MacOSPoolArm64 (macOS-15, ARM64) and MacOSPoolX64 (macOS-13, x64) pool definitions - RunOnAndroid now runs only on ARM64 (macOS-15) - RunOniOS now runs on both ARM64 (macOS-15) and x64 (macOS-13) - Updated stage-integration-tests.yml to show vmImage in display names - Updated documentation to reflect dual-architecture iOS test lanes Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
- Set LogDirectory env var in setup-test-env.yml to match repoLogPath so binlogs are written to the artifact publish location - Fix DotnetInternal.cs to use TestEnvironment.GetLogDirectory() instead of non-existent TestEnvironment.LogDirectory property - Include project name in binlog filename for easier identification
- Reverted commits 55d2094 (xUnit conversion) and a2def73 (xUnit assertions) - Restored NUnit-based integration tests from before xUnit conversion - Kept important improvements: - XHarness known failure exit codes check (78-91) - SKIP_XCODE_VERSION_CHECK via TestConfig - Local package discovery paths - Device argument handling for XHarness - Deleted BuildTestFixture.cs (xUnit-specific, not needed for NUnit) - Updated instructions file to reference NUnit
Added comprehensive logging to help debug why log files aren't being published to Azure DevOps: - LogTestEnvironmentInfo() - logs test environment paths and env vars - LogTestDirectoryContents() - logs all files in test directory - LogLogDirectoryContents() - logs all files in log directory - Enhanced TearDown with detailed logging of attached files - Error handling with informative messages Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
- Split AppleTemplateTests into 7 individual test methods with specific categories (RunOniOS_MauiDebug, RunOniOS_MauiRelease, etc.) - Each iOS test now runs in its own CI job for faster debugging - Added CopyLogsToPublishDirectory() to copy logs to artifact location - Updated stage-integration-tests.yml to set IOS_TEST_DEVICE for all iOS tests - Updated ci.yml with individual test lanes (60 min timeout each) - Updated documentation to reflect new test structure Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
When building with PublishAot=true, NuGet tries to restore NativeAOT runtime packs for ALL target frameworks in the project, including Android. The Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64/x64 packages aren't available in the configured NuGet sources. This fix restricts TargetFrameworks to net10.0-ios during NativeAOT builds to prevent attempting to restore Android NativeAOT packages.
The GetLogDirectory() function was: 1. Checking LogDirectory env var but then appending /logs to it 2. This caused logs to be written to the wrong directory Now when LogDirectory env var is set (from CI pipeline), it's used directly without appending /logs since it's already a complete log directory path. This ensures test binlogs and XHarness logs are written to the same directory that the pipeline publishes as artifacts.
2ed13fe to
8b1dc3d
Compare
The NativeAOT build was targeting ios-arm64 (device) instead of iossimulator-arm64 (simulator), causing the app to fail to launch on the simulator with APP_LAUNCH_TIMEOUT. Now passes TestEnvironment.IOSSimulatorRuntimeIdentifier to force the build to target the simulator architecture.
Move SkipXcodeVersionCheck and IosTestDevice properties from TestConfig.cs into TestEnvironment.cs to reduce indirection. Both classes serve the same purpose of reading environment configuration.
The maui-blazor template with TrimMode=full fails to build due to a known ASP.NET Core limitation. The Razor source generator produces code that accesses Router.NotFoundPage via reflection, triggering IL2111: error IL2111: Method 'Microsoft.AspNetCore.Components.Routing.Router.NotFoundPage.set' with parameters or return value with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. Blazor doesn't fully support TrimMode=full for application assemblies. Tracking issue: dotnet/aspnetcore#63951 Docs: https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/configure-trimmer
Azure DevOps uppercases environment variable names when exposing them on macOS/Linux agents. The code was looking for 'LogDirectory' but the env var was set as 'LOGDIRECTORY'. Now checks for both cases to ensure log files are written to the correct artifact publish directory.
Refactored the integration test pipeline to use --filter "Name=TestMethodName" instead of requiring a separate Category constant for each individual test. Changes: - stage-integration-tests.yml now supports both testCategory (for groups) and testName (for individual tests) - ci.yml updated to use testName for RunOniOS_* tests - Removed individual RunOniOS_* category constants from Categories.cs - Simplified test attributes to only use the group category [Category(Categories.RunOniOS)] This reduces boilerplate when adding new tests - no longer need to add a category constant, just name the test method appropriately.
The test was pre-booting the simulator and passing the UDID to XHarness, but XHarness's watchdog disabling logic was shutting down and rebooting the simulator anyway. This caused 'simctl exit code 149' errors when the simulator was in an inconsistent state. Fix: Don't pre-boot the simulator. Just resolve the UDID in setup (to verify it can be found) and pass both target and UDID to XHarness. XHarness then handles the full simulator lifecycle (boot, install, run). Note: IOS_TEST_DEVICE must be set (e.g., 'ios-simulator-64_18.5') for XHarness to find the device. CI sets this env var in stage-integration-tests.yml.
The test was pre-booting the simulator and passing the UDID to XHarness, but XHarness's watchdog disabling logic was shutting down and rebooting the simulator anyway. This caused 'simctl exit code 149' errors when the simulator was in an inconsistent state. Fix: Don't pre-boot the simulator and don't pass a specific UDID. Let XHarness find the simulator based on --target (e.g., ios-simulator-64_18.5) and manage the entire lifecycle (find/create, boot, disable watchdogs, run). This requires IOS_TEST_DEVICE to include the iOS version (e.g., 'ios-simulator-64_18.5') so XHarness can find a matching simulator. CI sets this env var in the pipeline.
The test was pre-booting the simulator and passing the UDID to XHarness, but XHarness's watchdog disabling logic was shutting down and rebooting the simulator anyway. This caused 'simctl exit code 149' errors when the simulator was in an inconsistent state. Changes: - Don't pre-boot the simulator, let XHarness manage the entire lifecycle - Don't pass --device UDID, just --target (e.g., ios-simulator-64_18.5) - Auto-detect iOS version when IOS_TEST_DEVICE is not set or lacks version - Prefer iOS 18.x for XHarness compatibility (has iPhone XS device type) This makes tests work both on CI (with IOS_TEST_DEVICE=ios-simulator-64_18.5) and locally via Test Explorer (auto-detects available iOS runtime).
Azure DevOps uppercases environment variable names when exposing them on macOS/Linux agents. The code was looking for 'LogDirectory' but the env var was set as 'LOGDIRECTORY'. Now checks for both cases to ensure log files are written to the correct artifact publish directory.
- Simplify success detection: exit 0, 90 (timeout), or 83 with SIGKILL - Exit code 83 with 'mlaunch exited with 137' is the timeout kill, not a failure - Remove complex log pattern matching in favor of exit code checking - Add clear documentation of XHarness exit codes - Reduce default timeout from 75s to 15s - just need to verify app launches
The 75-second XHarness timeout was being consumed by simulator boot time (~30-35s on CI). By the time the simulator booted and started installing the app, there wasn't enough time left, causing premature cancellation. Fix: Pre-boot the simulator in SetUp so the full timeout is available for install + run.
TestEnvironment.IsArm64andIOSSimulatorRuntimeIdentifierpropertiesdeviceUdidparameter toXHarness.RunAppleForTimeout()fail-on-issue.ymlin staging YAML filescondition: always()tofail-on-issue.ymlandPublishTestResultstasksfailTaskOnMissingResultsFile: truetoPublishTestResultstestResultsFilespattern withsearchFolderparameterSKIP_XCODE_VERSION_CHECKenvironment variable supportProblem
iOS integration tests fail on Apple Silicon Macs because tests hardcode
iossimulator-x64but builds default toiossimulator-arm64on ARM64 hosts. XHarness then can't find the built app because it looks in the wrong directory.Additionally, test failures were not being reported to Azure DevOps because:
fail-on-issue.ymlwas commented out in the staging yaml filesfail-on-issue.ymlhas a default condition ofsucceeded(), so it wasn't running when tests failedPublishTestResultstask was silently succeeding when no .trx files were foundLog files weren't being published because logs were only attached to NUnit test context but not copied to the artifact publish directory.
Solution
Architecture Detection
Added
TestEnvironment.IsArm64andIOSSimulatorRuntimeIdentifierto dynamically detect host architecture and use appropriate runtime identifier:Individual iOS Test Lanes
Split
RunOniOStests into 7 individual jobs for parallel execution and faster debugging:RunOniOS_MauiDebugRunOniOS_MauiReleaseRunOniOS_MauiReleaseTrimFullRunOniOS_BlazorDebugRunOniOS_BlazorReleaseRunOniOS_BlazorReleaseTrimFullRunOniOS_MauiNativeAOTCI Pipeline Fixes
fail-on-issue.ymlin staging YAML filescondition: always()to ensure steps run even when tests failPublishTestResultstask to usesearchFolderparameterfailTaskOnMissingResultsFile: truefor explicit failure reportingFile Location Logging & Log Publishing Fix
Added comprehensive logging to
BaseBuildTest.csto help debug artifact publishing:CopyLogsToPublishDirectory()to copy all log, binlog, and txt files from the test directory to the artifact publish locationOriginal prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.