Ask a Question

Help! lightweight find method for flex/flash application needed.

SOLVED
Antonio_Haynes
Contributor

Help! lightweight find method for flex/flash application needed.

Hello,
 I have implimented a basic find method to locate objects in my tested application. 

Method Below:

 

function Get_Control(PropName, PropVal){
 //Creates arrays of property names and values
 propArray = PropName.split(",");
 valuesArray = PropVal.split(",");

 // Searches for the control
 var p = Project.Variables.Process;
 // Depth at 1000 because we do not know where the control might be.
 Project.Variables.Control = p.Find(propArray, valuesArray, 1000);

 // Processes the search results
 if (Project.Variables.Control.Exists){
  Log.Message(Project.Variables.Control.Name);
 }
 else{
  if(!Project.Variables.Optional){
   Log.Message("Failed to Identify an object by the property value specified.", PropName + " " + PropVal)
   Log.Error("The object was not found.");
  }
  else{
   Project.Variables.MoveToNextStep = true;
  }
 }
}

 

This method works woderfully when i am in the login screen of my application wich has maybe 20 controls to sort through.
However once logged into my application there are thousands of controls to sort through and i have seen up to 3 minute wait times before a control is found, if i am lucky.
One other thing that happens when trying to find a control using this method, there is a constant growth in memory usage on my machine between my browser and Test Complete. I have tried finding ways to disable caching of objects during playback and set my name mapping to Do not store Code Completion data, wich helped a little on the memory usage.
I am running Windows 7 64bit OS with 6GB ram and after disabling store code completion data, im left with about 50 mb ram by the time my control is found now.
Test Complete runs at about 200,000 kb ram during normal use and my Fire fox is about 250,000kb during normal use with TC.
I have watch these processes reach the millions while executing the find operation and even crashed TC a few times.

I hope to use a method like this to find the control I intend to work with, but taking anything more than a few seconds to find a control is not acceptable when there may be hundreds of controls needed in a single test.
Please help me on this, I need something fast and lightwieght enough to not max my proccessor.
This method is the heart of my project, if i can't effectivly find my controls, then i don't have anything to work with.
I would also like to avoid name mapping as our developers do daily releases and while the properties of the controls users can see on the page don't normally change, we see alot of containers and wrappers that are dynamically generated and even some containers that do not exist between browsers. Name mapping for this particular test environment has created a nightmare for my team and become more work than i feel we can keep up with, this project is an attempt to resovle some of those issues.


The tested application I am working with is a flex/flash application and my tests must be able to execute against IE, FireFox, and Chrome.

Thanks, and feel free to ask for more information if i've left something out.

17 REPLIES 17
Antonio_Haynes
Contributor

I went ahead and took the liberty to record a jing of my recource monitor when running this test.
The test is a simple log in and then one object trying to be found and clicked once logged in.
I felt it may be important to share this info in the scenario this may be a bug or something someone knows how to fix.
Jing

Thanks.

Please any help would be very much appreciated, I would like to add that when the object does not exist on the page the find fails in no time flat but if the object does exeist that is when i recieve the long wait time.

We had a similar experience with flash/flex automation. We reached the conclusion it was because our application had layers inside of layers, inside of layers, inside of layers...

 

Eventually we gave up flash automation.

LinkedIn 😄 "A SQL query walks into a bar and sees two tables. Walks up to them and says 'Can I join you?'"

Thanks for the response, I was getting worried my post had been lost.
Unfortunatly you are correct there are many layers, in fact once logged in, unless its a dialog, every control is "visible" to testcomplete.
Also I do not have the luxury to not automate the testing for this project, Its not up to me. 😞

There has got to be a way to do what i need done. If i can figure this issue out, the solution it leads to is downright awesome.
The end goal is a method that can identify objects by their property name/values and do it fast and without killing TC due to memory usage. Thanks!

Wrote these functions for you to test. I'm curious if it is any quicker for you.

I tested on a form with about 8000+ controls and it returns in approx 6 seconds.

Not great...but better than 2 minutes I guess Robot Indifferent.

[Edit] removed the second split in findobject function (was used in testing)

 

function Get_Control(PropName, PropVal){
 //Creates arrays of property names and values
 propArray = PropName.split(",");
 valuesArray = PropVal.split(",");

 // Searches for the control
 var p = Project.Variables.Process;
 // Depth at 1000 because we do not know where the control might be.
 Project.Variables.Control = findobject(p, propArray, valuesArray, 1000);
 
 // Processes the search results
 if (Project.Variables.Control.Exists){
  Log.Message(Project.Variables.Control.Name);
 }
 else{
  if(!Project.Variables.Optional){
   Log.Message("Failed to Identify an object by the property value specified.", PropName + " " + PropVal)
   Log.Error("The object was not found.");
  }
  else{
   Project.Variables.MoveToNextStep = true;
  }
 }
}

