From 0b0bc77dc969a0cfa76846915e6aab4ad6b2cf63 Mon Sep 17 00:00:00 2001 From: amrali-eg <32075105+amrali-eg@users.noreply.github.com> Date: Thu, 10 Sep 2026 09:59:50 +0300 Subject: [PATCH] Look for the review where it lives, not across the whole desktop Review discovery searched TreeScope.Descendants from the desktop root, which walks every window of every running application - twice whenever the review was absent, because it tried the identifier and then the title. It runs on every 50 ms poll of several waits. Measured before changing anything, by timing the lookups directly rather than inferring from total runtime: 7.9s and 7.8s of a 22.5s suite run on a desktop holding ten windows, against 4.1s and 4.2s on one holding five. The cost tracked what else the machine had on screen, which is not something a test result should depend on. It was noticing that runs went faster with EC alone on a desktop that prompted the measurement. Where the review actually lives was measured too, after a first attempt scoped to the desktop's immediate children found nothing and failed six runs out of six: an owned dialog is not a top-level window. Probing all four scopes while a review was open gives root/children=no, root/descendants=yes, main/children=yes, main/descendants=yes. It sits among the main window's own children, so that is where it is looked for, with identifier or title in one condition instead of two searches. Scoping to the main window also makes the process filter redundant. Automation errors are not caught here. Returning null for one would report the review as absent when the truth is that nothing could be read, and the waits that call this already retry and keep the error - the same erasure this driver has had to fix twice before. Full suite on the same cluttered desktop: 17.3s and 17.6s, against 22.7s and 22.3s before. On a fresh desktop: 17.8s and 17.7s - the gap that tracked desktop clutter is gone, and it is faster than the old best case. Six consecutive runs pass after the corrections, and the unit suite is unchanged at 756. Other descendant searches are left alone. EC is unchanged. Co-Authored-By: Claude Opus 5 --- .../EncodingChecker.GuiSmoke/EcGuiDriver.cs | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/sources/EncodingChecker.GuiSmoke/EcGuiDriver.cs b/sources/EncodingChecker.GuiSmoke/EcGuiDriver.cs index 6e573a6..7da5732 100644 --- a/sources/EncodingChecker.GuiSmoke/EcGuiDriver.cs +++ b/sources/EncodingChecker.GuiSmoke/EcGuiDriver.cs @@ -696,9 +696,30 @@ private static string Safely(Func describe, string whenItFails) } } - private AutomationElement? FindReviewWindow() => - FindProcessElementById("ConversionConfirmationForm") ?? - FindProcessElementByTitle("Review conversion"); + /// The conversion review, if EC currently has one open. + /// + /// The review is an immediate child of the main window, so it is looked for there. + /// Searching the desktop instead means repeatedly walking unrelated applications, on + /// every poll of several waits. + /// + /// Automation errors are deliberately not caught: returning null for one would say + /// the review is absent when the truth is that nothing could be read, and the waits + /// that call this already retry and keep the error. + /// + private AutomationElement? FindReviewWindow() + { + var condition = new AndCondition( + new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window), + new OrCondition( + new PropertyCondition( + AutomationElement.AutomationIdProperty, + "ConversionConfirmationForm"), + new PropertyCondition( + AutomationElement.NameProperty, + "Review conversion"))); + + return MainWindow.FindFirst(TreeScope.Children, condition); + } private int ResultCount() => FindById(MainWindow, "lstResults") is AutomationElement list @@ -893,36 +914,6 @@ private AutomationElement RequireById( return AutomationElement.RootElement.FindFirst(TreeScope.Children, condition); } - private AutomationElement? FindProcessElementById(string automationId) - { - var condition = new AndCondition( - new PropertyCondition( - AutomationElement.ProcessIdProperty, - _process.Id), - new PropertyCondition( - AutomationElement.AutomationIdProperty, - automationId)); - - return AutomationElement.RootElement.FindFirst( - TreeScope.Descendants, - condition); - } - - private AutomationElement? FindProcessElementByTitle(string title) - { - var condition = new AndCondition( - new PropertyCondition( - AutomationElement.ProcessIdProperty, - _process.Id), - new PropertyCondition( - AutomationElement.NameProperty, - title)); - - return AutomationElement.RootElement.FindFirst( - TreeScope.Descendants, - condition); - } - private AutomationElement? FindProcessWindowByTitle(string title) { var condition = new AndCondition(