Technical: How QTP identifies Objects

How QuickTest Professional Identifies Objects

-- A post by Motti Lanzkron from QTP R&D

 

Note: The following describes the inner workings of QuickTest; it is intended to help people understand how things work but may change in future versions and shouldn’t be depended on.

 

QuickTest Professional’s bread and butter is identifying controls in the application being tested and it faces a tough decision since there are two directions in which one can optimize.

  • Optimize for speed
  • Optimize for robustness

Unfortunately one usually comes at the price of the other. To alleviate this problem, QuickTest has two concepts called description and runtime ID which are used together to achieve both speed and robustness:

 

Description

You should be familiar with the method QuickTest uses to identify Test Objects. This is a set of property/value pairs which (given the Test Object’s parent) describe an object uniquely.

 

 321i463B4AFBB3BD1291

Figure 1: Object Identification Dialog

 

This description can be used to describe a control robustly so that it will still match the correct control even when run in a different environment or in different builds of the application. However, finding the object that matches this description may be slow.

 

Runtime ID

A runtime ID is a way to quickly identify a control in the application being tested; the actual implementation changes according to the technology in question. But first, a bit of background…

 

In Microsoft Windows, each control has a Window which is identified by a handle known as HWND for “Handle to WiNDow”. All of the Windows APIs use HWNDs to access controls. This method is very fast; however, the HWND is like a “black box”. You can’t assume anything about its value since Windows assigns each control an HWND from an internal pool and the value will change every time the application is run. This makes an HWND the perfect match to be the runtime ID of Win32 controls. For example, a WinButton Test Object’s runtime ID may be its HWND.

 

Combining the Two

Here is a summary of the characteristics of runtime IDs and descriptions:

 

322i995357BAAD55177C

Figure 2: Runtime ID vs. Description

 

Every Test Object may contain a runtime ID and/or a description. If both are missing, there is no way to identify the control in the application being tested and the Test Object is useless (with a few exceptions).

 

When a Test Object is created from the application being tested, it contains a runtime ID. If the Test Object is to be stored in the Object Repository (during learn or record) a description is created for this Test Object.

 

When running a test, the Test Object has its description filled in (either from the Object Repository or from Programmatic Description) and then its runtime ID is found. Since finding the runtime ID is potentially an expensive operation, the value of the runtime ID is cached to avoid fetching it multiple times. However since the runtime ID may change during the test run, QuickTest is careful to clear the stored value whenever a new step is run. This means that if you store the Test Object in a variable or use With the aforementioned runtime ID clearing will not take place and the runtime ID may be invalidated. If this happens you can call the RefreshObject method (available with QuickTest version 10 and later) which manually clears the runtime ID.

 

 323iBC39705A3934AD1A

Figure 3: Invalidating a Runtime ID

 

An unexpected pitfall came as a support call when a customer tried to call Exist on a Test Object returned from ChildObjects. Let’s follow the chain of events with our new knowledge of the inner workings of QuickTest.

1. ChildObjects creates Test Objects with their runtime IDs set. (The Test Objects are to be used immediately so there no point in creating their descriptions.)

2. Exist wants to check if the object still corresponds to a control in the application being tested. To do this it clears the runtime ID and tries to re-create it.

        a. The description is empty so Exist fails.

3. Further down the line the customer tries to use the Test Object again and the test fails since the Test Object doesn’t have a description or a runtime ID.

 

The problem is that QuickTest creates a layer of abstraction above the application being tested and like all sufficiently powerful abstractions, it’s leaky. We know what ChildObject does and we know what Exist does, but put them together and BOOM - the things you don’t know (or weren’t supposed to know, like runtime ID) come leaking through and punch you in the face.

 

Our solution was to have Exist always return true when run on a Test Object that has a runtime ID but no description (this is part of QuickTest 10 Release Update). We feel that this is correct behavior since you just got the object from the application using ChildObject; obviously it Exists otherwise it wouldn’t have been returned.

 

An alternative solution could have been to make the objects returned from ChildObject create their description, however that would slow down all tests that use ChildObject for the benefit of the vanishingly small number of tests that check for existence.

 

The best way to avoid the problem in the first place is to use objects created by ChildObject as soon as they are created and before anything changes in the application being tested.

Labels: QTP
Comments
Yugesh | ‎10-27-2010 02:28 PM

Interestingly, the release update kills the purpose of the Exist command. Assuming we get the childobjects and would want to use it later in the application, with the release update, it is going to always return true. 

 

Please correct me if my understanding is wrong. 

 

Cheers!

Motti | ‎10-28-2010 12:37 AM
Yugesh: Interestingly, the release update kills the purpose of the Exist command. Assuming we get the childobjects and would want to use it later in the application, with the release update, it is going to always return true.
I wouldn't say that, the release update didn't remove any functionality. It was never the case that you could call ChildObjects and then later on, after the application has changed, check if the object is still valid using Exist. Prior to the release update using Exist would invalidate the test object and Exist would return false, now the object is in the same state as it was before calling Exist. The confusion would have been avoided if we used a better more precise name for Exist such as ThereIsCurrentlyAnObjectInTheApplicationThatMatchesThisDescription but this would be rather verbose :smileyhappy:.
bbaassiri | ‎12-22-2010 06:49 AM

I was experiencing many many random fails i.e. general run time errors , unable to identify object errors and many objects identified errors and what I found usefull and I hope this helps someone out there was to introduce the closing and re-opening of the Browser (in my case a majority of my testing is web based)

 

Restarting the browser on each test case can and is expensive and causes QTP to find runtime id but having said that, I've sacrificed speed for stability.

 

To provide more context, I use descriptive programming developped in QTP 8.0 using alot of Exist  statements before acting on a object (i.e. click or set or childobjects,etc) and upgraded to QTP 10

Leave a Comment

We encourage you to share your comments on this post. Comments are moderated and will be reviewed
and posted as promptly as possible during regular business hours

To ensure your comment is published, be sure to follow the Community Guidelines.

Be sure to enter a unique name. You can't reuse a name that's already in use.
Be sure to enter a unique email address. You can't reuse an email address that's already in use.
Type the characters you see in the picture above.Type the words you hear.
Search
Showing results for 
Search instead for 
Do you mean 
About the Author


Follow Us
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation