Add resilience to UI tests for frozen/unresponsive apps#34023
Add resilience to UI tests for frozen/unresponsive apps#34023
Conversation
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR improves the reliability of the Appium-based UI test infrastructure by preventing indefinite hangs when the app under test becomes frozen/unresponsive (e.g., iOS layout cycles that block WDA), and by adding a force-termination fallback path.
Changes:
- Add a hard timeout wrapper around select Appium UI interactions and polling queries to fail fast instead of hanging indefinitely.
- Add a new
forceCloseAppcommand that bypasses Appium/WDA by terminating the app via OS-level commands, and use it as a fallback whencloseApphangs/fails. - Update NUnit TearDown handling to attempt force-close/reset when unresponsive timeouts are detected.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| src/TestUtils/src/UITest.NUnit/UITestBase.cs | Adds TearDown handling intended to force-close/reset when the app becomes unresponsive. |
| src/TestUtils/src/UITest.Appium/HelperExtensions.cs | Introduces RunWithTimeout and applies it to Tap/Click and to the internal Wait(...) polling query calls. |
| src/TestUtils/src/UITest.Appium/Actions/AppiumLifecycleActions.cs | Adds forceCloseApp and wraps closeApp with a 15s timeout + fallback to force-close. |
| if (!task.Wait(timeout.Value)) | ||
| { | ||
| // Signal cancellation (Appium driver won't respect it, but good hygiene) | ||
| cts.Cancel(); | ||
|
|
There was a problem hiding this comment.
On timeout, this code throws while the background task continues running and is never observed. If the underlying Appium call later faults, it can surface as an unobserved task exception (noise/flakiness). Consider attaching a continuation in the timeout path to observe/log task.Exception (OnlyOnFaulted) before throwing.
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
60d8eed to
3c5fc28
Compare
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
/azp run |
Summary
When an app enters an infinite loop (e.g., layout cycle on iOS), WDA (WebDriverAgent) blocks forever waiting for the main thread to become idle. This causes Appium commands to hang indefinitely, which in turn hangs the entire test run.
This PR adds resilience to prevent test hangs and allows graceful failure with clear error messages.
Changes
HelperExtensions.cs
RunWithTimeoutwrapper (45s hard limit) around all Appium commandsTap(),Click(), andWait()query calls with timeoutCancellationTokenSourcefor proper cleanup hygieneTimeoutExceptionwhen app is unresponsiveTask.Run+GetAwaiter().GetResult()to properly unwrap exceptionsAppiumLifecycleActions.cs
ForceCloseAppcommand using OS-level termination:xcrun simctl terminateadb shell am force-stoposascript quitCloseAppwith 15s timeout, auto-falls back toForceCloseAppUITestBase.cs
TimeoutExceptionfor unresponsive apps in TearDownResult
Before: Tests hang indefinitely when app freezes, blocking entire CI run
After: Tests fail gracefully after 45s with clear error message:
Testing
Tested with Issue32586 test case that triggers infinite layout cycle on iOS:
Notes