Test coverage: UI Automation service and capture stack (issue #630)#669
Merged
Conversation
Split RealUiAutomationTests into partial files under the 1000-line cap and harden the ambiguous-selector assertion. Added deterministic pure coverage for screenshot retry/letterbox seams, WGC support/blank/HRESULT helpers, record sizing/retarget/frame helpers, MP4 publish/validation/complete paths, and UiRecordCommand short-description/COM failure handling. Final filtered coverage observed: UiAutomationService.cs 80.0%; UiAutomationService.Record.cs 29.1%; UiAutomationService.Screenshot.cs 81.0%; UiAutomationService.ValueSetStrategy.cs 88.6%; WgcCapture.cs 49.8%; WgcCapture.Record.cs 6.3%; Mp4SinkWriterEncoder.cs 85.2%; RecordModels.cs 100.0%; UiRecordCommand.cs 97.7%. Documented issue #630 ceilings on innermost native WGC/D3D/GDI/MF boundaries and retained real gated capture attempts for hosts that can exercise them. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add deterministic recorder seams for WGC grabbers and MP4 encoders, exercise real in-process record paths, and document native UIA/WGC/Media Foundation coverage ceilings for the remaining host-bound arms. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- H1 (WgcCapture.Record.StartGrabber): dispose pool+session in the catch before rethrow so a fault after pool/session creation can't leak the WGC frame pool or capture session (mirrors FrameGrabber.Dispose order). - M1/L1 (UiAutomationService): remove 27 identical copy-paste ceiling <remarks> blocks (several on fully-covered methods, one duplicated) and replace with a single accurate class-level <remarks>. - M3 (ScrollIntoView test): assert the child's VerticalScrollPercent actually increases (before < after) instead of only "no exception". - M2 (NumericUpDown test): construct the service with a capturing logger and assert the value-set strategy walks ValuePattern -> RangeValuePattern -> LegacyIAccessible (both pattern strategies log a caught failure), a real deterministic assertion of the fallback routing instead of "no throw". - L2: correct a misleading HScrollBar test comment. Test-only + one small product leak fix; no behavior change. Coverage unchanged (documented native ceilings hold). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add real UIA coverage for edge selector, window, slug, and pattern paths with resettable fault-injection seams for native COM failure arms. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The seam-wrapper methods pass 'this' to the static seam, which already satisfies the analyzer; the _ = _logger; discards were dead noise. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add real fixture controls and targeted COM seam tests to cover additional UiAutomationService branches. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Multi-model review finding: ResetNativeSeams() reset only the core navigation seams, while the screenshot seams (s_captureFromWindow, s_captureFromScreenScaled, s_foregroundWindowForBlankRetry, s_sleepForBlankRetry) declared in the Screenshot partial were reset only by duplicated per-test-class cleanup code. No leak existed (each class reset the seams it touched), but the reset contract was incomplete and duplicated. Make ResetNativeSeams the single source of truth for every UiAutomationService static seam by resetting the four screenshot seams to their declared defaults, then drop the now-redundant per-class resets: the reflection-based block in RealUiAutomationTests cleanup and the four resets plus their two orphaned GetReal* reflection helpers in UiAutomationServicePureTests cleanup. Behavior-preserving and test-only; UiAutomationService.cs coverage holds at 95.5%. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
UiAutomationService.ValueSetStrategy.cs documented the RangeValuePattern success line and the LegacyIAccessible COM-failure catch arm as coverage ceilings, claiming the deterministic WinForms fixture could not expose them. That is no longer accurate: SetValueAsync resolves its COM element through the seam-injectable ResolveComElement, so the same ComProxy COM fault-injection used elsewhere in the suite drives these arms directly. Add two targeted tests via SetValueAsync: - RangeValuePattern success after ValuePattern is unavailable (proxy ValuePattern throws, proxy RangeValuePattern.SetValue records the value). - LegacyIAccessible SetValue COM fault is logged and surfaces the send-keys hint (non-numeric text skips RangeValue; proxy legacy pattern throws), asserting both the thrown message and the captured debug log. Remove the stale "coverage ceiling" remarks now that both arms are covered. UiAutomationService.ValueSetStrategy.cs goes 88.6% -> 100%. Test-only plus doc-comment removal; no behavior change. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Raises per-file test coverage for the UI-Automation service and its capture/record stack toward the >=95% bar from issue #630. This is a test-coverage PR: the bulk is new tests plus a small set of behavior-preserving
internal staticseams that let real COM-fault paths be driven deterministically. No[ExcludeFromCodeCoverage], nocoverage.runsettingsexclusions, no service exclusions - hard-to-test paths get real tests, minimal seams, or a source-documented genuine ceiling.Net: 19 files, +4,295/-34 (mostly new
RealUiAutomationTests.*partials,UiAutomationServicePureTests, the liveUiaTestFixture, andDesktopTestHelpers).Coverage - in-scope product files
UiAutomationService.csUiAutomationService.ValueSetStrategy.csComProxyThe 69 residual lines in
UiAutomationService.csare genuine ceilings: COM-faultcatch {}swallows, defensivebreaks during liveTreeWalkerwalk-ups, and native owned-window enumeration (GetAllAppWindows) that in-process UIA already resolves through its primary pass. Each is a single native-boundary arm, documented at the call site.Documented native ceilings (GPU / WGC / Media Foundation)
These files exercise the genuinely native capture+encode stack - GPU frame delivery, a live
Windows.Graphics.Capturesession, and Media Foundation sink writers - which cannot run deterministically/headlessly on a shared desktop. Interactive-only tests cover what they can; the residual is a hardware/OS boundary, documented in-source with<remarks>:WgcCapture.csWgcCapture.Record.csUiAutomationService.Screenshot.csUiAutomationService.Record.csMp4SinkWriterEncoder.csApproach
UiaTestFixture(buttons, text/value/multiline, checkboxes, list, scroll panel + nested children, combo, tabs, tree, slider, progress, numeric, owned window) drives the service against real providers. Real-UIA tests self-skip viaAssert.Inconclusiveoff an interactive desktop, so CI is never blocked - no assertion is suppressed.internal static Funcseams (e.g.s_getRootElement,s_elementFromHandle,s_getDesktopRootElement,s_getMainWindowHandleForProcessId) default to the exact original expression and are restored byResetNativeSeams()in[TestCleanup]; production never reassigns them.ComProxy<T>(DispatchProxy) fakes the COM interfaces to fault-inject specific arms - always againstEnvironment.ProcessId, never a foreign PID.Review & validation
f5bfa899): a WGC grabber leak on theStartGrabbercatch path, plus assertion-strengthening on Scroll/NumericUpDown fallback-routing tests.ResetNativeSeams()was not the single source of truth for all UIA seams; consolidated in395d74fb(screenshot seams now reset centrally; duplicated per-class reflection resets removed). No leak existed, but the reset contract is now complete.Record_WebView2StyleCompositedContenttest); the real-UIA tests ran for real. New COM-proxy tests re-run clean across repeats (deterministic).Base note
Branches off current
main, which includes the #654 revert of the #629/#647 NuGet-client migration. No UIA scope overlaps that revert.