Article revised on 04/04/2012
This article discusses an elegant way of cross-checking expected vs actual properties of objects. The two important components of this technique are:
- Modular Classes
- DoPropertiesConform Method
Modular Classes
The main concept behind this technique is the usage of a Dictionary object to hold property-value pairs. There are 2 types of Dictionary objects used in Modular Classes: a Base (Parent) Dictionary and one (or more) Child Dictionaries. All Child Dictionaries are stored in a single Base Dictionary and passed through the class method. In practice, if we’re checking properties for the LogIn page, the Login Class will contain a Base Dictionary and several Child Dictionaries. Example:
Class LoginModule Public Function Collection Dim BaseDictionary 'A Single Parent Dictionary Dim Search '1st Child Dictionary Dim SiteLogo '2nd Child Dictionary Set BaseDictionary = CreateObject("Scripting.Dictionary") Set Search = CreateObject("Scripting.Dictionary") Set SiteLogo = CreateObject("Scripting.Dictionary") End Function End Class
Above, we created 3 dictionaries: 1 Parent and 2 Child. Now, let’s add some properties to the Child Dictionaries:
Class LoginModule Public Function Collection Dim BaseDictionary 'A Single Parent Dictionary Dim Search '1st Child Dictionary Dim SiteLogo '2nd Child Dictionary Set BaseDictionary = CreateObject("Scripting.Dictionary") Set Search = CreateObject("Scripting.Dictionary") Set SiteLogo = CreateObject("Scripting.Dictionary") With Search .Add "Me", Browser("title:=Google").Page("micclass:=Page").WebEdit("name:=q") .Add "html tag", "INPUT" .Add "width", 100 End With With SiteLogo .Add "Me", Browser("title:=Google").Page("micclass:=Page").Image("file name:=logo.gif") .Add "html tag", "IMG" .Add "width", 50 End With End Function End Class
Above, we added properties to the 2 Child Dictionaries. Please note that, the very first item/key in the dictionary in the Child Dictionaries is the object itself. I have used “Me” denoting that it is the object itself; you can change “Me” to any other descriptive term. However, the first item in the Collection must always be the object. Finally, let’s pass the Child Dictionaries through the method with the help of the Parent Dictionary:
Class LoginModule Public Function Collection Dim BaseDictionary 'A Single Parent Dictionary Dim Search '1st Child Dictionary (Search WebEdit) Dim SiteLogo '2nd Child Dictionary (SiteLogo Image) Set BaseDictionary = CreateObject("Scripting.Dictionary") Set Search = CreateObject("Scripting.Dictionary") Set SiteLogo = CreateObject("Scripting.Dictionary") With Search .Add "Me", Browser("title:=Google").Page("micclass:=Page").WebEdit("name:=q") .Add "html tag", "INPUT" .Add "width", 100 End With With SiteLogo .Add "Me", Browser("title:=Google").Page("micclass:=Page").Image("file name:=logo.gif") .Add "html tag", "IMG" .Add "width", 50 End With With BaseDictionary .Add "Search", Search .Add "SiteLogo", SiteLogo End With Set Collection = BaseDictionary End Function End Class
Above, we passed the Parent (Base) Dictionary containing both child Dictionary objects through the method. One last thing here. We must dispose all objects when we’re done (we will have to declare the variables in the Class scope, instead of method scope):
Class LoginModule Private BaseDictionary 'Parent Dictionary (Class Scope) Private Search 'Child Dictionary 1 (Class Scope) Private SiteLogo 'Child Dictionary 2 (Class Scope) Public Function Collection Set BaseDictionary = CreateObject("Scripting.Dictionary") Set Search = CreateObject("Scripting.Dictionary") Set SiteLogo = CreateObject("Scripting.Dictionary") 'Child Dictionary #1 With Search .Add "Me", Browser("title:=Google").Page("micclass:=Page").WebEdit("name:=q") .Add "html tag", "INPUT" .Add "width", 100 End With 'Child Dictionary #2 With SiteLogo .Add "Me", Browser("title:=Google").Page("micclass:=Page").Image("file name:=logo.gif") .Add "html tag", "IMG" .Add "width", 50 End With 'Add the Child Dictionary objects to Base With BaseDictionary .Add "Search", Search .Add "SiteLogo", SiteLogo End With Set Collection = BaseDictionary End Function Public Sub Dispose BaseDictionary.RemoveAll : Set BaseDictionary = Nothing Search.RemoveAll : Set Search = Nothing SiteLogo.RemoveAll : Set SiteLogo = Nothing End Sub End Class
The Modular class is ready and holds a Base collection with several Child collections.
DoPropertiesConform
This is where all the magic happens (simply keep it in one of your Global libraries and you’re good to go). This method verifies all the properties stored in the BaseDictionary with the runtime object properties. The final results are reported through Reporter events as HTML tables. The input to this method is the parent dictionary.
'Arg: ' DictBase - Base Collection - this contains several child collections 'Returns: ' Boolean (True if all properties in the collection match) Public Function DoPropertiesConform(ByVal DictBase) Dim vKeys, intStatus, i, m_ContextTemp, bResult, keysTemp, oTemp, x, sStatus, css, StepInfo DoPropertiesConform = False vKeys = DictBase.Keys intStatus = micPass For i = 0 to DictBase.Count-1 ' The below will create temporary references to Collection ' In our test, the Collection contains two objects: "Logo" and "UserName" Set m_ContextTemp = DictBase.Item(vKeys(i)) bResult = bResult & "<table id='custom' border='1'><tr><th>" & _ "Status</th><th>Property</th><th>Expected</th><th>Actual</th></tr>" keysTemp = m_ContextTemp.Keys If m_ContextTemp.Item(keysTemp(0)).Exist(0) Then ' Create a temporary reference to the object in the base collection ' Key values for these objects must always start with "Me" Set oTemp = m_ContextTemp.Item(keysTemp(0)) For x = 1 to m_ContextTemp.Count - 1 sStatus = "<span style='color:green;'>Pass</span>" If Not CStr(oTemp.GetROProperty(keysTemp(x))) = CStr(m_ContextTemp.Item(keysTemp(x))) Then intStatus = micWarning sStatus = "<span style='color:orange;'>Warning</span>" End If bResult = bResult & "<tr><td>" & _ sStatus & "</td><td>" & _ KeysTemp(x)& "</td><td>" & _ m_ContextTemp.Item(keysTemp(x)) & "</td><td>" & _ oTemp.GetROProperty(keysTemp(x))& "</td></tr>" Next Set m_ContextTemp = Nothing bResult = bResult & "</table>" & vbLf End If Next css = "<style>#custom {font-family: Calibri, Arial;font-size: 12px;background: #fff;" & _ "margin: 10px;width: 480px;border-collapse: collapse;text-align: left;}" & _ "#custom th{font-size: 14px;font-weight: normal;color: #039;padding: 10px 8px;" & _ "border-bottom: 2px solid #6678b1;}#custom td{border-bottom: 1px solid #ccc;color:" & _ "#669;padding: 6px 8px;}#custom tbody tr:hover td{color: #009;}</style><body>" Set StepInfo = CreateObject("Scripting.Dictionary") StepInfo("ViewType") = "Sell.Explorer.2" StepInfo("DllIconIndex") = 206 StepInfo("DllIconSelIndex") = StepInfo("DllIconIndex") StepInfo("DllPAth") = Environment.Value("ProductDir") & "\bin\ContextManager.dll" StepInfo("Status") = intStatus StepInfo("NodeName") = "DoPropertiesConform" StepInfo("StepHtmlInfo") = "<html>" & css & bResult & "</body></html>" Reporter.LogEvent "User", StepInfo, Reporter.GetContext If intStatus = micPass Then DoPropertiesConform = True Set DictBase = Nothing Set m_ContextTemp = Nothing End Function
Once we have added all the relevant objects and their properties to the parent dictionary, it just takes the following line of code to run all the verifications:
Call DoPropertiesConform(ParentDictionary)Example
In the example below, we will verify expected and actual properties of the Site Logo and the UserName WebEdit for the Mercury/HP Demo Web Application. Below are the snapshots of the 2 objects verified in the examples:
Class HomePage Private m_ContextBase 'Parent Private m_ContextLogo 'Child 1 Private m_ContextUserName 'Child 2 Public Function Collection ' Parent Dictionary (Base) Set m_ContextBase = CreateObject("Scripting.Dictionary") ' Child Dictionary objects Set m_ContextLogo = CreateObject("Scripting.Dictionary") Set m_ContextUserName = CreateObject("Scripting.Dictionary") ' Properties of the Object: Site Logo Image With m_ContextLogo ' Actual Object is the first Item/Key .Add "Me", Browser( "title:=Welcome: Mercury Tours" ).Image( "file name:=logo.gif" ) .Add "alt", "Mercury Tours" .Add "file name", "logo.gif" .Add "height", "110" .Add "name", "Image" .Add "width", "100" End With ' Properties of the Object: UserName WebEdit With m_ContextUserName ' The first Item/Key must always contain the object .Add "Me", Browser( "title:=Welcome: Mercury Tours" ).WebEdit( "name:=userName" ) .Add "disabled", "0" .Add "height", "22" .Add "kind", "singleline" .Add "name", "userName" .Add "readonly", "0" .Add "rows", "0" .Add "type", "text" .Add "width", "86" End With ' The Parent Dictionary stores both Child Dictionaries With m_ContextBase .Add "Logo", m_ContextLogo .Add "UserName", m_ContextUserName End With Set Collection = m_ContextBase End Function Public Sub Dispose Set m_ContextBase = Nothing Set m_ContextLogo = Nothing Set m_ContextUserName = Nothing End Sub End Class
' Usage: Dim NewHomePage Set NewHomePage = New HomePage DoPropertiesConform NewHomePage.Collection NewHomePage.Dispose
Result:
I hope you guys find this article useful :)

{ 28 comments… read them below or add one }
hi Anshoo,
I need to say that ‘It is a great article.’ I have a question for you.
Why do you pass the value If intStatus micPass Then DoPropertiesConform = False
you are not using it anywhere?
Thanks,
-Deepak
At the end of the function:
This just means that, if the status of all the checks is not “Passed” then, the result of the Function is going to be “False”. At the beginning of the code, the method starts with:
This means, if there is any descrepency during the checks, the method will return false. I create this to help users even use it in a conditional block:
If DoPropertiesConform(Class.Collection) Then 'Do Something Else 'Do Something Else End IfHi Anshoo,
If i wrote a multiple classes for each action and calling the same function “DoPropertiesFunction” so it show me result for 1st action and from second action it shows only Passed even i changed some actual properties value. Can you please help me out, or let me explain how would i able to do it for multiple action. hoping for cooperation.
Thanks
Mahesh
Mahesh, are you keeping the classes in Actions, or in function libraries?
Also, can I see the code that you have there in a .txt file? You can e-mail me the code and I will respond over e-mail or over here, whichever you prefer..
Hi Anshoo,
I am using the same code that you provide, just change the title and some properties, i dont have code now but i will show you tommarow, but anyhow if you understand th eproblem so please give me solution.
Thanks
Mahesh
Hi Mahesh,
I think the only reason why you will not be able to enter that loop is when the object (“Me”) does not exist. If you are executing the same code as I am, please make sure there is only
1browser open, and that browser is the target browser: http://newtours.demoaut.comIt should work.. I just tested this code on both versions 9.2 and 9.5..
Hi Anshoo,
i take a value of
MsgBox(m_htContextBase.Count-1) it shows = 1
but when i tried to take a value of
it shows type mismatch so can you please help me out i need to complete it today. hoping for cooperation.
Thanks
Mahesh
It shows “Type Mismatch” because its a collection, and Msgbox “Collection” will not give you a correct result. You will have to loop through the elements in the collection and output each element to know what the collection contains.
For Each oKey in m_htContextBase.Keys Print oKey " ---- > " & m_htContextBase.Item(oKey) NextHi Anshoo,
I debug my code i am unable to come into this loop
If m_ContextTemp.Item(keysTemp(0)).Exist(0) Then ....................... End IFPlease let me know what process i did wrong
Thanks
Mahesh
Not sure entirely.. You may be creating your dictionary object incorrectly – which is my only guess without looking at the code.
Hi Anshoo,
If i had given 8 child objects for a class then it wont show me the result even it wont show me result if i have 1 child object also, please help me out what is the cause.
Thanks
Mahesh
Hi Mahesh,
Can you please post your code? I am not able to reproduce this issue..
Hi,
As per my knowledge wecan get properties of any object with the help of “SPY ONLY” (in QTP), But what is an 3 rd party tools ? & what is the use of these 3 rd party tools, Is an alternate for OBJECT SPY? ,I saw this information on below conversation
Hi Vidyanand,
The few 3rd party tools other than QTP that I have described in my post offer much more than what Object Spy does. However, having a good understanding of HTML and CSS helps to use these tools better. Object Spy is a good tool, and I don’t think unless there is a need to understand the page structure without reading the code that you would need to use any of these tools.
I know some advanced users who use DebugBar for finding web anchors in their automation. You can read about identifying those anchors and finding their relationships in this article by Yaron: http://www.advancedqtp.com/knowledge-base/articles/environment-techniques-id15/web-id34/using-web-anchors-to-automate-non-unique-controls/
:)
Hi Anshoo,
Can u please explain about the SetCellData method ?In the below code , can we iterate the Group Name with the different datatable values?
JavaWindow(“SPEED”)JavaTable(“Contract Term”).SetCellData “#0″,”Group Name”,”G1″
eg: I have to set the row 1 with the values as G1 and row 2 as G2 and so on … how should i do it ?
Ranjini,
Unfortunately, I have not worked with Java Applications to give you an accurate answer. You can refer your query to AdvancedQTP’s Java Forum where I’m sure you will find an answer quickly. Also, if I am not wrong, you may just need to run a simple For..Next loop for the number of rows present in the table and use the SetCellData method. The syntax is:
JavaWindow("SPEED").JavaTable("Contract Term").SetCellData RowNumber, ColumnNumber, DataSo, I think you might need to replace #0 with the row number, “Group Name” with the column number.
HI Anshoo Arora,
Iam searching for a tool which can identify the object property and property values of a pirticular webpage.
Can u please let me know if there any such kind of tool to captuure properties according to the QTP properties.
Waiting for your valuable reply
Thanks
Tester
Sure. There are quite a few actually:
DebugBar
IE Developer’s Toolbar
FireBug
I mostly use DebugBar, but they’re all equally good. You can try them all and see which one you like the most.
Thanks- Anshoo
Thanks :)
Thankyou verymuch
You’re right, we cannot directly call Classes directly. Instead, we call Class members and this is made possible by initializing the class object using the ‘New’ keyword. Example:
Set oNew = New clsMyClass
Set oOld = New clsMyClass
You can use ‘oNew’ and ‘oOld’ above differently, according to your needs, and each instance will behave differently. However, what’s even more important than this concept is the way we can encapsulate a lot of the functionality into a single class, and we reveal only what we want to, through Public Properties, Variables and Methods. Rest, we hide through the use of Private Properties, Variables and Methods. This is a very deep topic, and I would really like to suggest you to find resources on Google and read further, especially about Encapsulation, Polymorphism and Inheritance. However, one must note that VBScript only supports Encapsulation, but understanding the principles of Classes is quite important.
If you look at the classes I have created, I have mentioned that these are modular classes. Thus, if I were to create a separate module for the Login page, everything can be encapsulated into a single working class that checks all the items, logs in the user and verifies if the login was successful.
Using the same example, we can verify the object properties using the methods outlined in this article, verify if all the objects exist, enter username and password, hit submit, wait for the resulting page to appear and report if the Login action was successful or unsuccessful. This entire process can be covered into a single class and it helps binding all of the module methods together.
I hope this helps answer your question. If you’re unclear about any concepts mentioned in this blog, please do let me know.
Thanks – Anshoo
Hi Anshoo
I read the article more than once, understood this and now am trying to create some classes which I can use in my code.
I have a confusion that why we create classes and not just use functions, as later we are calling the functions as methods from a class to serve the purpose.
I might sound novice and my concepts are not clear but if you can help then it will be great.. Do class take more memory then function or like the same question somebody asks “What is advantage of creating a class and not just using functions” then what to do… am searching this on google as well… if you can comment and suggest something then it will be great help.
Thanks! :)
Hai Anshoo,
This is an excellent article.
regards,
testking123
Hey what is this debug bar?? As per your articles, I learned to use object spy to gather the object properties so why this DebugBar?
Hi Pragya,
I hope you’ve been well.
To answer your question.. all 3 tools that I mentioned in my above post are 3rd party tools. In other words, you can use these even on PCs which do not have QTP installed. Object Spy is dependant on QTP and its not available on PCs where QTP is not installed.
I generally use these tools to better understand the page HTML (without reading the source code) and to find anchors to my target controls.
Hi Anshoo,
Thanks for your help. I have referred the Java forum which helped me in resolving my issue. i was able to identify my mistakes when i went to some of the Q&A posted in it .
Ranjini, I’m glad you have a working solution now :)
{ 3 trackbacks }