Relevant Codes

A Test Development Resource for HP QuickTest Professional.

QTP: Understanding the Description Object (Description.Create)

September 6, 2009 · 30 comments

Learning Zone
Creative Commons License photo credit: SideLong

Introduction
In this article, we will cover the basics of Description Object and the ChildObjects method. This is a very powerful approach to creating robust automation test suites. It is also a very important principle of Descriptive Programming in QTP.

We will see how we can create an object description with a single property, with multiple properties, by using regular expressions and finally putting all these concepts into their application with the ChildObjects method.

Before we see how it is done, we must first understand the following statement:

Set oDesc = Description.Create

Above, we are using the variable oDesc to create a description of something. Since, oDesc is preceeded by a Set statement, it must be an object reference. Therefore, when the above statement executes, oDesc will become an object reference to a description object. We will use the description object with the ChildObjects method to retrieve object collections. These object collections are nothing but arrays of objects with the exact properties of the description object.

If you are starting with DP, please read the article on Descriptive Programming Concepts on Relevant Codes for a quick walk-through on Descriptive Programming before continuing with this article.

I. Creating a Description Object for a Parent (Browser/Window)
To create an object description for a parent, we will simply use the “Class” of the parent object and add the property-value combination:

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
'Remember to always use 'micclass' and not 'class name'
oDesc( "micclass" ).value = "Browser"
 
'We used Desktop as the parent here because, the Desktop Object holds all the Windows
Set colObject = Desktop.ChildObjects( oDesc )

When the above snippet execute, colObject will contain a collection of all browsers visible on the desktop.

But, since we have done this, how will we know how many browser objects exist on the desktop through code? Also, how will we retrieve their information? The answer is quite simple: colObject contains the necessary information and methods we can use to perform events on our target objects.

'Retrieve # of open browsers
MsgBox colObject.Count
 
'Retrieve Titles of all open browsers
For x = 0 to colObject.Count - 1
	MsgBox colObject(x).GetROProperty("title")
Next

As I mentioned above, colObject is nothing but an array of all objects having the exact same properties as the description object. Therefore, colObject(0) points to the first object in the collection, colObject(1) points to the second object in the collection, and so on. This is demonstrated in the For..Next loop in the snippet above.

II. Creating a Description Object for an Object contained in a Browser/Window
Using the same approach above, we will retrieve collection of all Link objects on a page. Notice here that instead of Desktop, we have used the entire Browser-Page hierarchy. This is because, a link object is present somewhere inside the Page, instead of the desktop :).

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
 
'Using the entire Browser-Page hierarchy
Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )

By executing the snippet above, we will use colObject to perform some events on these objects. Let’s retrieve the number of link objects present in our browser:

'Returns 30
MsgBox colObject.Count

The above example is created for the Google page, and if you want to test it for some other browser, do not forget to change the Browser and Page titles to the correct values.

III. Creating a Description Object for an Object contained in a Browser/Window Using Multiple Properties
If you saw the above example, we created a description object using only the class of the Link object. Now, we will retrieve a more specific object collection. We are going to specify an additional property and narrow down the search results- this is because, even though there can be multiple Link objects on a page, its not necessary that there would be the same number of objects with the text “Hello, I am a Link!”.

This approach helps us retrieve only the objects that we really want for our automation, since having a collection of all objects can be quite cumbersome to work with. Also, if we provide relevant information to our Description Object, QTP will return a narrowed-down collection, which is the easiest to work with. This is similar to how you search Google. If you specify “QTP” in Google Search, you will have a huge array of search results. You can narrow down the search results (and find information faster) if you add “QTP + Browser + DP” instead.

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
'Additional property- for more focused and controlled collection
oDesc( "text" ).value = "Images"
 
Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )
 
Msgbox colObject.Count    'Returns 1

Now, colObject will only contain the Link objects that have the text: Images. Also, if you notice Google page, there is only one link with the Images text. This is a good example of finding the target object dynamically. Suppose, if there were 2 links on the page instead, we would have both of them in our collection colObject. Let’s highlight our found object:

colObject(0).Highlight

Executing the statement above, we will highlight the first object in the collection. I know there is only one object in the collection, but we can make sure by doing this:

For x = 0 to colObject.Count - 1
	colObject(x).Highlight
Next

IV. Creating a Description Object using WildCards
If we have dynamic objects in our application, then we may not always have the luxury to feed their properties as we have done in the example above. Sometimes, we would need to create dynamic descriptions and retrieve our target objects from resulting (dynamic) collections. I say dynamic collections because at one time, your collection may hold 9 objects, whereas during the next session, it may hold 10.

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
oDesc( "text" ).value = "I.*age.*"  'Images
'.regularExpression is 'True' by default
oDesc( "text" ).regularExpression = True
 
Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )

You may want to read the article on Regular Expressions to better understand how these work in Descriptive Programming.

After executing the snippet above, we will have a collection object with all object that match the regular expression. Let’s see the count of the objects:

'Returns 1 because our supplied pattern only matches with the word: Images
MsgBox colObject.Count

Let’s replace the “text” with “ma” instead and see if we still retrieve a collection with a single object:

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
oDesc( "text" ).value = ".*ma.*"  'Images
'.regularExpression is 'True' by default
oDesc( "text" ).regularExpression = True
 
Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )

To see what has changed, let’s execute the following:

'Will return 4
MsgBox colObject.Count

If you do execute the snippet above, the count would be 4. Why is that? To see the new objects in our collection, let’s do this:

For x = 0 to colObject.Count - 1
	MsgBox "x:" & x & " || " & colObject(x).GetROProperty("innertext")
Next

Below are our outputs:

Interesting, isn’t it? Our description for the text property matched all links that had the letters ma in them.

V. Negating WildCards
Sometimes we have an object description with wildcards in it. Here, we want to turn off the Description Object’s ability to register the description as a regular expression. This is quite simple, and we do it by turning regular expression as False:

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
oDesc( "text" ).value = ".*ma.*"  'Images
oDesc( "text" ).regularExpression = False
 
Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )
 
MsgBox colObject.Count    'Returns 0

Now, the above snippet will not identify Images or Maps. Instead, it will only identify objects that have the exact text .*ma.* which really doesn’t exist anywhere on the Google homepage.

VI. Creating a Description Object for Integer-Types
So far, we have only learned various ways to work with description objects using Strings. Here, we will see how they transform into integer-types. Let’s bring up the properties of the Images link again using the Object spy and feed its “x” coordinate to see whether we can find the link:

Object Spy Snapshot: Images Link (Google)

Object Spy Snapshot: Images Link (Google)

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
oDesc( "x" ).value = 51             'It should always be 51, not "51".

Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )
 
'Will return 1
MsgBox colObject.Count
 
'Will return Images
For x = 0 to colObject.Count - 1
	MsgBox colObject(x).GetROProperty("innertext")
Next

Notice that 51 above is not within quotation marks. This should always be the case. Notice when we replace it with a string-type below:

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
oDesc( "x" ).value = "51"
 
Set colObject = Browser( "title:=Google").Page("title:=Google").ChildObjects( oDesc )
 
MsgBox colObject.Count
 
For x = 0 to colObject.Count - 1
	MsgBox colObject(x).GetROProperty("innertext")
Next

The collection is an empty one:

(Mis)Using Integers as Strings

(Mis)Using Integers as Strings

So, always remember to treat integers as they are. This always holds true for x, y, abs_x, abs_y.

VII. Building Object hierarchy with ChildObjects
We will use the Browser Object Collection to set a value in a text box to demonstrate this:

Dim oDesc        'Description Object
Dim colObject    'Object Collection

Set oDesc = Description.Create
oDesc( "micclass" ).value = "Browser"
oDesc( "title" ).value = "Google"
 
'Notice we used the Desktop Object again for retrieving Window collection
Set colObject = Desktop.ChildObjects( oDesc )
 
'Retrieve the count
iCount = colObject.Count
 
'Set value in the WebEdit of the last Window object in the collection
For x = 0 to iCount - 1
   'Verify if the Browser title equals "Google"
   If Browser("creationtime:=" & x).GetROProperty("title") = "Google" Then
      'Set Description.Create in the search TextBox
      Browser("creationtime:="&x).Page("micclass:=Page").WebEdit("name:=q").Set "Description.Create"
   End If
Next

When the above snippet executes, we will have the following value set in the Search TextBox in Google HomePage:

Using Description.Create to Set Value

Using Description.Create to Set Value

I hope this article will help you guys understand the concepts of one of the most important concepts in Descriptive Programming: the Description Object. Thanks for visiting Relevant Codes :)

If you have any questions, please ask them in the comments section. If your information is to be treated as confidential, please use the Contact Form to send me an e-mail instead.

{ 1 trackback }

baby crib safety
October 5, 2009 at 12:09 am

{ 29 comments… read them below or add one }

1 sunitha September 16, 2009 at 3:53 am

Hi Anshoo,

The Description object article is very clear with examples.keep up the good work

Regards
Suni

Reply

2 Anshoo Arora September 16, 2009 at 5:46 pm

Thanks! :)

Reply

3 Sangeetha September 17, 2009 at 11:54 am

Hello Anshoo,

Can you please tell me the difference between vbcr and vbcrlf vbscript constants? In the help file, its mentioned that vbcr gives a carriage return which according to me is Enter key in our keyword and vbcrlf does the same plus it adds linefeed. now what is this linefeed? I have already got the enter command through vbcr so why vbcrlf? Also vbNewline is there?

Regards,
Sangeetha

Reply

4 Anshoo Arora September 17, 2009 at 7:07 pm

Hi Sangeetha,

Great question, and to be honest with you, I never use vbCr. However, you raise a good question and to answer it, I am going to recommend you to read the following article: NewLine. It will explain what each means and how they came about.

what is this linefeed?

A linefeed is quite an interesting concept, but before I explain that, I must explain what a carriage does. A carriage just moves one line down from the point where the method is executed. A linefeed enables the cursor to move to the far-left, where you would want it to be, and that’s ideal/common.

vbCrLf resembles that and its easier for beginners to understand what it does. So, even though it does the same thing, its quite easy to comprehend what it would do without much thought.

vbNewLine on the other hand, and I am not too sure here, but I think its platform dependent and it may signify different things in different environments. This is all MSDN says about it: vbNewLine.

Reply

5 Pragya September 25, 2009 at 2:09 pm

Hello Anshoo,

Can you please tell me that in the case of array, which approach is better to loop thru the items: For Each loop or a normal for loop? or either can be used?

Also why do LBound and UBound function works fine with the arrays created using Array keyword and not with the arrays declared like Dim A(3). I see that UBound(arr) gives a different answer in these cases.. Can you please explain me why?

Reply

6 Anshoo Arora September 26, 2009 at 6:11 pm

Hi Pragya,

I rarely use For..Each Loops. I find it easier and more efficient working with the normal For..Next Loop (you can directly access the element number without using an explicit counter which you would in For..Each). I have also noticed on several occassions that there is a slight performance drop when using For..Each loops. To illustrate, let’s see the example below:

Dim arrArray: ReDim arrArray(9)
Dim tStart, x, Element

arrArray = Array("a", "b", "c", "d", "e", "f", _
		"g", "h", "i", "j")

tStart = Timer
For Each Element in arrArray
	Print Element
Next
Print "For Each: " & Timer - tStart

'I can directly use "x" here
'With For..Each, I would have to use an increment to know which element I am working with
tStart = Timer
For x = LBound(arrArray) to UBound(arrArray)
	Print arrArray(x)
Next
Print "For Next: " & Timer - tStart

Which one gives a better time?

I see that UBound(arr) gives a different answer in these cases.. Can you please explain me why?

Using the same array above, when I execute the following line, I get 9:

'Returns 9
MsgBox UBound(arrArray)

In your case, when you do UBound(A), you should get 3. It should return 3.. Can you please share with me your result as well?

Reply

7 alkaa October 1, 2009 at 4:05 am

Hi,

Can you explain with the example that what are child object, How should we get this from parent object and where
should we use this?

Thanks,

Reply

8 Anshoo Arora October 1, 2009 at 6:39 pm

Alkaa,

Your question can emcompass an entire topic – its that vast. However, to give you a quick idea of how and where we use ChildObjects, let me walk you through a simple scenario:

Suppose you have n number of CheckBoxes on a page, and this number changes depending on your inputs on previous screens. The requirement is to enable them all regardless of the number of CheckBoxes. So, let’s say for Process 1, there are 20 Checkboxes on the page, but for Process 2, this number increases to 40.

This is where ChildObjects can be used, and makes work extremely easy. Since ChildObjects retrieves object collections, we can use it to enable all the CheckBoxes easily. In your library, this is all the code you would have to keep to enable them all:

'Creating a description object for a WebCheckBox
Set oCheckBox = Description.Create
oCheckBox("micclass").value = "WebCheckBox"

'Object Collection
Set colObject = Browser("").Page("").ChildObjects(oCheckBox)

'Looping through the collection and enabling all CheckBoxes
For x = 0 to colObject.Count - 1
 colObject(x).Set "ON"
Next

I hope this helps.. If you’re still unclear, we can create a working example too.

Reply

9 alkaa October 3, 2009 at 5:01 am

Anshoo,

You gave me a good initiative idea about child object. I am understanding from different angles. Kindly clarify my one more issue that….can we use micClass universally in descriptive programing everywhere like with browser, page, text and combo or it is specified only for Browsers? I explored alot but could not get any satisfactory answer. I have big tumor of confusion and questions from long time. Therefore kindly reply.

thanks in advance..

Reply

10 Anshoo Arora October 3, 2009 at 11:24 am

can we use micClass universally in descriptive programing everywhere like with browser, page, text and combo

Yes, the micclass identifier can be used with any object, regardless of the application and technology. micclass equals Class Name in Object Spy. Each Object, regardless of the properties it has, also has a class-type identifier, which is defined by micclass.

However, even though each object can be identified using its micclass identifier, you must note that it may not be sufficient to uniquely identify an object. For example, open 2 browsers and execute the following code:

Browser("micclass:=Browser").Highlight

It will result in an error. That is because even though the Class Name was used, it is not enough to identify the correct browser between the 2 open browsers. Thus, you will have to add other properties to make the distinction between the two. Obviously, this would result in the same behavior if there were multiple objects of any class. We would need to use additional properties to identify them uniquely, and using micclass alone will not help.

Reply

11 Suraj November 20, 2009 at 5:35 am

Good Explaination with examples ,thank you

Reply

12 Anshoo Arora November 20, 2009 at 11:58 am

Glad it helped! :)

Reply

13 Jason January 6, 2010 at 12:02 pm

Hey there,

I believe my question is related as it deals with child objects. Anyhow here’s my problem.

I’m having a bit of trouble identifying WebEdit objects on a web app I’m testing. The problem is the input box themselves don’t have id’s and the class associated with each is not unique. Also the ordering of them may be different depending on other variables so I cannot use their indexes. However, each input box is a child of a div that does have a unique id. I can’t figure out how to set the value in the input box.

The HTML structure is as follows:

and the following qtp snippet spits out the innerhtml of the first input box:

Browser("").Page("").Frame("").WebElement("html tag:=DIV", "html id:=unique_id_1").GetROProperty("innerhtml")

Is there anyway to take that output and cast it to a WebEdit object?

Thanks for any help,
Jason

Reply

14 Anshoo Arora January 7, 2010 at 5:36 am

Jason,

You can wrap your code around:

p r e
/ p r e

(without spaces)

Reply

15 Jason January 6, 2010 at 12:06 pm

Sorry, I thought the ‘code’ tags would display the HTML structure.. guess not. Let’s try with ‘pre’ tags:

and if that didn’t work:

div id="unique_id_1"
   input type="text" class="non_unique_class"
/div

div id="unique_id_2"
   input type="text" class="non_unique_class"
/div

Reply

16 Anshoo Arora January 7, 2010 at 5:27 am

Hi Jason,

You can try the following:

With Browser("Browser").Page("micclass:=Page")
    .WebElement("html id:=unique_id_1").WebEdit("class:=non_unique_class").Set "1"
    .WebElement("html id:=unique_id_2").WebEdit("class:=non_unique_class").Set "2"
End With

or:

With Browser("Browser").Page("micclass:=Page")
    .WebElement("html tag:=DIV", "html id:=unique_id_1").WebEdit("index:=").Set "1"
    .WebElement("html tag:=DIV", "html id:=unique_id_2").WebEdit("index:=").Set "2"
End With

Reply

17 sam January 26, 2010 at 1:09 am

excellent info, If you have more things to I would very much aprreciate it.

Reply

18 Anshoo Arora January 26, 2010 at 11:06 am

Thanks, Sam. I will try to post a few more such articles in the coming weeks!

Reply

19 Babu February 6, 2010 at 5:03 am

Hi,

I have one problem in passing a value to a link object.

