Forum Discussion

rickm's avatar
rickm
Contributor
6 months ago

Searching for the mapped object "btnYes" took a long time

I've been running TestComplete for 13 years now. I have over 1100 tests, all created with the recording function and letting TC take care of all name mapping. This is with an Open App. Nothing browser related, etc.

One thing I've never had to get much involved with is Name Mapping. In recent years, certain message boxes have become very slow. Instead of a fraction of a second, it can take 20 to 30 seconds just to click a "Yes" button. When it takes more than about 10 seconds, I get the TC warning:

"Searching for the mapped object "btnYes" took a long time. This happened because the sought-for object has the Extended Find attribute enabled, and the test engine searched for this object on all levels down the object hierarchy. To speed up the search and improve the test performance, add more parent objects of this object to the Mapped Objects tree of Name Mapping."

I tried turning off the Extended Find but then some objects couldn't be found at all.

I think I can see why the search is necessary, but don't know what to tweak in the Name Mapping to fix this.

Dialogs that process button presses immediately have FullNames and MappedNames that have the same object hierarchies. Quoting one from the "Details" panes of a log file, it looks like this:

Tested object:
Aliases.MyApp.SaveChangesForm.CommitPanel.NoButton
(Sys.Process("MyApp").VCLObject("SaveChangesForm").VCLObject("CommitPanel").VCLObject("NoButton"))

One that takes a long time looks like this:

Tested object:
Aliases.MyApp.dlgMyAppError.btnYes
(Sys.Process("MyApp").Window("#32770", "MyApp", 1).Window("Button", "&Yes", 1))

If I bypass the name mapping search and insert "Run Code Snippet" into my keyword test with the string Sys.Process("MyApp").Window("#32770", "MyApp", 1).Window("Button", "&Yes", 1), it runs in a fraction of a second. That doesn't make sense to me. If the run log Details (and the Object Spy) can list both the Alias and the FullName, why does it take so long to find the FullName (and the button) while running?

We're hoping not to have to change our code PLUS the thousands of button click events in our keywordTests!

The Yes button seems to have the main MyApp as it's parents. We think the problem has something to do with the dynamic nature of the message boxes used. The programmer described this:

"The tested application displays many message boxes (900+) using Win32 MessageBoxA. The arguments to MessageBoxA are the handle of the active window, the message text, the title, and the style of the message box, e.g., MB_YESNOCANCEL | MB_ICONWARNING. We call MessageBoxA from thin wrapper functions such as userError(), userMessage(), debugMessage(), assertMessage(). We tested replacing MessageBoxA in several instances with the newer TaskDialog and it made no difference to the time taken for TC to find the object."

I'm running TestComplete Version: 15.62.2.7 x64 on Windows 10.

Our Windows development and build environment:

Dell Latitude 3590 x64 16 GB RAM, Win 10 Pro v22H2 Build 19045.4170
Embarcadero C++ Builder 10.4 Update 2

DevExpress ExpressGridPack VCL Products 20.2.5
Easy Compression Library (ECL) 5.92
LeadTools Raster Toolkit Pro 15 (API version) no patch
Parallax69 Eroiica API 5.0.28.0 & tif2rtl.dll (v??? 2012-11-16?)
Indy 10.6.2 IdHTTP
TinyXml 2.5.3
ZipForge 6.93 - Personal Edition

  • I eventually convinced myself that the problem was indeed that the problematic buttons were not _missing_ any mapping, but TC simply mapped them into the wrong place in the Mapped Object list. These maps were created over 10 years ago, obviously with a very old version of TC.

    I couldn't see any way to edit the mapping (just search criteria), so I deleted the 3 buttons from the main program parent in the Mapped Objects (including their aliases). Then I recorded a little keyword test using the 3 buttons to force TC to create new maps. The new maps went into the correct object, the same as the other buttons that do behave properly, and the problem is solved!

    Thanks to all, I sincerely appreciate the help. 

  • rraghvani's avatar
    rraghvani
    Champion Level 3

    Where does the 'Yes' button appear in the Object Browser, hierarchy tree? How many levels down, is it?

    • rickm's avatar
      rickm
      Contributor

      The buttons appear right at the top of the Object Tree in the Object Browser at the first level below the main program, exactly as in the Run Code Snippet call that runs in a fraction of a second. The only Button that shows there at any time is the one that is active on the screen at the time.

       

      v Process("MyApp")

         v Window("#32770", "MyApp", 1)

            v Window("Button", "&Yes", 1)

       

      The Object Spy shows the FullName as this hierarchy which is what works in Run Code Snippet, and shows the Name as Windows("Button", "Yes"", 1), but the MappedName is Aliases.MyApp.dlgMYAPPError.btnYes. The Object name dlgSTRIPLOGError doesn't appear in the Object Tree anywhere. It seems like the mapped name should somehow point to "#32770"?

       

      In the Workspace "NameMapping" tab, in its top section "Mapped Objects", it shows as "NameMapping.Sys.MyApp.btnYes", but below in the Aliases section it appears under "dlgMYAPPError". No mention of #32770 anywhere, but the context menu "Show in Object Browser" in both the top and bottom section of NameMapping find it at the top of the Object Browser.

      • rraghvani's avatar
        rraghvani
        Champion Level 3

        If you are using name mappings, then it's important to get the name mappings correctly defined, to instruct TestComplete on how to locate the object in your tested application.

        If you have the following hierarchy defined in TC,

        • Mapped Object: Sys.Process("MyApp").Window("#32770", "MyApp", 1).Window("Button", "&Yes", 1)
        • Aliases Mapped Object: Aliases.MyApp.dlgMYAPPError.btnYes

         

        Then the following aliases should equal to,

        • MyApp = Process("MyApp")
        • btnYes = Window("Button", "&Yes", 1)
        • dlgMYAPPError = Window("#32770", "MyApp", 1) - my guess is, this is not correctly defined.

         

  • I eventually convinced myself that the problem was indeed that the problematic buttons were not _missing_ any mapping, but TC simply mapped them into the wrong place in the Mapped Object list. These maps were created over 10 years ago, obviously with a very old version of TC.

    I couldn't see any way to edit the mapping (just search criteria), so I deleted the 3 buttons from the main program parent in the Mapped Objects (including their aliases). Then I recorded a little keyword test using the 3 buttons to force TC to create new maps. The new maps went into the correct object, the same as the other buttons that do behave properly, and the problem is solved!

    Thanks to all, I sincerely appreciate the help.