function findobject(parentObject,propArray,valuesArray,depth) {
//propArray = propArray.split(",");
//valuesArray = valuesArray.split(",");
parentObject.Refresh();
/*
  check all visibleonscreen first
*/
var VOSArray = parentObject.FindAll(["Visible","VisibleOnScreen"],[true,true],depth,false).toArray();
var tmpObj = matchproperty(VOSArray, propArray, valuesArray,depth);

/*
  check all not visibleonscreen
*/
if (!tmpObj.Exists) {
  var NOVOSArray = parentObject.FindAll(["Visible","VisibleOnScreen"],[true,false],depth,false).toArray();
  var tmpObj = matchproperty(NOVOSArray, propArray, valuesArray,depth);
}
CollectGarbage();
return tmpObj;
}

function matchproperty(objArray, propArray, valuesArray) {
/*
  testcomplete wild card replacement
  .* same as * , . same as ?

  reverse the objArray so a top-down (as per the obj browser) ascending search is performed
*/
objArray = objArray.reverse();

/*
  iterate objArray and propArray to determine matching object
*/
for (var o = 0; o < objArray.length; o++ ) {
  for (var p = 0,match = true; p < propArray.length;p++) {
    if (!aqObject.IsSupported(objArray[o], propArray[p])) {
      match = false;
      break;
    }
    var objval =  objArray[o][propArray[p]];      
    var searchresult = RegExp("^" + valuesArray[p] + "$","i").exec(objval);
    if (!searchresult || searchresult.index != 0) {
      match = false;
      break;
    }
  }
  if (match) {return objArray[o];}
}

/*
  if no match return stub object
*/
return Utils.CreateStubObject();
}

 


''-Praise the sun and Give Kudos.''

Thanks for the reply!!! 
As a visual to what I am working with, Here is a jing of the tested appliction expanded in the Object Browser.
Sorry for the quick run through i tried doing a slower scroll later in the video.

I will try your methods and get back to you, Thanks for the input!

So I'm trying to impliment your methods and failing to bring back any objects from them every time.

the issue falls in the line of code below found in your matchproperty method:

if (!aqObject.IsSupported(objArray[o], propArray[p])) {

In an example the first control this runs against in my application is of ObjectType Image
the propArray has a value of ObjectLabel
the ObjectType Image does have a property for ObjectLabel yet aqObject.IsSupported is returning false.
It returns false for every control found.

[edit]

It seems that propArray[0] evaluates to undefined.
When propArray only has one value it is passed into the method as a string, the same is true for valuesArray.

all i need is a way to explicitly define as an array inside of the method in the scenario there is only one propname/value entry.


Thanks!

 

[Update]
After executing your methods i find an almost equivalent amount of time used to identfy controls once logged in.
😞 Thanks for the effort but there seems to be too many objects to run through .... im going to have to figure out a way to narrow down the parent and work with children closer to the object im looking to identify. i still want to do this with out heavy reliance on name mapping if possible.

AlexKaras
Community Hero

Hi Antonio,

 

You are searching for the control from the Process root. Any real reason to force TestComplete to traverse the whole objects tree? My preference in this case is to start search as close to the expected control's location as possible. I.e. if you expect control to be on some specific window - start search from this window, if the control is on some tabbed panel - start search from there. To say the truth, I can hardly imagine the test case that says something like "search for the SSN control throughout the application and populate it with the patient's SSN". More likely is that the test says "while on the Patient Properties form, enter patient's SSN into the SSN field". So searching for the SSN control from the Patient Properties root you'll get two benefits: a) the search will be faster; and b) if the control is not found this will let you know that something changed in the form's design and this might be a problem worth to be reported.

Regards,
  /Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================
Ryan_Moran
Valued Contributor

Alex,

....that is exactly what Antonio already said.

 

Antonio,

I was able to improve performance a bit...at least in my tests this returns in about 1/4 the time.

 

 

function main() {
var wshell = new ActiveXObject('WScript.Shell');
var start = new Date().getTime();
var parent = //your parent object
mychild = findobject(parent,"Name",".*yourcontrolname.*",5000);
wshell.popup("Time executed: " + (((new Date().getTime() - start) / 1000)) + "\nFound object: " + mychild.exists);
}


function findobject(parentObject,propArray,valuesArray,depth) {
propArray = propArray.split(",");
valuesArray = valuesArray.split(",");
parentObject.Refresh();
/*
  just checking all visible controls
*/
var VOSArray = parentObject.FindAll(["Visible"],[true],depth,false).toArray();
var tmpObj = matchproperty(VOSArray, propArray, valuesArray,depth);
CollectGarbage();
return tmpObj;
}

 

 


''-Praise the sun and Give Kudos.''
cancel
Showing results for 
Search instead for 
Did you mean: