Forum Discussion

liquidphantom's avatar
liquidphantom
Occasional Contributor
6 years ago

FindChild taking a long time TC12

The software I am testing is written in VB6 and has the issue whereby the object names can change every time it is compiled making mapping impossible. To get around this I use the the FindChild method to find the objects every time I need to call them (yes it's tedious) I came up with the following function (VBScript), I also included a timer for debugging which I comment out when not developing.

 

Function Find_ChildObj(VBobj, Idx, Parent, DepthVal)
    Dim StartTime, EndTime, Elapsed

    If DepthVal >= 0 then
        Depth = DepthVal
    Elseif isNull (DepthVal) Then
        Depth = 4
    End If    

    StartTime = aqDateTime.Time
    If isNull (Idx) and isNull (Parent) Then 'When Index and Parent are Null
        PropNames = Array("Name", "Visible")
        PropValues = Array(VBobj,True)
        Set P = Sys.WaitProcess("Base App Name")
        Set child = p.FindChild(PropNames, PropValues, Depth, True)
        'Log.Message("Idx and Parent parameters Null")

    ElseIf isNull (Idx) Then 'When Index is Null
        PropNames = Array("Name", "Visible")
        PropValues = Array(VBobj, True)
        Set P = (Parent)
        Set child = p.FindChild(PropNames, PropValues, Depth, True)
        'Log.Message("Idx Parameter Null")

    ElseIf isNull (Parent) Then 'When Caption is Null
        PropNames = Array("Name", "Index", "Visible")
        PropValues = Array(VBobj, Idx, True)
        Set P = Sys.WaitProcess("Base App Name")
        Set child = p.FindChild(PropNames, PropValues, Depth, True)
        'Log.Message("Parent Parameter Null")

    Else
        PropNames = Array("Name", "Index", "Visible") 'All values present
        PropValues = Array(VBobj, Idx, True)
        Set P = (Parent)
        Set child = p.FindChild(PropNames, PropValues, Depth, True)
        'Log.Message("No Null parameters")
    End IF
    EndTime = aqDateTime.Time
    Elapsed = aqDateTime.TimeInterval(StartTime, EndTime)

    Parent = CStr(P.FullName)

    If Not child.Exists then
        log.Error "Unable to locate child obj of " & Parent, "", pmNormal, LogStyle ("TestFail")
        GeneralEvents_OnLogError
    Else
        Set Find_ChildObj = eval(child.FullName)
        CName = child.FullName
        log.message(Elapsed &" to find " &CName)        
    End If
End Function

This is called in each script with the following

Set ChildObj = Find_ChildObj ("*Partial of Child Name*", ChildIndexNumber, ParentObjectName, Depth)

I can cascade this, so I can find the Parent and then the child so the ChildObj becomes the ParentObjectName in the next call, which makes finding some objects a lot quicker.

 

What I am finding is that in one case an object can be found quickly but in the very next test, called in exactly the same way from on the same screen of the app in test, It can take a very long time to find the object sometimes sometimes a minute or minute and a half.

 

If I take the Depth down to 1 making sure the parent object is included in the call, it can help but then this can throw up another bizarre situation where even though the child is with in depth 1 the child object cannot be found at all and if I increase the depth to 2 it is found but takes a long time again. If I try to store the object then I sometimes have the error that the object does not exist.

 

Generally the function and call works fine and objects are found within a couple of seconds if not milliseconds.

 

Can any one shed some light as to why I am seeing inconsistent performance and success in the call.

 

Btw feel free to use the function if it's of any help.

 

Many thanks

3 Replies

  • tristaanogre's avatar
    tristaanogre
    Esteemed Contributor

    I would not use the "Name" property of an object to find the object.  Basically, if you're looking for something via the Name, TestComplete just goes ahead and bypasses all find functionality and attempts to search using the Name as per the Object Browser.  I'd recommend enhancing your function to actually take in the arrays of properties and values instead of just "name" to get more specific and targeted searches.

    • liquidphantom's avatar
      liquidphantom
      Occasional Contributor

      tristaanogre wrote:

      I would not use the "Name" property of an object to find the object.  Basically, if you're looking for something via the Name, TestComplete just goes ahead and bypasses all find functionality and attempts to search using the Name as per the Object Browser.  I'd recommend enhancing your function to actually take in the arrays of properties and values instead of just "name" to get more specific and targeted searches.


              PropNames = Array("Name", "Index", "Visible") 'All values present
              PropValues = Array(VBobj, Idx, True)
              Set P = (Parent)

       

      I almost always use Name (Partial of the vbobject name), Parent and Index.

       

      The VBObject name of the child has to be partial as at compile the object name is often suffixed with a number, for example the Object is called CtlBox becomes CtlBox_12 but the index stays the same.... that is unless a dev ads a new control further up in the pecking order and the controls are re-indexed but that's a very quick change in my script code to fix it.


      I can't use Wnd
      Caption in a lot of situations as most have been written as custom controls in containers due to exceeding the control limit of VB6 and don't have a WndCaption. WndClass is shared by lots of objects and some may have the same index across the whole screen but unique within their own containers.

       

      I'm starting to think that I should resign myself to the long object searches.

       

      Although to toot my own horn, I do manage to run around 160 Units covering 21 tests in roughly 40 minutes compared to my predecessor whom manged 5 scripts covering 1 test in over an hour.

      • tristaanogre's avatar
        tristaanogre
        Esteemed Contributor

        You don't have to use WndCaption and WndClass only... you can pass in any set of properties and corresponding values to find the component. I've found this to be a common mistake among newer users that they look at only the very basic properties and don't look deeper.

         

        So, look beyond just using "Name".  Add other properties to narrow things down to the specific component you're looking for.  INclude things like "Caption" or perhaps text content, label, ObjectIdentifier, etc.  The more directed your Find, the easier it is for TestComplete to find your component.