I have set of links in a folder frame .. for ex: Test1,Test2,Test3,Test4 .. etc.
While recording, i had selected Test1 link in the folder frame. Test1 has been added to the object repository as a test object.
Test1,Test2,Test3,Test4 are the objects of the class Link.
Now if i want to select Test2 by running the same script .. how?
For that i used msgbox function to allow the user to enter the value of the link.

I got the list of link objects in the folderframe object and i created a loop to check whether the value entered by the user is equal to the value of the link (got it by using child objects method).
Whenever the value entered by the user and the link got it from the application are same, i am trying to pass that value to the link method as mentione below:

Browser(“Login”).Page(“Application”).Frame(“folderFrame”).Link(“Classification”).Click
Classification is the value which is entered by the user.
Let us say user wants to select Link Test2 where as Link Test1 has been selected while recording.

When i execute the above mentioned statement, instead of selecting link Test2, it is selecting Test1(which was selected while recording).

Pls help me in this .. if you are not able to understand, feel free to mail me @ nbabu11@gmail.com

Reply

20 Anshoo Arora February 10, 2010 at 2:13 pm

Hi Babu,

If you’re using DP:

For ix = 1 to 4
    Browser("Login").Page("Application").Frame("folderFrame").Link("innertext:=Link" & ix).Click
Next

If you’re using OR:

For ix = 1 to 4
    Browser("Login").Page("Application").Frame("folderFrame").Link("Link" & ix).Click
Next

Reply

21 Steve Langille February 18, 2010 at 12:40 pm

How would you go about only grabbing children that ONLY have numbers in their “innertext”?

Here is what I have so far:

———————————————————————————————————————————————————————

Dim oDesc ‘Description Object
Dim colObject ‘Object Collection

‘Filter web child objects to get only the child under “Account Number”
Set oDesc = Description.Create
oDesc(“micclass”).Value = “Link”
oDesc(“html tag”).Value = “A”
oDesc(“height”).Value = 13

Set colObject = Browser(“micClass:=Browser”).Page(“micClass:=Page”).ChildObjects( oDesc )

‘Retrieve the count
iCount = colObject.Count

————————————————————————————————————————————–

It is returning back 8 children. But I only want to retrieve one child. The other seven children have letters in their “innertext” and teh one child I want only has numbers.

Thanks,
Steve

Reply

22 Anshoo Arora February 19, 2010 at 1:42 am

Hi Steve,

For a description object to incorporate only numeric values, the following ReGex would be applicable to the object’s innertext:

Set oDesc = Description.Create
oDesc("micclass").Value = "Link"
oDesc("innertext").Value = "\d+"

Reply

23 Steve Langille February 19, 2010 at 9:15 am

Thanks much Anshoo!

Steve

Reply

24 Anshoo Arora February 19, 2010 at 9:35 am

:)

Reply

25 Israel February 24, 2010 at 8:27 pm

Your examples are truly useful but I got one question:

If I wanted to use a Description Object to identify certain type of objects on my app screen, but I want to exclude objects, say for example, that have a property with a specific value.

How could I handle this?

Something like:

Set oDesc = Description.Create
oDesc(“micclass”).Value = “Link”
oDesc(“html tag”).Value = “A”
oDesc(“height”).Value 13

That would return Links with html tag = “A” but exclude those links with value = 13.

Thanks!

Reply

26 Anshoo Arora February 24, 2010 at 10:30 pm

Hi Israel,

I don’t think this is possible, and you can verify this through Object Repository as well. With constants in such situations, regular expressions are not allowed so I’m not sure how we can create such a description object. I think the only feasible way at present is by using (and negating) objects in the collection through a loop:

For ix = 0 to iCount - 1
    If colObject(ix).GetROProperty("height") = 13 Then SkipStep
Next

Reply

27 Israel February 24, 2010 at 11:01 pm

Hey!
Thanks for the quick response!

You are right, but I was thinking that maybe regular expressions could help (^) to retrieve objects with a property different than a specific value.

Regards,

Reply

28 Anshoo Arora February 28, 2010 at 5:41 pm

ReGex is possible, but only for some properties. This is a limitation that has become more prominent as people have sought advanced use of the description object. I hope HP will someday address this..

Reply

29 shivani March 8, 2010 at 2:25 am

thanks

Reply

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Previous post:

Next post: