Relevant Codes

A Test Development Resource for HP QuickTest Professional.

QTP: Working with Multiple Browser Applications – A Concept

by Anshoo Arora on August 24, 2009

Introduction
Web applications due to their dynamic nature, make script development quite challenging. I am writing this article in an attempt to simplify one of its aspects that automation developers face while working with Web applications. We will see how it can be made extremely easy to work with multiple browsers with the use of a Dictionary object, to which we can add Browsers, remove them, change their description etc. You will notice in the example at the end of this article that, regardless of how many pages we navigate, we would never have to keep a track of changing titles (unless we need to).

Let’s begin by creating a global variable, that will hold the Browser Collection to be accessed by our class:

'Public Variable: Browser Collection
Public colBrowser

Another reason to create a global variable is that as long as it is an object, it can be used as a reference by (local) class variables, thus being over-written as many number of times as we want. Next, we will create a Browser class, that will make use of the global variable (as a reference) we declared above:

Class clsBrowser
 
End Class

To ensure that we are not creating a new object each time our class initiates, we must create a Singleton, which will be stored in the initialization procedure of our class. It will also assure us that our code is highly efficient and our global variable is created only once, and not destroyed unless required.

' Purpose: Initializes the Scripting.Dictionary Singleton
Private Sub Class_Initialize
	Dim bInit: bInit = False		
 
	' If colBrowser has already been instantiated, then Init = True
	If IsObject(colBrowser) Then
		If Not colBrowser Is Nothing Then
			bInit = True
		End If
	End If
 
	' If colBrowser was destroyed or has not yet instantiated, then create it
	If bInit = False Then Set colBrowser = CreateObject("Scripting.Dictionary")
 
	' colObject (local) acts as a reference to colBrowser
	colObject = colBrowser
End Sub

Above, colObject is a reference to our Global Collection object colBrowser. To ensure that the reference isn’t lost while being accessed by Class members, let’s make it a read/write property:

Private m_hashTable
 
' Purpose: Stores the colObject Object to be accessed by Class members
Public Property Let colObject(ByRef Val)
	Set m_hashTable = Val
End Property
Public Property Get colObject()
	Set colObject = m_hashTable
End Property

Instead of creating a new object each time, we will reuse the same reference to add all the necessary Browsers. To add browsers to our collection, let’s create a simple method called “AddBrowser” and a public property “HWND”, that will store the Windows Handle of the Browser:

' Purpose: Adds Browsers and their HWNDs to a Collection
Sub AddBrowser(sName)
	' If the Name already exists in the collection, then remove it so it can be re-added
	If colObject.Exists(sName) Then
		colObject.Remove sName
		colObject.Remove sName & "-HWND"
	End If
 
	' Add the Browser with its corresponding handle
	' Store the Handle Property
	With colObject			
		.Add sName, Browser("hwnd:=" & Me.HWND)
		.Add sName & "-HWND", Me.HWND
	End With
End Sub
 
Private Handle
 
' Purpose: Stores the Browser Handle
Public Property Let HWND(ByVal Val)
	Handle = val   
End Property
Public Property Get HWND()
	HWND = Handle   
End Property

To provide ourselves with more options to add browsers, let’s create 3 more methods: AddUsingCreationTime, AddUsingTitle and AddLastOpen. As the name suggests, AddUsingCreationTime will enable us to add the browser in our collection object using its creationtime:

' Purpose: Uses the "AddBrowser" method to add browsers to the collection 
' using their CreationTime Property
Public Sub AddUsingCreationTime(sName, intVal)
	Dim oBrowser, oCol
 
	' Description object for Browser Class
	Set oBrowser = Description.Create
	oBrowser("micclass").Value = "Browser"		
 
	' ChildObjects of Browser Class Description
	Set oCol = Desktop.ChildObjects(oBrowser)
 
	' If the supplied CreationTime is greater than the total number of open browsers, 
	' then Report Err.
	If intVal > oCol.Count Then
		Reporter.ReportEvent micWarning, "Add Browser Using CreationTime",_
		"Browser with CreationTime " &intVal& " was not found."
		Exit Sub
	End If
 
	' Store the Browser Handle
	Me.HWND = Browser("creationtime:=" & intVal).GetROProperty("HWND")
 
	' Add the browser to the collection
	AddBrowser sName
End Sub

Similarly, AddUsingTitle will enable us to store a Browser if we prefer using Browser’s Title:

' Purpose: Uses the "AddBrowser" method to add browsers to the collection 
' using their Title Property
Public Sub AddUsingTitle(sName, sTitle)
	' Verify if the browser with the supplied title exists
	If Not Browser("title:=" & sTitle).Exist(1) Then
		Reporter.ReportEvent micWarning, "Add Browser Using Title", _
		"Browser with Title " &sTitle& " was not found."
		Exit Sub
	End If
 
	' Store the Browser Handle
	Me.HWND = Browser("creationtime:=" & intVal).GetROProperty("HWND")
 
	' Add the browser to the collection
	AddBrowser sName
End Sub

Lastly, for greater flexibility, we will create another method, AddLastOpen, which as the name suggests, will add only the most current browser to our collection:

' Purpose: Uses the "AddBrowser" method to add the last (most recent) open browser
'	Note: The last open browser always has the greatest CreationTime
Public Sub AddLastOpen(sName)
	Dim oBrowser, oCol
 
	' Description object for Browser Class
	Set oBrowser = Description.Create
	oBrowser("micclass").Value = "Browser"		
 
	' ChildObjects of Browser Class Description
	Set oCol = Desktop.ChildObjects(oBrowser)
 
	' Store the Browser Handle
	Me.HWND = Browser("creationtime:=" & oCol.Count - 1).GetROProperty("HWND")
 
	' Add the browser to the collection
	AddBrowser sName
End Sub

To simplify calling of objects, lets create a method named ‘Name’ which will work directly with our Dictionary using its methods:

Public Function Name(Key)
	Dim Keys
 
	Keys = colObject.Keys
 
	If IsNumeric(Key) Then
		Key = Keys(Key)
	End If
 
	If IsObject(colObject.Item(Key)) Then
		Set Name = colObject.Item(Key)
	Else
		Name = colObject.Item(Key)
	End If
End Function

Finally, we must create an instance of the object, that will enable us to call class methods:

' Create a new instance of Class clsBrowser
Set BrowserObject = New clsBrowser

We’re done! You can download the class here, or view the text version here

Demonstration
As a demonstration, you can associate (or ExecuteFile) the library and run the following lines of code:

' Launch 2 Browsers:
'	1. Google Home (HOME)
' 	2. Google Maps (MAPS)
With SystemUtil
	.Run "iexplore.exe", "www.google.com", "", "", 3 : Wait(2)
	.Run "iexplore.exe", "maps.google.com", "", "", 3 : Wait(2)
End With
 
' Add the 2 open browsers
'	1. Add Google Home using its creationTime
'	2. Add Google Maps using the .AddLastOpen Method (Since GoogleMaps is the last open
'		browser, it will have the highest CreationTime. In other words, its the most 
'		current open browser)
With BrowserObject
	.AddUsingCreationTime "HOME", 0
	.AddLastOpen "MAPS"
End With
 
With BrowserObject
	' Highlight and output the title of the "HOME" browser (it has a creationtime of 0)
	.Name("HOME").Highlight
 
	MsgBox "Title: " & .Name("HOME").GetROProperty("title")
 
	'Set search text
	.Name("HOME").WebEdit("name:=q").Set "Google Home"
	'Click Google Search
	.Name("HOME").WebButton("name:=Google Search").Click
	' You never have to worry about changing Titles/object properties
	.Name("HOME").Back
 
	' Highlight and output the title of the "MAPS" browser (it is the last open browser)
	.Name("MAPS").Highlight
 
	MsgBox "Title: " & .Name("MAPS").GetROProperty("title")
 
	' Close MAPS Browser
	.Name("MAPS").Close
End With
 
'Release Dictionary
BrowserObject.Destroy

Notice the demo above. We only have to use the custom name we gave to the browser to perform events on the objects that exist inside of it. Our custom names can be used throughout the automation cycle, but I would recommend you to look into the “ChangeName” method available in the class and included in the QTP test, that you can download. This would make object naming easier, and more descriptive, as the titles change the moment we navigate to another page.

Download the Class: clsBrowser

If you would like very high-level demo of this class, you can download the demo QTP test as well.

If you need more examples, or clarification on any of the concepts mentioned in this article, please let me know! Also, if you feel this class can be improved further by adding some interesting methods, then we’ll surely work together to incorporate them.

References

  1. An Improved Dictionary Object by Yaron Assa (AdvancedQTP, SolmarKN)
  2. Singleton Pattern by Yaron Assa (AdvancedQTP, SolmarKN)

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

Leave a Comment

Previous post:

Next post: