QTP Unplugged - Final Book PDF
QTP Unplugged - Final Book PDF
ISBN: 978-0-9836759-1-4
Printing History:
No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by
any means, electronic, mechanical, photocopying, recording, scanning or otherwise without either the prior
written permission of the Author, or authorization through payment of the appropriate percopy fee to the
Author. For permission please contact author at KnowledgeInbox.com/contact-us.
Source codes discussed in this book can be copied, modified or distributed without permission from author
or the publisher by including the below mentioned reference
This document also contains registered trademarks, trademarks and service marks that are owned by their
respective companies or organizations. The Publisher and the author disclaim any responsibility for
specifying which marks are owned by which companies or organizations.
Tarun Lalwani is a Test Automation & Solutions Architect and the author of the first ever book on QTP
named "QuickTest Professional Unplugged". He has worked on various automated testing projects utilising
technologies like VBScript, VB6, VB.Net, C#.NET, Excel and Outlook Macros. He founded
KnowledgeInbox.com — a blog targeted towards the QuickTest community. He uses the blog to share his
custom APIs, products, articles, tips and tricks with his readers pro bono. He is also a regular contributor at
AdvancedQTP and SQA forums. Tarun's work has been showcased on several websites such as:
RelevantCodes.com
AdvancedQTP.com
Tarun was awarded with the 'Best Feedback Award' by HP for QTP 11 Beta testing. His book "QuickTest
Professional Unplugged" was recognized as the Best Automation Book in the 2nd ATI Automation Honors
award. It is the industry's original set of awards dedicated to software test automation recognizing industry
leading tools, resources and practitioners. The ATI Automation Honors awards rely on industry practitioners
to identify which tools, resources and people are the best, which have the most significant upgrades and/or
which are setting the trends that will help to take software test automation to the next level.
KnowledgeInbox.com/contact-us
LinkedIn.com/in/tarunlalwani
Acknowledgements
The following individuals deserve a special mention for reviewing my work in progress, and providing me
with many useful comments and suggestions:
Terry has not only worked as a reviewer but also as a Technical Editor for this book. Terry has worked with
automated testing tools since the early 90's when he started designing solutions with Segue's QA Partner
1.0. He transitioned to Mercury Interactive tools in 1999 and has worked exclusively with QuickTest
Professional since 2005. He can be contacted on [email protected].
Siddharth has worked as an Editor for this book and has done a great job making sure that contents of this
book are lucid and unambiguous for the beginners. He is an Assistant Professor in the Department of English
at Hindu College, University of Delhi. He can be contacted on [email protected]
I would especially like to thank my family and friends who have always motivated me while I was working
on this book.
"Tarun Lalwani has single-handedly helped thousands of people to expand their knowledge of QuickTest
Professional. Here is a book the automated testing community has been crying out for. This book will help
QTP practitioners, from beginners to experts. I have used QTP from V6.0 and during the review I learnt
something from every chapter." – Mark
"After long brainstorming sessions with Tarun over almost each and every sentence, I realized that I am
truly in the presence of a genius. Tarun has with his dedication and perseverance made possible a book
which will go a long way in helping people understand the ins and outs of QTP." – Siddharth
How many times have you wished that there was somebody who could clear some niggling doubts about a
particular aspect of QTP? Or explain some difficult-to-grasp concepts and smart workarounds? Or show you
some of the lesser known features of QTP?
Written by the author of the best selling QTP book – "QuickTest Professional Unplugged", this book does just
that in a gripping story that will make you turn every page in anticipation. "And I Thought I knew QTP! –
QTP Concepts Unplugged" is 'different' in the way it seeks to explain the various concepts through an
interesting and innovative story-telling style (which is rarely used for technical books). Instead of following a
textbook format, this book is more like a technical novel.
Whether it is to brush up your QTP concepts or simply to satiate your curiosity about how a seasoned IT
veteran fared in a no-holds-barred 'intellectual duel' on QTP – whatever your reason to pick up this book, it
is sure to leave you astounded with its pace of narration, expertise, and breadth of topics covered.
ISBN: 978-0-9836759-0-7
I started with Web testing Automation in mid 2004 by creating a project in Visual Basic 6 using the Internet
explorer COM Automation. The project was a great success but with every change to the application the
Automation Code had to be updated and recompiled. While trying to find a solution to this maintenance
issue, I stumbled upon QuickTest Professional 8.0 (QTP).
QuickTest Professional is a Test Automation tool and uses VBScript as its scripting language. QTP is a record
and playback tool which can record events we perform on an application and replay them back. QTP is an
object based tool which recognizes each element of the application as an object and provides various
methods to work on them. All this makes QTP look like an easy-to-use test tool. The myth about Record &
Playback is that it makes people think that they do not need development skills for QTP, but to create
effective Automation Frameworks one needs to view QTP as a development tool and not as a testing tool.
This book presents QTP as a development tool rather than a mere test tool.
One of my problems while evaluating the tool led to me to join www.SQAForum.com, without knowing that I
will specialize in the use of this tool in future. After sometime I launched KnowledgeInbox.com for sharing
my articles on QTP with the larger group. Dealing with day-to-day automation problems faced by people on
the QTP forums, I tried solving those problems for them and learnt a few new things on my own. Observing
the patterns of queries being asked on the QTP forums, I thought what the QTP community was missing is a
book which can guide the amateur automation engineers in becoming a professional in the use of this tool. I
took up this responsibility and started writing this book in May 2005. I spent a year on the research of the
undocumented QTP features and solving the unsolved queries of QTP.
Being a first-time author, I had a very hard time getting this project completed. It was an additional
responsibility, over and above my office work, QTP forum support, writing articles on KnowledgeInbox,
creating tools for the community. It required a lot of motivation to keep myself focussed on the project. But
knowing what difference this book can make to the QTP community always kept me motivated.
I have organized the chapters in such a way that can make learning QTP an easier task. Each chapter is
based on a QTP feature. The book is divided into two sections, Basics and Advanced. Chapters 1 to 18 cover
features related to QTP while the chapters in the Advanced section cover integration/interaction of QTP with
various external tools like Outlook, Word, Excel and Quality Center. The book discusses a lot of issues that
are commonly faced while using various features of QTP and their resolution. This book discusses almost all
the topics of QTP which one would require to create complex frameworks.
facebook.com/pages/QuickTest-Professional-Unplugged/154615194628123
Test automation is the process of reducing, and when possible, removing human interactions from an
existing manual testing process.
Below is a list of parameters which makes a manual test a good candidate for automation:
Ad hoc testing where a subject matter expert randomly prowls through a variety of combinatorial
workflows.
One time testing or testing repeated only a few times.
Testing which requires covering multiple functional areas such that the test travels through a small
amount of virtually all of the product's functionality.
Testing where look and feel, color, table layout, etc. are validated.
Testing where pass/fail validation requires evaluating information from several different and
unrelated systems and/or applications.
It is important to understand the various phases involved in the automated testing process in order to
develop and effective framework and test cases:
Selecting the "best fit" Automation Tool: Before starting to automate testing in any application
it is important to pick the best fit tool for the majority of your applications. The choice should be
based on variety of factors such as cost, ease of use, application support capabilities and product
support.
Proof of Concept (POC): This activity involves creating a few sample scripts that validate a few
important business workflows in one or two of your most important applications. This helps identify
any major issues that might be encountered during future test case development. A proof of
concept should also be used to select the best automation test tool for your applications.
Requirements Analysis: This activity involves analyzing the requirements of an application,
studying the existing manual test cases and then defining the scope of the test automation project.
Project Estimates: Once the scope of automation is defined, estimates can then be formulated
based on various factors like the number of test cases to be automated, their level of complexity,
what re-usable components need to be developed, staffing requirements etc.
Framework Design: This activity involves creating shared object repository(s), any reusable
components, writing a best practice guideline document and completing any supplementary
activities to prepare a base of supporting components that will be utilized to develop automation
test scripts.
Test Script development: Test cases are created by calling the reusable components and adding
appropriate validations to each workflow specific script.
Debugging: Completed test cases are debugged to make sure they work as designed. Make sure
you force the code through all error handling paths during phase.
Execution: In this phase test cases are finally put to work through regression testing and validating
the application under test.
Result Analysis: Process followed by the results created by each executed test after execution.
Maintenance: This phase involves updating scripts to fix any code related to issues found during
execution. These issues may include UI or markup changes, changes in flow or functionality or any
other inevitable changes made to the application during new builds or releases. A well designed
framework and set of tests ensures that maintenance costs are kept to a minimum.
HP QTP is a Functional Test Automation tool. Out of the box, it supports a Record and Playback methodology
where automation Engineers can record and capture events with the application under test and then replay
those actions during the testing phase.
QTP has two modes in which it is possible to view and edit a test script:
Keyword View
Expert View
The Keyword View displays the script in the form of keywords (each object is an icon) arranged in a tree-like
format that is targeted at Subject Matter Experts (SMEs) with little or no programming background. A
snapshot of the Keyword View is shown below:
Figure 1-2: Keyword View
The Expert View exposes the underlying VBScript code shown as icons in the Keyword view and provides
access to substantial capabilities not available in the Keyword view:
This book is targeted at automation engineers who want to exploit the power that QTP offers when working
in the Expert View.
Note QTP uses VBScript as its programming language. Virtually all VBScript functionality is available in the
QTP Expert View. Conversely, any VBScript limitations are also present in QTP. It is important to learn
what are QTP VBScript related in a test's structure. This book also helps clarify those aspects.
To start with QTP, first we need to download the latest version of it from the HP website. Follow the below
steps to download the latest copy
Go to http://support.openview.hp.com/
Click on the Products link on the Left
Locate "HP Unified Functional Testing software" on the page and click on the link
Click on Trails and Demos and choose "HP FUNCTIONAL TESTING XX.00 EVALUATION"
Create a new HP passport in case you don't have one, else login using your existing passport id
Download the demo the file. The demo file will be in ISO format
Installing QTP
To install QTP from the ISO file there are 2 methods that can be used
Burn the ISO file on the a DVD using a DVD Burner tool
Mount the ISO file using any Virtual drive tool. You can use freeware tools like Virtual CloneDrive or
Daemon tools to mount the ISO file.
Note The book doesn't endorse or recommend any of above tools specified and should be used at
your own discretion.
Once the DVD is inserted, double click on the drive. This should launch the setup, in case AutoRun on the
system is disabled then you can run the setup.exe file from the root folder. The installation menu will appear
as shown in Figure 1-5. Click on the "QuickTest Professional Setup" option. The installation home screen will
be displayed as shown in Figure 1-6.
Figure 1-5: Installation Menu
After accepting the license agreement, next comes the Add-in select screen. By default only ActiveX, Web
and VB add-ins get installed. To add other any add-in select the same and choose "Entire feature will be
installed on local hard drive" as shown in Figure 1-7.
Figure 1-7: Selecting Additional Add-ins for Installation
After choosing the add-in select the folder where QTP needs to be installed. The default location usually is
"C:\Program Files\HP\QuickTest Professional". If you are planning to install the JAVA addin then I would
recommend changing the path to something like C:\QTP. This would help avoid some of the issues that you
get when JAVA add-in installed. If JAVA add-in is not required then I would recommend to use the default
path itself. Click Next and start the installation. Let the installation finish and there will be a additional
installation require screen that comes up, the different installation required in this will depends on the add-
ins which were selected during the installation.
After the installation process we get an installation complete screen as shown in Figure 1-8. After we hit the
finish button we get another configuration wizard and the configuration items will depend on the add-ins
chosen for installation. This wizard screen is shown in Figure 1-9.
To install QTP with a demo version license make sure to uncheck the "Run the Licenses Installation Wizard".
Note If the wizard is run and a concurrent license is selected then QTP does not install the demo license.
This would be needed to accomplish manually at a later time.
Seat License
Floating License
Seat License
Seat license is a node locked or machine-based license. This license can be used only for a machine it was
generated for, as the locking code QTP generates is specific to the machine it is installed on. To apply for a
seat license, select the "Seat License" radio button as shown in Figure 1-10 and click Next. After clicking
next the license wizard will show the locking code of the machine as shown in Figure 1-11. Note down the
locking code and put a license request on https://webware.hp.com/welcome.asp. Once you receive the
license launch the wizard again and click Next button on the Locking code screen and paste the license key
received by HP. This will install the seat license.
Figure 1-10: Select License Type
Note Seat license uses some of the system components to generate a locking code. Changes in these
components can change the locking code invalidate the installed license. Similarly, the locking code
becomes obsolete if for any reason it becomes necessary to uninstall the system OS and reinstall it. It
would be required to install QTP after a fresh OS install, which will generate a new locking code
rendering the previously generated Seat license useless.
Floating License
Floating licenses can be used on any machine which has network access to the floating license server. At
any point in time the machines using the QTP licenses cannot exceed the maximum license count on the
server. The license server is a utility that needs to be installed separately and comes with the QTP
installation. The license server can be installed on Windows 2000/2003/XP. Floating licenses are per session
license i.e. they are only used when QTP is open on a machine.
To apply for a floating license choose the "Concurrent License" radio button on wizard screen Figure 1-10.
Click on the next button and enter the Server IP or name in the server. Click on the Check Connection
button and if successful the wizard will show the licenses available on the server as Figure 1-11. Click on the
Next button and save the floating license
Note QTP uses UDP port 5093 for communicating with the license server. This port needs to be unblocked in
case of any firewalls
Note We can also create system environment variable with name LSHOST or LSFORCEHOST to specify the
QTP License server IP or address.
QTP's online Help provides lot of useful information while we are working with QTP. But at times, especially
for those new to QTP, finding specific information can be difficult. This chapter explains how to effectively
search the Help file to find what we are looking for.
QTP Help file has four tabs as shown in the Figure 2-1
We discuss each of the first three tabs in the remainder of this chapter.
Contents Tab
This tab provides a structured view of the Help file. The topics presented by this tab depend on what add-ins
have been installed. As each add-in is installed its user's guide is added to this tab and its object model is
added to the Object Model reference folder. We can use the content tab to perform the following tasks:
To look at new QTP features – Go to the "QuickTest New Features Guide" and go through each page
to learn about all the new features
To read through each installed Add-in user's guide in a structured manner
Learning VBScript – We can learn VBScript in the VBScript reference folder. As it is written by
Microsoft, it contains help for VBScript, Dictionary object, FileSystemObject object and Windows
Script Host,
Understanding the QTP Object Model – This important folder explains all about the various QTP
objects. We explore a couple of the key methods and properties from this folder next
Index Tab
Use this tab when we know what individual topics or features we are looking for. For example, suppose we
need details about using the InStr function; in that situation we should select the Index tab and then type
"InStr" into the search field. Performing that set of steps produces the following Help information display on
the right side of the help windows, as displayed below:
Figure 2-3: Index Tab – InStr function
Search Tab
Use the Search tab in situations where we have been unsuccessful in finding the needed information using
the Contents and Index tabs. The Search tab allows us to enter free form text in an attempt to match the
entered string in any part of the Help file. In the following example, when we enter the string, "Search a
string", then it displays all Help file locations which contain that string, in the left pane.
We then apply some deductions to determine which location entry(s) to review for applicability to our
problem. In this example we decide that it will be a VBScript function, so we can ignore all other entries
except where Location indicates "Microsoft VBScript reference". In this example we find our way back again
to the detailed Help page which describes the InStr functions:
QTP stores a definition for each test object in the Object Repository (OR). The definition contains values for
various parameters which are used to uniquely identify an object at runtime in the AUT. The QTP Object
Repository Manager is used to view and modify repository objects and their properties.
Figure 3-1 shows a simple object repository. This OR has a WinToolbar object which is identified with the
Logical Name of "Running Applications" and has two property definitions: "text" and "nativeclass". We can
add and/or remove the properties by clicking the Add/Remove… button. Figure 3-2 shows the Add/Remove
Properties dialog which can be used to add or remove any of the properties from object identification.
Note Selecting an object from the tree view and clicking the Highlight button will highlight the button in the
application (that needs to be open). The same can be done in the code for highlight objects at run-time
Window("Window").WinToolbar("Running Applications").Highlight.
How Objects are Added to the OR
Object can be manually added to the OR by clicking on Add Objects button and then clicking on the object
that needs to be added.
Note In case the object we want to add appears after a mouse click, then press and hold the CTRL key prior
to that mouse click. This temporarily disables the object selection mode and allows us to perform
mouse click operations to navigate. Then, when we are ready to add the object to the OR, release the
CTRL key and click on the object. In case we need to switch between applications, first press CTRL +
ALT to disable the object selection mode. Then we can switch between different applications and use
key combinations like ALT + TAB etc. Once done, press the CTRL + ALT key to enable the object
selection mode and add the object.
Once the object is selected QTP displays the object selection window
The object selection window displays the complete hierarchy of the objects on the web page. Select the
object which needs to be added and click the OK button.
Note The object hierarchy displayed might not be the same as the one recorded in the OR. QTP only keeps
the hierarchy which is necessary for it to identify the object. This also reduces the length of the code
line generated when the object reference is used in a test script.
If we select the page object and continue, QTP will ask if we want to add all its child objects
Figure 3-4: OR Object Selection options
Selecting the Selected object and all its descendants radio button and then clicking OK will add all the
objects present on the page
Note QTP does not add hidden objects present on the page.
Test Objects (TO): Test objects are QTP defined classes used to represent the various objects in the
application under test (AUT).
Run-time objects (RO): Run-time objects are the actual AUT object which a Test Object refers/points to
during test execution.
Comprehending the difference between these two object types is very important. Consider two cars; Car A
and Car B. QTP would represent both cars using a Car Test Object in the script. In addition, each Test Object
also provides methods and properties used to interact with its associated Run-time Object. For example,
methods like Start, Run and Stop would be useful methods provided by a Car Test Object.
TO Properties
Test Object properties are those properties that QTP maintains in the OR for identifying a Run-time object
during test execution. QTP allows enumeration of all TO properties using GetTOProperties. GetTOProperty
and SetTOProperty are used to read or modify the TO property values respectively.
Dim i, iCount
iCount = TOProps.Count - 1
'Loop through all the properties
For i = 0 To iCount
MsgBox newName
We use GetROProperty to read the value of any Run-time Object property, and save the value into a
variable:
'x will have the text present the Search edit box.
x = Browser("").Page("").WebEdit("").GetROProperty("value")
MsgBox x
Note QTP does not provide a method to set Run-time Object properties i.e. there is no SetROProperty. Also
each different test object has a different list of supported property values which is defined in the object
model reference in QTP help.
There are 2 types of object repositories or rather the object repository modes
Figure 3-5: Per Action OR Setting
The Object Spy is a tool used to interrogate methods and properties supported by an object. To launch
object spy go Tools→Object spy…
Click on the pointer button to select an object. When the Test Object Properties radio button isselected, it
will display all the available TO properties in the Properties tab and all available methods in the Methods tab
as shown in the Figure 3-6
Figure 3-6: Object Spy Test Object Properties
Selecting the Run-time Object Properties radio button displays the actual properties/methods of the object
as shown in the Figure 3-7
Figure 3-7: Object Spy RO properties
Most of these properties can be accessed using GetROProperty methods. To know about all the supported
properties refer to the QTP Manual
Note The Object Spy does not display any of the ordinal identifier properties such as CreationTime, index or
location. They can only be evaluated after adding the object to the OR.
Object Identification
Object identification is a crucial part of a test case. QTP does not record properties arbitrarily, rather there is
a configuration that QTP follows while recording a selected combination of properties. We can change these
properties in case the application requires a different combination. To change these settings go to
Tools→Object Identification….
There are three types of properties that QTP uses for object identification
Mandatory properties – These are always captured and saved for the object even if it's possible to
identify the object without some of these properties
Assistive properties – In case mandatory properties are not enough for uniquely identifying an
object, QTP adds the assistive properties one by one, in the order specified, until the object can be
uniquely identified
Ordinal identifier – If, after using all the mandatory and assistive properties, the selected object still
can't be uniquely identified, QTP then uses the ordinal identifier. There are three types of ordinal
identifiers:
Figure 3-8 shows the Mandatory and assistive properties of the WebCheckBox test object on my machine.
User-defined Objects
QTP uses the class name of the Window to identify which type of test object it is. In case our application
does not use standard Window classes QTP might be unable to correctly identify the object. Consider the
Windows search dialog box which has certain checkboxes under the more advanced section. When we try to
add them to QTP OR it would identify the checkbox as a WinObject as shown in the Figure 3-9. This occurs
because QTP does not identify these checkboxes as a generic Test Object class.
Figure 3-9: Search window checkbox identified as WinObject
Once mapped QTP will thereafter be able to identify the object as a WinCheckBox as shown in the Figure 3-
11.
Figure 3-11: User-define object identified as checkbox
The OR Manager does not allow mass update of various object properties
Objects cannot be moved/copied under other objects
It is necessary to re-record the entire test case in the situation where a Frame is added to the AUT
Duplicate objects are often added when re-recording on a Page/Window which was previously
recorded on—thereby creating duplicate Page/Window's in the form: Page_1, Page_2 etc.
Sometimes this issue can be fixed by changing QTP web settings. Go to Tools→Options…→Web
(Tab)→Page/Frame Options… and change the settings as shown in the Figure 3-12
Note Most of these shortcomings have been resolved in QTP 9.x version.
Chapter 4: DataTables
Overview
A DataTable provides a way to create data driven test cases. It is similar to MS Excel spreadsheets and can
be used to run an Action multiple times. Each test case has one global data sheet which is accessible to all
actions inside that test case and each action has its own private data table also known as local data table.
The name local data table is somewhat misleading because it is in fact possible to access any action's local
data table from any other action, but the way of accessing the data becomes a bit different.
Figure 4-1 shows a sample DataTable with 2 parameters, Username and Password.
We can use most of the formulas that work inside a typical Excel spreadsheet. But there are some
differences between a DataTable and an Excel spreadsheet. In fact a DataTable is wrapped around an Excel
spreadsheet—which provides access functionality to the values but does not expose the Excel spreadsheet
object model.
The same DataTable cannot have duplicate parameter names but we can use the same name parameters in
different sheets (Global DataTable and Local DataTable). Each DataTable has only 1 row enabled even when
it is blank and the other rows get enabled when data is entered into a new A DataTable is stored as
"Default.xls" file in the test folder. Figure 4-2 shows how the stored file looks like
Figure 4-2: Default.xls Data table
When viewed in Excel, the first row of the sheet contains the parameter names, while QTP displays the
parameter as the column titles. Therefore, when viewed using Excel, the 2nd row starts the 1st row of data
in the DataTable. The DataTable shown above has only 2 data rows enabled. Note that QTP makes a data
row enabled by marking the borders of the row in the actual spreadsheet. A row with no data but with
marked borders is still considered as an enabled row by QTP. To delete an enabled row we must select the
row and delete it from the context menu which appears on right clicking the row.
As the name suggest the data table during the script design time is known as design time data table. Any
changes to this are saved when the script is saved.
The run-time data table contains a copy of the design time data table when a script is executed. It may
contain values that are changed during script execution and are presented in the test result summary. The
changes made to the data table during run-time are not saved to design time data table. Figure 4-3 shows a
run-time data table from the test results summary
It is important to understand in what situations the global or a local data table should be used. Consider the
following two scenarios
Scenario 1 - Log into the application, book 1 ticket, log out. Repeat the scenario for many users
Scenario 2 - Log into the application, book 3 tickets, and log out
Scenario 1
The Global data table is better suited for this scenario where we have the user name, password and tickets
details as the parameters and we execute the scenario using a single action (which does everything) or
multiple actions (Login, booking and logout).
Scenario 2
A Local data table is better suited for this scenario. Here a good approach would be to split the test into
three actions: login, booking and logout. Login and logout can use the username and password parameters
from the global data table and booking can use ticket detail parameters from its local data table and the
action will be executed for all rows in its local data table.
To run a test case for some number of iterations we need to set the iterations of global data table in the
Test Settings dialog, which is invoked using Test→Settings…→Run (Tab) Figure 4-4 shows the iteration
settings for the global table. These settings are specific to script.
The Action call properties dialog can be used to set the iterations as shown in the Figure 4-6
QTP provides an object model to access various properties and methods in a data table:
DataTable – Represents all the global and local data tables in the test
DTSheet – Represents a single sheet in the test
DTParameter – Represents a single column in a sheet.
Each object has certain functions available and certain properties associated with it. These are explained in
detail in the QTP user manual.
When data is entered into the data table it automatically formats the value using the best possible matching
format. For example, if "12345678901" is entered into a cell then it would be auto formatted to
"1.23456789E+010". In situations where the formats are important the data should be entered with care. If
data entered in the cell start with a single quote ( ' ) then it is always treated as a text and no format
conversion is performed.
We can also define a specific format by right clicking the cell or an entire column and then picking a specific
format from the popup context menu.
Problem 4-1: How to access a parameter from the global data sheet
There are a variety of ways to access a parameter from the global data table, most of which are presented
in the following code snippet:
'By giving the sheet index starting from 1 for the global sheet
val = DataTable.Value("ParamName",1)
Problem 4-6: How to export contents of a WebTable to a data sheet. Let's assume that the first row of the
data table contains the columns heading. We then add those as parameters of the data table:
'Variable declaration
Dim i,j
Dim rowCount,colCount
Dim cellText, objTable
For j = 2 to colCount
cellText = objTable.GetCellData(i,j)
Problem 4-7: How to get value of a parameter from any specific row in the data table
Problem 4-8: How to execute a script for all Global Data Table iterations, when the script is set to run for
only one iteration:
In case we want to manually repeat the code for each iteration, we need to write a bit code.
'Declare variable
Dim i, iCount
'Get # of rows
iCount = oGlobal.GetRowCount
For i = 1 to iCount
'Set the current row
oGlobal.SetCurrentRow i
'Execute the code to be repeated here
Problem 4-9: How to get the number of columns that contain data:
To solve this problem we need to utilize the excel formula COUNTA. We add a parameter to the data table
with the formula and then read its value:
Note The above code won't work when there are no columns in the data table or all the columns have been
used.
Chapter 5: Actions
Actions are used to divide scripts into logically related groups of QTP statements. They are similar to
VBScript functions, but with a few differences. Actions are unique to QTP while functions are supported by
both VBScript and QTP. Actions can optionally pass and receive input and output parameters. When used,
input parameters must be passed first, followed by output parameters. A parameter cannot serve both as an
input as well as an output parameter. In addition to supporting output parameters, Actions can also return a
value. Lastly, an object/array can't be used as an action parameter.
The next step shows how input and output parameters are used by both the calling Action and the called
Action:
Create a new blank test and right click in the expert windows and then go to Action → Insert Call to a New…
as shown in the Figure 5-1
Select "After the current step" radio button and click Ok as shown in the Figure 5-2
Next, browse back to Action1 in expert view and we will see that QTP has added a call to Action2 in the
following line of code:
Next, we add two input parameters, input1 and input2, as well as one output parameter, output1, to the
above Action call:
Next, browse back to Action2 and add the following code that uses the new parameters being passed by
Action1:
In Action2 we access the parameters passed by Action1 using Parameter ("name") statements (we can also
use the Parameter Item statement as well). In our example we also use the ExitAction statement to
terminate Action2 execution as well as return a string value to the calling Action.
After this line of code executes, which occurs when Action2 terminates, the output1 variable contains the
two numbers added by Action2, and the actionOutput variable contains the string returned by Action2 in its
ExitAction statement.
For more details on the RunAction statement refer to the QTP manual.
In our example Action1 only called Action2 for a single iteration. But it is also possible to invoke RunAction
as described below to iterate on a data table, thereby calling Action2 multiple times.
'The code below runs Action2 for all iteration in the local data table
RunAction "Action2", rngIterations, rngAll
'The code below runs Action2 for 1st, 2nd and 3rd data table row
RunAction "Action2", rngIterations, "1-3"
'The code below runs Action2 for only the 2nd data table row
RunAction "Action2", rngIterations, "2-2"
Action run iterations can also be configured in the Keyword view by right clicking on the action call and
selecting "Action call properties…" from the context menu. Then we can set the iteration properties as shown
in the Figure 5-4
Figure 5-4: Action Call Properties – Iterations
Types of Actions
Normal/Non-reusable action – An action that can be called only in the test in which it resides and
can be called only once
Reusable action – An action that can be called multiple times by the test in which it resides and can
also be called by other tests
External reusable action – A reusable action stored in another test. External actions are read-only in
the calling test, but we can choose to use a local, editable copy of the Data Table information for
the external action
An "Insert Call to New…" will create a new action in the current test
An "Insert Call to Existing…" allows insertion of a call to a reusable action present in the current test
or in another test
An "Insert Call to Copy…" inserts a copy of the specified action into the current test. If the copied
action uses checkpoints and OR objects, these are also copied
Before the first action is executed in the test, a code can be executed in two ways
Add the code to a library file and associate it with the test
Or else we can open the Script.mts file present in Action0 manually in the notepad and add the code
before the first RunAction call
To insert a call to existing re-usable action, select a line of code in the expert view then right click and select
the Action→Insert Call to Existing… from the context menu choices. By default the invoked Select Action
dialog shows all the reusable actions present in the current test. To select a shared action from a test not
yet called, click the "…" button to browse to another test. Figure 5-7 shows the Select Action dialog.
Figure 5-7: Insert Call to existing Action
Using the above dialog selections generates a 'RunAction "Action2", oneIteration' line of code. Note that we
can't arbitrarily add this line of code without first following the steps specified above. And deleting the code
statement still keeps the action call information in the test. To completely delete all the information
associated with the call, the Keyword view should be used.
Note By default selected external actions are inserted using a fully qualified pathname. But we can override
this default behavior and use path relative references like "..\CommonActions\Lib1" which searches
one level above the including test's directory. If tests might be moved from one location to another,
always use relative paths references when inserting actions.
To insert a copy of an existing action, select a line of code in the expert view, right click and then select the
Action→Insert Call to Copy… from the context menu choices. This call works for both reusable and non-
reusable action and a new action is created in the current test.
When we insert a call to a copy of an action into a test, the selected action is copied in its entirety, including
checkpoints, parameters, the corresponding action tab in the Data Table, plus any defined action
parameters. If the test we are copying from uses per-action object repository mode, the copied action's
object repository is also copied together with the action.
If the test into which we are copying uses a shared object repository, the copied action will then use that
shared object repository. Before running the test, confirm that the shared object repository contains all the
objects that are referenced in the copied action, and if necessary add any object references needed by the
copied action not yet in the test's shared object repository.
The action is inserted into the test as an independent, non-reusable action, even if the original action was
reusable. Once the action is copied into our test, we can add to, delete from, or modify the action just as we
would with any other non-reusable action. Any changes that we make to this action after we insert it affects
only this action, and changes we make to the original action do not affect the copied action.
Chapter 6: QTP Environment
Variables
QTP environment variables are special types of variables whose values persist across and are shared by all
actions in a test. These values persist for the life of the test's runtime execution. QTP environment variables
can be used to share information across actions, recovery scenarios and libraries. These environment
variables are different from Windows environment variable. Windows environment variable are available to
all the programs running on the machine while QTP environment variables are only available to a test script
running at run-time.
Built-in – QTP provides a variety of environment variables that define information such as the
currently executing test's name, the test's path, the operating system type and its version, and the
local host name. We can check the available built-in environment variables by going to
Test→Settings…→Environment (Tab) as shown in the Figure 6-1
User defined Internal – These variables are defined in a test and saved with the test. These
variables can be modified during run-time
User-defined external – These variables are defined in an external environment file. These
variables are read-only and cannot be modified at run-time. The external file can be associated with
the test and can also be loaded at run-time using the LoadFromFile method discussed later in the
chapter
The Environment object provides access to the values of environment variable. Its methods and properties
are given below.
ExternalFileName Property - Returns the name of the loaded external environment variable file
specified in the Environment tab of the Test Settings dialog box. If no external environment variable
file is loaded, this property returns an empty string
LoadFromFile Method - Loads the specified environment variable file
Value Property - Sets or retrieves the value of environment variables. We can retrieve the value of
any environment variable. We can only set the value of user-defined internal environment variables
using this property
QTP throws an error if we try to access an environment variable that does not exist‥ Therefore we use the
following code to check if the error exists without throwing a QTP exception:
Dim envVal
envVal = Environment(varName)
The code shown below demonstrates the usage of the IsEnvExist method.
The act of assigning a value to a non-existent environment variable causes QTP to implicitly create and
initialize the variable. So building on the previous example:
There are two ways to do this. First method is to write text strings to generate XML statements and second
is to use the XMLUtil object to create XML objects and then export their statements. In the next example,
we use a simpler method by writing strings. Working with the XMLUtil object will be covered in a later
chapter.
<Environment>
<Variable>
<Name>FirstName</Name>
<Value>Tarun</Value>
</Variable>
<Variable>
<Name>LastName</Name>
<Value>Lalwani</Value>
</Variable>
</Environment>
And here are the QTP statements to generate that XML code in an external file:
'Function to get XML tags for a variable with name and value
Public Function GetVarXML(varName,varValue)
GetVarXML ="<Variable>" & vbCrLf & _
"<Name>" & varName & "</Name>" & vbCrLf & _
"<Value>" & varValue & "</Value>" & vbCrLf & _
"</Variable>" & vbCrLf
End Function
End Sub
Note The environment variable names are case sensitive, so FirstName and Firstname are treated as
different variables.
Problem 6-5: How are QTP record and run settings changed using Environment variables?
When we start a web test, environment variables can be used to define the browser type and the URL QTP
uses. The environment variables used to control this are BROWSER_ENV and URL_ENV respectively. In QTP
8.2 the possible values for BROWSER_ENV are IE, NS or NS6 and modifying these values in test script code
won't work. Rather we need to add these statements to a library file and then associate that library with the
test so that the code is executed before the test is invoked.
Add the following two lines of code to a text file and save it as "c:\LaunchURL.vbs"
Now associate the LaunchURL.vbs file by browsing to Test→Settings…→Resources (Tab) as shown in the
Figure 6-2
Figure 6-2: Associated library file
Now set the Record and Run setting to launch a new browser with the mercury website as shown in the
Figure 6-3
When we execute this script we will notice that the browser will open and navigate to
http://www.google.com instead of http://newtours.mercuryinteractive.com.
Note In case the option "Record and run test on any open Web browser" is selected then these changes
would not make any difference, they won't make QTP launch a browser and navigate to the desired
URL. So proper test settings are necessary for the code to work as described.
Problem 6-6: How is an environment variable cleared or destroyed?
QTP does not provide any method to delete an environment variable, but we can always put nothing or
Empty into it to differentiate it with having or not having a value
'Change it to nothing
Environment("FirstName") = Nothing
Note The error generated when the variable does not exist and when the value is set to Nothing is different
but since we are only checking if any error occurred while accessing the environment variable in the
function IsEnvExist this method will work fine.
Problem 6-7: How an object is passed using an environment variable?
If we try to use the Set operator to assign an object to the Environment variable a 'Type mismatch'
exception is raised. There are two ways to deal with this. One is to use a string definition of the object and
then convert it to an object and another is to simply assign the object to the variable without using the Set
operator.
Method 1
Dim objBrowser
objBrowser.close
Method 2
Dim objBrowser
Warning In case the "Browser" is a part of the Action1 OR then using the code given above in Action2 may
not work as the OR for two actions are different. So the code must always be executed within the
scope of the Action.
Problem 6-8: How an array is passed using Environment variables?
QTP throws a "This array is fixed or temporarily locked" exception, if we try to pass a fixed length array
using an environment variable. To pass a fixed length array we need to first assign it a variable and then
assign it back to the environment variable:
Dim dynArr
MsgBox Environment.Value("PassArray")(2)
Problem 6-9: How are environment variables loaded from an external XML file?
The above example highlights the limitation of loading multiple environment files, as the earlier XML
variables are destroyed. There will be a workaround to the issue presented in "Working with XMLs" in a later
chapter.
QTP provides several utility objects to enhance the power of scripting. Below is a list of all QTP utility objects:
Crypt, DataTable, Description, DTParameter, DTSheet, Environment, Extern, OptionalStep, Parameter, PathFinder,
Properties (Collection), QCUtil, RandomNumber, Recovery, Reporter, Services, Setting, TextUtil, TSLTest, XMLUtil
The remainder of this chapter only discusses those objects not covered in the other chapters of this book.
This object encrypts strings in a format that the QTP SetSecure function understands. Encrypt is the only method provided
by this object:
The above statement will assign myVar a value which looks something like:
"45249373c5a4ec489211eda2314133751e8a5cbd529ac9060aee041a38f75636".
This value produced by Crypt.Encrypt is not constant because encrypting the same string again generates a different
encrypted string. Now the question arises that when should this capability be used? Consider a script which is executed on
a tester's PC with the results sent to others. If the script has a step to enter a password:
Then this step will appear in the test result summary and will include the "tarun" value. This could compromise security, so
let's replace the above statement with a new one:
Now the password won't appear in the test results summary as we are using the secure mode of setting a password.
Note We can also create an instance of the Crypt object in VBScript using the following code statement: Set myCrypt =
CreateObject("Mercury.Encrypter").
This object is used to make a statement optional in situations where the statement might fail. Consider the following
statement:
This statement could have been recorded with a browser where security warnings were enabled, but then run on another
PC who's browser does not have those warnings enabled—in that scenario the statement will fail. So when a statement
depends on the system state, it should be made optional using the OptionalStep object:
Page 2 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This object can be used to find the absolute path to a file. QTP allows setting folder paths in the Tools→Options→Folders
(Tab) as shown in the Figure 7-1 and in situations where we want to determine which particular folder a file resides in we
can use PathFinder.Locate method. Consider the following example:
Let's say we want to find the key.txt file located in the "C:\Setups" folder.
Even if "C:\Support" folder also has a "key.txt" file the Locate method will still return "C:\Setups\key.txt" as the "C:\Setups"
folder has a higher priority than the "C:\Support" folder.
This object provides a method to get a random number between two specified values
Since value is the default property for RandomNumber object, we can also use the following syntax:
This object provides the following properties and methods to modify test properties at run-time:
n Add Method
n Exists Method
Page 3 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n Remove Method
n Item Property
The Add Method
Setting.Add "LogErrors","Yes"
Msgbox Setting.Item("LogErrors") 'Will return "Yes"
'Since Item is the default property for
'Setting object we can also use the following syntax:
Msgbox Setting ("LogErrors") 'Will return "Yes"
This method is used to remove any user-defined settings from the object:
Setting.Remove "LogErrors","Yes"
Note We will see how useful the Setting object is in the "Advanced QTP" chapter.
n AutomaticLinkRun
n DefaultLoadTime
n DefaultTimeOut
n ReplayType
n SnapshotReportMode
n WebTimeOut
Refer to QTP online help for more details on these setting values.
Page 4 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Delete cookies
WebUtil.DeleteCookies
Note The WebUtil object is implicitly available after installing QTP Plus, and it can be explicitly instantiated using the
following statement:
This object is used to run and close processes. Below are few examples of starting processes:
This object is used to add new methods to a test object or to override existing ones. The syntax is:
If we want to override the Set Function for the WebEdit test object then we need to create a new function and then assign
it using the RegisterUserFunc object as follows:
Page 5 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Browser("...").Page("...").WebEdit("...").Set "tarun"
The last statement in the above example now calls our NewSet function and changes the input value to upper case and
then sets the value.
If we want to use the NewSet function to handle different types of test objects, then we can use GetTOProperty function to
determine which type of object has been passed to the function
If we want to define a new Set method for all objects like "WebEdit", "WebCheckBox", "WebList","WebRadioButton" etc,
then we can create a function like one shown below
WebSet and WebSelect functions used in the code given above are user defined functions that are being used to do
operation on specific types of object.
Page 6 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Chapter 8: Checkpoints
A checkpoint is used to verify a runtime value against an expected value predefined in a Test. Checkpoints allow setting
Pass/Fail status in the Test Results File.
Types of Checkpoints
n Standard checkpoints: Standard checkpoints are used to verify a set of properties for standard objects. This
checkpoint can be used on objects like Buttons, Images, Radio buttons etc.
n Image checkpoint: It compares the various property values of an Image like source file location, width, height etc.
n Bitmap checkpoint: This checkpoint compares an on screen bitmap image and compares it pixel by pixel against a
previously recorded bitmap
n Table checkpoint: Validates data presented in a screen table against the predefined values
n Text checkpoint: Validates that a text string is presented at an expected place in the application
n Textarea checkpoint: Validates that a text string is displayed in an expected area in the application
n Accessibility checkpoint: Checks for the areas in a web application that do not comply with W3C accessibility
standards
n Page checkpoint: Validates properties on a web page like number of links, page load time, etc
n Database checkpoint: Validates the contents of a database entry specified in the checkpoint
n XML Checkpoint: Validates the content of an XML document or a Web XML document
Note XML and Database checkpoints can be added in recording/design mode. All other checkpoints can be added in
recording mode or through active screen objects.
Refer to the QTP user's manual for the steps needed to insert checkpoints into a test case.
When a checkpoint is executed its result are placed in the Test Results File. A checkpoint statement looks like below:
'Execute the checkpoint
Browser("").Page("").Link("test").Check CheckPoint("TestLink")
Here "TestLink" is the name of the checkpoint and "test" is the object on which the checkpoint is being executed. We can
check the status of a checkpoint by evaluating the return value of a Checkpoint call:
'Save the return value of the checkpoint call
cpStatus = Browser("").Page("").Link("test").Check (CheckPoint("TestLink"))
If cpStatus Then
MsgBox "Checkpoint Passed"
Else
MsgBox "Checkpoint Failed"
End if
In cases where we don't want the status of checkpoint reported in the Test Results File, we use the Filter property of the
Reporter object as follows:
'Disable all events reporting
Reporter.Filter = rfDisableAll
Page 2 / 4
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Reporter.Filter = rfEnableAll
It's important to understand some of the problems that are encountered while using QTP checkpoints:
n Checkpoints are not very flexible. For example, QTP does not allow the expected value of a checkpoint to be changed
through the code—but we can achieve this by using DataTable variables or Environment variables to specify the
checkpoint's expected values
n Checkpoints are stored using a proprietary binary format in the Object Repository—and they are not visible
QTP checkpoints are most suitable when the application being tested is static in nature like an informational website which
contains static content that rarely changes.
Using inline VBScript statements to validate runtime values against expected results generally proves to be a more
effective and flexible alternative to using QTP checkpoints. In this section we convert the previous checkpoint into this type
of inline code validation:
'Read the actual property values we want to validatre from that object
actualHREF = objLink.GetROProperty("href")
actualTEXT = objLink.GetROProperty("text")
We can simulate any QTP checkpoint using this technique, except a bitmap checkpoint.
Note Equivalent Database checkpoints can be simulated using ADODB. We will find more information about ADODB in
the "Working with Databases" chapter. XML checkpoints can be simulated using the XMLUtil object. We will find
more information about using the XMLUtil object in the "Working with XMLs" chapter.
QTP does not allow modifying checkpoint properties at run-time though it is possible to configure a checkpoint to use a
DataTable value or an Environment variable. Also there are some properties that we can modify using the code also.
Usually a checkpoint statement would look like this
Page 3 / 4
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Here CheckPoint("the web") is an object which contains all information about that checkpoint. There are two hidden
functions that the CheckPoint object supports and those are SetProperty and GetProperty. Let's see what properties we
can use with these functions.
Table 8-1: Checkpoint property description
Note micclass, step_type, step_timeout are three common properties that we can get for any checkpoint. Checkpoints
other than the above two are complex and cannot be modified at run-time.
Warning It is not recommended to change the checkpoint properties using the method discussed above as these are
undocumented methods and might not work in later version of QTP
Page 4 / 4
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
By using this method the same instance of the library is shared and accessed by all Actions included in a test. Go to
Test→Settings…→Resources (Tab) and add the library as shown in Fig 9-1:
Note1 These libraries are loaded from the bottom entry to the top entry. In case two different libraries have the same
defined function then the one nearer the top in the list will be used.
Note2 In the case where Library B depends on definitions in Library A, then Library A needs to be nearer the bottom of
the list.
Note3 QTP will use the fully qualified pathname while placing the library in the list. As a recommended option we can
use a relative path of the file, for example "..\test.vbs".
QTP provides the ExecuteFile function to dynamically load a library at run-time. When this method is used the library and
its contents are only visible in the Action in which the ExecuteFile is used. Below are the few examples:
Page 2 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note If ActionA and ActionB both load test.vbs using the ExecuteFile command, and ActionA calls ActionB, note that
they will both be using their own copy and separate instance of all test.vbs variables and functions.
As just described above, using ExecuteFile directly in an Action only makes that library visible within the Action. But every
QTP Script can have a set of global libraries which are available to all test's Actions. So instead of loading a library using
the ExecuteFile directly in an Action, if we load it through a function in one of the global libraries, then it will be available to
all the test's Actions:
'C:\LibLoader.vbs
Public Function ExecuteFileGlobal(ByVal fileName)
ExecuteFile fileName
End Function
We should save the code given above into a VBS file and associate it with the test and thereafter call the
ExecuteFileGlobal in any action to load the file. Files loaded using ExecuteFileGlobal function will be available for the all
the actions.
But when there are multiple Action iterations the call to ExecuteFileGlobal will reload the library multiple times, thus
destroying the current state of the library's global variables each time the library is reloaded.
This issue can be solved by using the following code. We add a reload flag to ExecuteFileGlobal function and when it is
False the library will not be reloaded. This is achieved by creating a global dictionary of all loaded files using
ExecuteFileGlobal. The file path is used to determine if the library has already been loaded.
'C:\LoadLibrary.vbs
Dim loadedFiles
Set loadedFiles = CreateObject("Scripting.Dictionary")
loadedFiles.CompareMode = vbTextCompare
To better understand the above code let's take an example. First create a library file which we will load at run-time
'C:\TestA.vbs
Dim X
X = 2
Page 3 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Sometimes it's necessary to share values across two or more Actions at run-time. Using the same concept we used for
loading the libraries we can create global variables at run-time
Declare.vbs
'C:\Declare.vbs
Sub ExecuteGlobalCode (sStatement)
ExecuteGlobal sStatement
End Sub
Action1:
Action2:
It is important to understand and differentiate between Global and Local scope of a test script.
n Global Scope is a place where QTP loads all the resource and recovery scenario libraries. This is accessible to all
actions present in the test
n Local scope is an action scope where anything defined within the Action is not accessible to anything present outside
the Action
Figure 9-2 depicts the scope view of a QTP script with 2 actions. This is how the QTP works
n QTP first adds all libraries for associated recovery scenarios. This is done in the order the recovery scenarios are
associated from Top to bottom
n After loading all associated Recovery scenario's library files, QTP then loads all the files associated in the
Test→Settings…→Resources (Tab). These files are loaded from Bottom to the Top
Page 4 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n After this QTP calls each action in the order defined in the Test Flow. For each action QTP creates a local scope which
is private to that action. The scope gets created and destroyed on each Action's iteration
n A function written in Action1 would not be accessible in any other Action or the Global scope
Note If more than one library in the global scope contains a function with same name then the last one loaded would be
called.
Option Explicit statement at the top of a library file allows a programmer to enforce variable declaration for all used
variables. We might observe that even having Option Explicit in some of our associated libraries is not enforcing errors for
undeclared variables.
This happens because of the way Global scope is created. We cannot enforce Option Explicit on individual libraries in a
global scope. It can be done only on the complete global scope. To enforce variable declaration Option Explicit should be
put in every library used. If any of the libraries is missing Option Explicit then QTP will not use option xplicit for the global
scope.
We earlier saw how to load library files in local scope from within the local scope ("Dynamically Loading libraries locally at
run-time") and how to load libraries in global scope from within local scope ("Dynamically Loading libraries globally at run-
time").
At times, because of script maintenance we might need to add code to the start or the end of the Action. This maintenance
might apply to multiple no. of scripts. QTP allows opening single script at a time, which makes editing multiple scripts a time
consuming task. To avoid such situations we can call two special functions in our Actions as shown the following code
GetActionStart and GetActionEnd function return either a blank string or some code that needs to be executed. Below is
the implementation of the above two functions
Page 5 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
If InStr(sAction,"main") Then
GetActionStart = "ExecuteFile PathFinder.Locate(""Workaround.vbs"")"
End If
End Function
Page 6 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Object Identification
To identify an object during test script play back QTP stores one or more properties for that object in the Object
Repository, which QTP then uses to uniquely identify the object at runtime. Figure 10-1 shows a simple Object Repository
that contains descriptions for a web page and three of its control objects.
The "Google Search" object in the OR has 3 recorded properties: "type", "name", "html tag". Note that QTP recorded 3
properties, i.e. the mandatory properties defined for this test object, but not all of them may be needed to recognize the
object at runtime.
Implicit Properties
When we define an object description using DP there are certain properties that we don't need to explicitly provide as QTP
automatically assumes certain values based on the test object type being referenced. For example, the "Google Search"
above is a WebButton, and as such QTP assumes that the "html tag" will be the INPUT and the "type" will be submitted.
But in a situation where we reference a generic WebElement, it is necessary to explicitly define every property of
importance
Below are some of the examples when Descriptive Programming is considered a good alternative to using a traditional
Object Repository to define a test object:
n When the objects in the application are dynamic in nature and need special handling to identify them at runtime. The
best example would be of clicking a link which changes according to the user of the application, Ex. "Logout
<<Username>>"
Page 2 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n When the Object Repository is getting very large. If the size of Object repository increases too much then it decreases
the performance of QTP during runtime playback
n When we don't want to use an Object Repository at all. The following scenarios provide some rationale for why we
might not use an Object Repository
n When modification to an OR object is required but the Object Repository in which the object resides is either Read
Only or it is located in a shared OR and the changes may affect other scripts outside of our control
n When we want to take action on large number of similar/uniform objects, for example we have 20 textboxes on a page
and their names are in the form of txt_1, txt_2, through txt_20. In this situation adding 20 entries to the Object
Repository would not be a good programming approach, but using dynamically defined DP statements would be
By using this approach we create a description object and define the properties and values for identification. The
description object is very similar to creating and initializing a Dictionary object. Using this technique the "Google Search"
button can be described as:
Descrition.Create creates a new object to store one DP description. Each description object property supports both a
Value assignment and a RegularExpression flag. By default the regular expression flag is True indicating that its Value
assignment string is interpreted using VBScript's Regular Expression syntax. To click the "Google Search" button using this
DP syntax technique the codewill be:
Note Once we start using any Descriptive Programming syntax in a statement, then the rest of the statement must
continue to use DP syntax. The above code statement starts with OR references through the page reference, but
at the WebButton reference we start using DP syntax.
In the code given above we saw that it took several lines of code to define the "Google Search" button using a DP
description object. Now we provide a subroutine that does most of the assignment work for us:
Page 3 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Dim i
For i = LBound(propArray) to UBound(propArray)
'Split the propery and value from property:=value
valArray = Split(propArray(i),":=")
Execute dpObjName &"(""" & valArray(0) & """).Value = """ &
valArray(1) & """"
Next
End Sub
'Usage
descArray = Array("html tag:=INPUT","Name:=Submit")
descStr1 = "Name:=Submit"
descStr2 = "Name:=Submit,html tag:=INPUT"
CreateDescription "dpSubmit1",descArray
CreateDescription "dpSubmit2",descStr1
CreateDescription "dpSubmit3",descStr2
The micclass is an identifier that describes the type of QTP Test Object. For example the "micclass:=WebButton" is an
implicit property of the WebButton object. When there is only a single button on a page we don't need to use any property
description other than "micclass:=WebButton". We can use GetTOProperty with the micclass on any QTP test objects to
determine its test object type:
'Displays Browser
MsgBox Browser("Browser").GetTOProperty("micclass")
'Displays Page
MsgBox Browser("Browser").Page("Page").GetTOProperty("micclass")
Note "Class Name" is not a property for the type of test object as QTP object spy shows it. micclass is mapped to the
class name in object spy.
In this method of descriptive programming we don't need to create a description object, instead we use a description string
to recognize the "Google Search" button in Figure 10-1. We use the following three description strings in the second line of
code:
But as we said earlier it is not necessary to define all the properties in order to identify the object:
Page 4 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Enumerating ChildObjects
QTP provides the ChildObjects method which is used to enumerate child objects. To enumerate all the textboxes on a
page we can use the following code:
dpAllTxt("micclass").value = "WebEdit"
ChildObjects enumerates all the child objects when we pass it an empty description object:
iCount = allChilds.Count - 1
Converting an OR-based script to a DP-based script demands the careful selection of each OR object's properties required
for each DP statement to uniquely identify the intended runtime object. Consider the OR-based statements below,
recorded when interacting with the Windows calculator to multiply 2 times 5:
Page 5 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Inspecting the OR we notice the objects are recognized based on their text labels. The DP-based converted script will then
use the following statements:
With Window("regexpwndtitle:=Calculator")
'Activate the window
.Activate
Note We have used the regexpwndtitle:=Calculator to recognize the calculator window. We could have also use
regexpwndclass:= SciCalc which looks unique to the calculator application. In case the application window title
keeps changing it is always a better option to choose just the window class or some other property.
It's important to select the correct property (or properties) to identify an object in DP. Selecting properties like x, y, abs_x,
etc., is never a good choice as they are subject to change with each run of the AUT. Properties like title, regexpwndtitle
etc. are in most cases much more reliable.
Placing our DP object definitions in a VBScript library file logically emulates a QTP Object Repository:
UserForm.vbs
Page 6 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
There are two ways to include the above file in one or more scripts:
n Use the ExecuteFile statement to load the file into one or more test Actions
Script
Browser(dpBrowser).Sync
'Enter data
Browser(dpBrowser).Page(dpPage).WebEdit(dpFirstName).Set "Tarun"
Browser(dpBrowser).Page(dpPage).WebEdit(dpLastName).Set "Lalwani"
This technique can also be used to implement a multi-language testing script. To do this create different VBS files for each
language, for example, dpOR_EN.vbs, dpOR_FR.vbs, dpOR_DN.vbs etc. and then use the following code to select the
proper file, based on the language specified:
'...
'The rest of the script goes here
'...
QTP only uses ordinal identifiers when there are multiple object matches for a given description.
The above code statement will tell whether there is a 2nd browser instance open or not. But that is not always the case
because QTP will first see the above statement as:
In situations where QTP is able to resolve the object based on just the above description then it will return the True/False
value. But in situations where there are multiple browsers that exist then QTP must use the ordinal identifier index or
Page 7 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
CreationTime property to uniquely identify each instance. For example, the following code:
bBrowser2 = Browser("CreationTime:=1").Exist(0)
bBrowser3 = Browser("CreationTime:=2").Exist(0)
Return values from the of the above code statements are shown in the Table 10-1
Table 10-1: CreationTime Exist values
Variable Value
No. of Open Browser bBrowser1 bBrowser2 bBrowser3
0 False False False
1 True True True
2 True True False
These results make it clear that in case of 0 or 1 open browser, the CreationTime property was never used for
identification. This creates a problem if we need to determine if a 2nd browser exists or not, because we can't use the code
below to make this determination:
Therefore we can use the following code to reliably test for a 2nd browser. This code uses window handles, which are
always unique for each browser. By comparing the handles returned by both CreationTime:=0 and CreationTime:=1
statement we will know that a 2nd browser exists if and only if the handles differ:
And, because there can't be a browser with CreationTime:=-1, the following statement will return a False value when there
is 0 or more than 1 browsers open:
So here is the complete code to reliably determine if 0, 1 or multiple browsers are open:
Page 8 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
bNonBrowser = Browser("CreationTime:=-1").Exist(0)
Note When there is only one browser then the Browser("CreationTime:=0").Exist(0) statement takes 10 seconds to
return.. This is a known issue with QTP. The only workaround for this issue is to avoid using such DP statements
in situations where only one browser is open. This can be accomplished by intentionally launching a dummy
browser to make the statements work faster.
QTP provides ordinal identifiers index and CreationTime for web browsers that can be used to differentiate between the
browsers at runtime.
'Naviagte to www.mywebsite.com
Browser("micClass:=Browser").Navigate "http://www.mywebsite.com"
The above code statement creates a new browser and opens the specified website in that browser. Now let's launch
another browser:
Script 2
The wait statement lets both browsers launch properly. But the 4th statement that specifies the web site will produce a
"multiple matches of object found" error because the Browser ("micclass:=Browser") statement is valid for both browsers.
Page 9 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
To differentiate between the two browsers we must use the index or CreationTime property unique to each browser:
Use of the CreationTime or index property to identify multiple browsers may cause problems in the following situations:
n Before running the script there are one or more browsers already open
n Running the script from QC. In this particular situation the QC browser might get counted as one of the script browsers
and that might cause the script to fail
n Close all the internet explorer processes before launching any browser. This can be accomplished using the next
statement:
'This may not work well when the script is running from QC as it might
'kill the QC browser as well.
n In the case where a script is using an Object Repository Browser object with the CreationTime property defined, we
can use SetTOProperty to update the CreationTime at run time (Note: Smart identification should be disabled for this to
work properly). For example the following line of code sets the Browser object to point to the 3rd browser:
But the above methods do not always provide reliable browser references. Now we discuss some of the additional browser
identification techniques.
The browser's OpenTitle property defines the browser's initial title when the browser is first launched:
Browser(dpBrowser).Navigate "www.gmail.com"
But we need to know the page title that corresponds to the opening URL and running the above code twice causes an
error because as there will then be two browsers with the same OpenTitle property. So this method is still not a foolproof
Page 10 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The following method specifies nonsense (but valid) opening URL that includes a unique integer:
'Launch a new browser with opening url based on the random number
SystemUtil.Run "iexplore.exe", "about:" & browserID
Browser(dpBrowser).Navigate "www.google.com"
Note We used a "about:#####" format of the URL because if we had used a constant string then the browser would try
to search the website with the string used. The above code is independent of the number of browsers already
open. The only limitation it has is in the case of the popup windows. When we know the URL/title of the popup
then we can use OpenTitle/OpenURL.
The above code provides a reliable method for browser identification and has none of the disadvantages of the other
methods described earlier. It also does not encounter any 10 second delay while using a single browser.
Page 11 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
n Using Breakpoints
QTP must be configured before we can start debugging. Go to Tools→Options→Run (Tab) and make sure that Run Mode
is selected as Normal as shown in the Figure 11-1
If this radio button is disabled it means that Microsoft Script Debugger is not installed on the machine. Download and install
the Microsoft Script Debugger to enable this option.
Using Breakpoints
Breakpoints are inserted into a script to cause the execution to switch from the normal mode to debug mode. We add a
breakpoint in QTP by pressing the F9 key or by right clicking and choosing Insert/Remove breakpoint…from the context
menu on the line of code where we want to place a stop code execution.
A red dot appears to the left of the line where a breakpoint has been set. Once the breakpoint is set we can run the
program. Consider the code below with a breakpoint set on the 3rd line:
'Code to be debugged
Dim X
Page 2 / 5
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
X = "This is a test"
y = Left(x,4)
MsgBox y 'Put a break point here
When this code is executed, QTP pauses at our breakpoint. Make sure we have the debug window visible (If not then go to
View→Debug viewer). There are three tabs in the debug window which we will discuss in the next three sections.
In this tab, we add variable names and statements in the left column, thereafter QTP keeps the contents of the variables
and the results of these statements updated in the right column. Let's add few entries to Watch Expressions tab as shown
in the Figure 11-2
We can see in the Watch pane that x has a value "This is a test" and y has a value "This". We can also change the actual
value stored in the variable by double clicking on value cell and changing the value.
Note Changing of values will only apply when the expression being watched is a variable and not an evaluated value
(Ex – Len(x)).
Now select the variable tab. This tab displays the name and values of all variables currently visible in the local scope as
shown in the Figure 11-3
Page 3 / 5
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This tab is used to interactively execute VBScript statements. Select the Command tab and then type y = "Changed from
command tab" and press the Enter key. Then re-select the Variables tab and note that this new string is now assigned to
variable y:
Note QTP 8.x does not allow debugging VBScript library files associated on the Test Settings, Resource tab, nor does
Page 4 / 5
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
any version of QTP support debugging library files referenced using the ExecuteFile function. The best way to
debug such a file is to a put a message box or to write information to a text file. QTP 11 supports a new method
named LoadFunctionLibrary to support debug libraries loaded at runtime. Refer to QTP 11 chapter for more
details.
Page 5 / 5
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QTP recovery scenarios provide a method for scripts to recover from different types of runtime error conditions. This is
required for an unattended test case execution.
This chapter does not discuss how to create different types of recovery scenarios because that is well explained in the
QTP Manual. Rather, the focus of this chapter is on when and where to use a recovery scenario.
Consider the following code, which has the potential to generate a divide by zero error exception:
The above scenario produces a predicted specific error in a specific location in the code. This type of situation can only be
handled using the "On Error Resume Next" statement, rather than a recovery scenario.
Note QTP Recovery scenarios are NOT activated by VBScript errors; rather they are activated on any error involving
QTP test objects.
We can use a recovery scenario when we know what type of error can occur, but don't know when or where it might occur.
Object state
Application crash
A Recovery action – This specifies what action needs to be taken after the associated trigger event has occurred,
and it can be any one of the following:
Keyboard or mouse operation
Function Call
Page 2 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Post Recovery – This specifies what should be done once the recovery action has been successfully completed, and
this can be any one the following:
Repeat current step and continue
Here in an example of where we could use a recovery scenario. Consider a website that displays a modal dialog every 15
seconds. No application interaction can be performed while the dialog is open. Suppose our test case is to verify each link
on the web page. If the dialog is presented while our script tries to perform some operation in the application, an error will
occur because the browser is disabled while the dialog is displayed. So in this situation we can create a recovery scenario
to automatically close the dialog when a script interaction error occurs due to its presence.
Let us create such an HTML page and a recovery scenario to handle this situation:
C:\TestRecovery.html
<html>
<head>
<script type="text/JScript">
function showmsg()
{
var t = setTimeout("alert('Clicked Me!')",500)
}
</script>
</head>
<body>
<form>
<input type="button" value="Click Me" onClick="showmsg ()">
</form>
</body>
</html>
Clicking the "Click Me" on the above page button will display a message box after 500 milliseconds. Let's create a QTP test
script for the above HTML page
'Launch explorer.exe
SystemUtil.Run "iexplore.exe"
Browser("CreationTime:=0").Sync
Browser("CreationTime:=0").Navigate "C:\TestRecovery.html"
Browser("CreationTime:=0").Sync
Browser("CreationTime:=0").Page("micClass:=Page").WebButton("name:=Click me").
Click
'Now we know that this will display a Msgbox after 500 msec,
'so let's wait for 1 sec and try to click the button again
Wait 1
Browser("CreationTime:=0").Page("micClass:=Page").WebButton("name:=Click me").
Click
Running the above script will produce an error in the last step "Object is disabled". This is because the alert box disabled
the browser. Now we will make a recovery scenario for the above test case and execute it again. Go to Tools→Recovery
Page 3 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Scenario Manager … and click the New scenario button on recovery manager window. Create a Recovery scenario with
following properties
Trigger Event: Pop-up window.
Window title: "Microsoft Internet Explorer"
Recovery Operation:
Operation type: Keyboard or Mouse operation
Then re-run the script and notice a "Clicked Me!" Message box left at the end of the script. This is how the things work in
this example.
The 1st Click event → A message box is displayed→The 2nd click event fails because of object being disabled→ Failure of
the script causes activation of the recovery scenario → The trigger event is identified and the action is taken to press enter
key→ Post recovery re-executes the 2nd click step again.→ The click causes another message box to be displayed and
the script ends
The test results summary will show when a recovery scenario has been used:
There are some situations in which a recovery scenarios won't work. Few of them are given below:
Case 1
Page 4 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
MsgBox x
Window("hwnd:=-1").Exist(0)
Even if we enable the recovery scenarios to be run on "On Every Step", it will not be activated on the first three steps, but it
will be activated on the 4th step, because QTP only activates recovery scenarios on code statements which contain QTP
test objects. Any pure VBScript code error can't be handled using recovery scenarios. So we can either use a dummy step
like Window("hwnd:=-1").Exist(0) or we can use the statement below at any position to force the activation of recovery
scenario:
The above statement forces execution of all enabled recovery scenarios associated with current test.
Case 2
'Division by Zero
X = 2/0
As explained in Case 1 the above error will not cause a recovery scenario to be activated, and can only be handled using
the "On Error Resume Next" statement as described earlier.
Case 3
In the above situation the object is not in the Object Repository and therefore can't trigger any recovery scenario. This type
of exception occurs before QTP has a chance to execute the script's recovery scenario(s).
Case 4
A recovery scenario cannot close a dialog box initiated by code statement inside QTP. Consider the following code
statements:
When the above statements are executed in a script which has a recovery scenario to dismiss unexpected modal dialogs,
the scenarios won't be activated. Neither Recovery. Activate nor QTP recovery itself can close these message boxes.
They either need to be closed manually or they need to be closed by some other process outside QTP. Note that we will
write a VBScript in "Working with APIs" chapter to achieve this.
Problem 12-1: How can we get the status of an Action as Pass/Fail at the end of the action?
The key here is to execute a recovery scenario whose recovery action is a function call and mark the Action as failed when
the function gets called. Create a recovery scenario as given below
Trigger Event: Test-Run error.
Error: Any Error
Page 5 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Recovery Operation:
Operation type: Function Call
Function:
Now in every action we start the action with code as given below
Page 6 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The full window title changes with the site being accessed. But it always starts the "Connect to" string. So we need to first
create a recovery scenario on a popup dialog which contains a title matching the regular expression "Connect to.*". The
recovery action will execute a script function which in turn will fill in all the dialog details. Here is the recovery function to
enter the details of login:
wndTitle = pwdWindow.GetROProperty("title")
We can make the function configurable by putting the User ID and password in an environment variable instead of hard
coding them in the function. One more enhancement that can be made is to define different UID/PWD for different domains.
We could get the domain name using this code:
userID = GetUserIDForDomain(strDomain)
password = GetPasswordForDomain(strDomain)
Page 7 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
QTP comes with some default scenarios that can be found in "\Program Files\Mercury Interactive\QuickTest
Professional\recovery\WebRecovery.qrs". This contains various recovery scenarios for the following pop-up dialogs:
Internet Redirect
Security Warning
Security Information
Security Alert
File download
There are other recovery scenarios as well. We can look up for all them using the recovery scenario manager. It's a good
idea to add all these scenarios to any web application test script, instead of creating our own.
The Recovery object provides various methods to control recovery scenarios using code at run-time. This object provides
the following methods:
Activate – Forcibly activates the recovery scenarios
GetScenarioName
GetScenarioPosition
GetScenarioStatus
SetScenarioStatus
Enabled – This is the default property. It sets/retrieves the current state of the whole recovery mechanism. We can
disable all the recovery scenarios at once by using one of the following statements:
Recovery.Enabled = False
or
Recovery = False
We have already looked at the Activate method and I won't be discussing the other methods here. Each usage is well
described in the QTP user manual.
A Recovery function call can use one of the following prototypes, depending on the type of associated trigger:
Trigger - OnRunStep
Function RecoveryFunction1(Object, Method, Arguments, Results)
Page 8 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Functions which do not use one of the above mentioned prototypes cannot be used as a recovery function.
There are some things that can be done in legal recovery functions. Here are the few examples:
'Recovery function
Function RecoveryFunction1(Object, Method, Arguments, Results)
Select Case Method
Case "Check"
'It's check point that cause an issue
Case "Set"
'It's a Set function that cause issue
Case "Select"
'It's a Select function that caused the issue.
typeOfObject = Object.GetTOProperty("micclass")
Select Case typeOfObject
Case "WebList"
'Try and run recovery for weblist selection
'Arguments(0) will give the value passed
Case "WinList"
'Recovery action for WinList Select method
End Select
End Select
End Function
To get the complete object definition from the QTP object we can use the following function:
Dim sProps()
ReDim sProps(0)
iCount = oTOProps.Count - 1
'Loop through and create a array for string description
For i = 0 to iCount
sProps(UBound(sProps)) = oTOProps(i).Name & ":=" & oTOProps(i).Value
ReDim Preserve sProps(UBound(sProps) + 1)
Next
Page 9 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Example
Set oPg = Browser("micclass:=Browser").Page("micclass:=Page")
MsgBox GetObjectSTR(oWebEdit)
Error Handling
On error resume next statement disables the standard error pop-up dialogs that are normally presented. We should use the
'err.number' to check for any known error situation and then handle them. Whenever an error occurs it is propagated to the
top of the call stack order until a function or code scope with "on error resume next" is found. And if none of these have
been found then VBScript displays the error message.
In the above code the MsgBox "Function Completed" will not be executed. The ErrorFunc raises an error which is then
passed to the calling module and also where we have the code handling the errors.
VBScript does not support 'on error goto' statements because it does not support labels. But there is workaround that we
can use to achieve the same functionality:
Function FuncWithError()
'This function contains the main code that needs to be executed
Dim x, y
Page 10 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
x = 2 + 4
y = x - 2 - 4
x = x/y
End Function
The above technique can be used when we are building frameworks where external sheets are used to run keywords
Page 11 / 11
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Regular expressions are strings containing special meta characters used to match patterns inside the strings. Text editors
use this feature for doing color syntax highlighting and other operations. This chapter covers the basics of regular
expressions in VBScript and how to use them in QTP. Table 13-1 summarizes the most often used meta characters:
Table 13-1: Regular Expression Characters
Meta Character Description
. Matches Any Single Character ( . )
[xyz] Matches Any Single Character in a List ( [xy] )
[^xyz] Matches Any Single Character Not in a List ( [^xy] )
[x-y] Matches Any Single Character within a Range ( [x-y] )
* Matches Zero or More Specific Characters ( * )
+ Matches One or More Specific Characters ( + )
? Matches Zero or One Specific Character ( ? )
() Groups Regular Expressions ( ( ) )
| Matches One of Several Regular Expressions ( | )
^ Matches the Beginning of a Line ( ^ )
$ Matches the End of a Line ( $ )
\w Matches Any Alphanumeric Character including the Underscore ( \w )
\W Matches Any Non-Alphanumeric Character ( \W )
\ Escape character, useful when a meta characters needs to be represented literally
{} Matches X number of occurrences
The "." character matches any single character. For example, "…" will match "12B", "B3B", "123", "ABC", "$g%" etc…
Match Any Single Character in a List [xyz]
A character list inside square brackets matches any of the single characters in the list. For example, "[abc][12]" will match
"a1", "a2", "b1", "b2", "c1" and "c2".
Match Any Single Character Not in a List [^xyz]
The "^" character is a negation character used to exclude a pattern from the regular expression. For example, "[^a][12]" will
not match "a1" and "a2", but will match "11", "12", "c1" etc…
Match Any Single Character within a Range ( [x-y] )
The "[d-h]" construct will match any character ranging from d to h. For example, "[abcdef][123]" can also be written as "[a-f]
[1-3]"
Match Zero or More Specific Characters ( * )
The "*" character is used to match zero or more occurrences of a regular expression that precedes the star. For example,
"a*" will match a blank string, "a", "aa", "aaa" etc, while ".*" matches any pattern of characters. Additional examples are:
"aa*" will match "a", "aa", "aaa" etc..
"[abc][1-4]*" will match "a", "b", "c", "a1", "b1", "a12", "a1234344" etc…
Page 2 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note Many people make mistake and use "User*" to match a string starting with "User" but "User*" will only match
strings like "Use", "User", "Userr" etc…
Match One or More Specific Characters ( + )
The "+" character is used to match one or more occurrences of a regular expression that precedes the plus sign. For
example, "aa*" can also be written as "a+".
"123+" will match "123", "1233", "12333" etc…
A "?" character is used to match zero or one occurrences of a preceding regular expression. For example, "a[123]?" will
match "a", "a1", "a2" and "a3"
Regular Expression Groups ( ( ) )
Use matching parenthesis, "()", to group a regular expression. For example, "(123)+" matches "123", "123123",
"123123123", etc., which makes it different from how "123+" is interpreted.
Match One of Several Regular Expression Phrases ( | )
The "|" character provides a logical OR operation in regular expressions. For example, [(123)|(abc)] will match "123" or
"abc".
Match the Beginning of a Line ( ^ )
A "^" character at the beginning of a regular expression is used to match the start of a line. For example, "^abc.*" matches
any line starting with "abc".
Match the End of a Line ( $ )
A "$" character at the end of a regular expression is used to match end of a line. For example, "abc$" matches "abc",
"123abc", "aabc" etc, at the end of the line, while "^abc$" only matches "abc" on its own line.
Match Any AlphaNumeric Character Including the Underscore ( \w )
A "\w" expression matches any character including underscore. This is equivalent to using the regular expression"[A-Za-z0-
9_]". For example, "\w\w" will match "A_", "a1" etc…
Match Any Non-AlphaNumeric Character ( \W )
A "\W" expression matches any non-word character. This is the negation/opposite of "\w" and is equivalent to "[^A-Za-z0-
9_]". For example, "\W" will match "$", "%", "@" etc…
Using the Escape Character (\ )
A backward slash allows the next character to be treated as a literal character or as a special character instead of literal.
For example, a "." will match any character, but to represent it as a literal period character we use "\." to escape the
period's special meaning. Normally the "t" character is treated as a literal but placing a backward slash before it allows tab
characters "\t" to be matched.
Match a Number of Occurrences ( {} )
The "{}" braces allows matching X number of occurrences of a regular expression. There are multiple ways to use this
capability as shown in Table 13-2
Table 13-2: Multiple occurrence matches
Character Description Example
{M} Matches M occurrences of a pattern. A{2} will match only "AA"
{M,} Matched M or more occurrences of a pattern A{1,} will match "A", "AA" etc… which is equivalent of using "A+". A{0,}
will be equivalent of using "A*"
{M, N} Matches at least M and at most N times A{1,3} will match "A", "AA" and "AAA"
Page 3 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
occurrence of a pattern
Although the QTP user manual does not list all regular expression characters, it does support all VBScript regular
expression characters. Shown next are the other regular expression characters which can be used:
Table 13-3: Miscellaneous regular expression character
Character Description Example
\d Matches any digit. Equivalent to using "[0-9]" "\d{2}" will match all numbers from 01 to 99. Though it won't
match 1 to 9 as they are single digits
\D Matches any non-digit characters. Equivalent to using "\D" will match "A", "&", "$" etc…
"[^0-9]".
\num Matches num, where num is a positive integer. A "(\d)\1\1" will match numbers "111", "222", "333" etc…
reference back to captured matches
\s Matches any white-space character. Equivalent to
"[\f\n\r\t\v]".
\S Matches any non white-space character. Equivalent to "[^
\f\n\r\t\v]".
Problem 13-1: What will the regular expression be for a domain which can have possible value of "
test.app.com", "qa.app.com", "www.app.com"
The ".app.com" is constant in both the string, so we can use the regular expression for that part as "\.app\.com" (a "\"
character is used before "." so that the "." character is treated literally as character and not as a meta character). Now we
need a regular expression which can have a value from test, qa or www. The regular expression for this would be
(test|qa|www). So the complete regular expression would be "(test|qa|www)\.app\.com"
Problem 13-2: What will be the r.e. Matching a date in the format MM/DD/YY?
MM can be from 1 to 12. So the regular expression would be ([1-9]|1[0-2]). For the DD it can be 1-31, so the regular
expression would be "([1-9]|[1-2][0-9]|3[0-1])". For the YYYY part it will be [0-9][0-9]. The combined regular expression for
the date would be "([1-9]|1[0-2])/([1-9]|[1-2][0-9]|3[0-1])/[0-9][0-9]".
This actually matches a string containing the date inside it, to make it just match a string which is a date, we can add ^ at
the start and a $ at the end. So the final regular expression would be "^([1-9]|1[0-2])/([1-9]|[1-2][0-9]|3[0-1])/[0-9][0-9]$".
If the expected value of a property is dynamic, but follows a pattern then regular expressions are most often the best
solution. For example, values NameID_233, NameID_256, NameID_290…‥ etc., follows a pattern where the value always
starts with the string literal, "NameID_", and is always followed by a number. This pattern can be represented using a
regular expression "NameID_.*", where "." and "*" are meta characters with special meanings as shown in Table 13-1. The
"." characters specified here mean any character and the "*" character after the "." means zero or more occurrences of
pattern matching ".".
Regular expressions can also be used to identify QTP Test Objects whose properties are dynamic or when there are many
objects with similar identifying patterns. Let say a webpage contains text boxes where all their names start with the string
literal "Name" and the actual name is a pattern like "Name1", "Name2", "Name3", etc.. To access these text box objects we
can use Descriptive Programming (DP) and one of the following methods.
Method 1
Page 4 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'To access the first text box whose name start with Name
oTextBox("index").value = 0
Method 2
'Set the value of first text box whose name start with "Name"
Browser("").Page("").WebEdit("name:=Name.*","index:=0").Set "Value"
In this method we can also avoid using the regular expression by generating the name at runtime as given here.
If our object is in the repository then we need to change the value using the Object Repository Manager. Using that tool,
open the object repository and browse to the object as shown in the Figure 13-1. Click on the "Constant value options"
button. Now check the checkbox for "Regular Expression" and enter the appropriate text in its input field as shown in the
Figure 13-2.
Page 5 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note If we click the regular expression after entering the text then QTP will ask if we want to add '\' to all the special
characters. We should choose Yes incase we want to match the string literally or No if .we want to match it as a
pattern.
If we are unsure what would be the literal regular expression, e.g. a URL like "http://www.testapp.com/Test%20Test.html".
We can enter the URL in the text box and then check the regular expression checkbox. Clicking the checkbox would open
the dialog for adding '\' to the special characters as shown in the Figure 13-3. The literal string generated by clicking Yes
on the dialog would be 'http://www\.testapp\.com/Test%20Test\.html'
QTP, through the Microsoft VBScript engine, provides the RegExp class which is used for general regular expressions
evaluation and processing. Below is a function that tests a pattern within a string:
'Set pattern.
regEx.Pattern = s_Pattern
'Ignore case
regEx.IgnoreCase = True
'Match complete string or not
regEx.Global = MatchCompleteString
Usage:
Page 6 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
To select a value from a WebList or WebRadioGroup we first get all the list's values using its "all items" Test Object
Property. The values returned are separated with a semicolon ";" character. We then place all values in an array using the
split function:
matches = 0
Regular expressions are also used to extract information from a string. Consider the string "Your package will be shipped
on 10/1/2008 and will be delivered by 15/1/2008". Now a regular expression to match a "DD/MM/YYYY" date pattern would
be "(0[1-9]|[12][0-9]|3[0-1])/(0?[1-9]|1[0-2])/([0-9] {4})"
Page 7 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This approach can also be used to be to extract information from web pages
Regular expressions are also used to replace a substring matching a given pattern. The VBScript LTrim and RTrim
functions remove space characters from the start and end of the string respectively. If we need a function that also
removes additional whitespace characters like new line, tab, carriage return etc., we can implement that by using the
following code:
Dim oRegExp
Set oRegExp = New RegExp
oRegExp.Pattern =RTrimPattern
oRegExp.Global = False
RTrimW = oRegExp.Replace(Text,"")
End Function
Dim oRegExp
Set oRegExp = New RegExp
oRegExp.Pattern = LTrimPattern
oRegExp.Global = False
LTrimW = oRegExp.Replace(Text,"")
End Function
Page 8 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
MsgBox (txtInformation)
MsgBox LTrimW(txtInformation)
MsgBox RTrimW(txtInformation)
MsgBox TrimW(txtInformation)
Page 9 / 9
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Strings
These two functions convert a string from lower top upper case or vice versa:
StrComp
This function compares two strings and returns 0 when they are equal:
'Compare strings
x = StrComp("abc","abc") ' this call returns 0
x = StrComp("abc","aBc") ' this call returns non-zero
StrReverse
Len
Left
This function returns the specified number of characters from the left side of a string:
Right
This function returns the specified number of characters from the right side of a string:
Page 2 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Mid
This function returns the specified number of characters from the middle of the string. If the number of characters is not
specified then it will return the string from the specified mid to the end
InStr
This function returns the starting character position of a sub-string in another string. It returns 0 when the substring is not
found, as character positions within a string starts from 1:
Problem 14-1: How can we find the current page and the total page values from the string "Page 4 of 15"?
First, we search for the " of " phrase within the full string (with a space character at the start and the end).
'Original text
s_Text = "Page 4 of 15"
Next, the length of our search string, " of ", is 4 characters. So to get the total pages value we need to read all characters
after 4 + i_Index. We have two ways to extract this portion of the string—either use the Right function or use the Mid
function. Both approaches are shown below, but the Mid function will produce a cleaner code:
'Get text right from the search string
s_AllPages = Right (s_Text, Len(s_Text) - i_Index - Len(s_Search))
Now the current page count always appears from the 6th position in the string and goes till the start of the " of " string:
Page 3 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'We took the string from the left of " of " and then took the
'string from the 6th position to get the current page no.
s_CurrentPage = Mid(Left(s_Text, i_Index - 1), 6)
Problem 14-2: How can we count the number of "if" phrases in the "if + if = 2 if" string?
'Original text
s_Text = "if + if = 2 if"
s_Search = "if"
Do
i_IndexFound = InStr(i_IndexFound + 1, s_Text, s_Search)
'Search string
s_Search = "if"
'Delete the "if" phrases from s_Text and note the difference in lengths
i_NumCount = (Len(s_Text) - Len(Replace(s_Text,s_Search,""))) / Len(s_Search)
InStrRev
This function is also used to search for a sub-string in a string but searches from the end of the string. It does not reverse
the string and then search it.
Below is an example which should make it clear when it is better to use InStr and when it is better to use InStrRev
Problem 14-3: Given a complete file path specification, extract the filename, file path and drive letter from the
specification
Page 4 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The complete file path specification is "C:\Test\Strings\Function.vbs". We know that the file name must appear after the
last "\" in the string and the drive letter must appear before the first "\"
'File name
s_File = "C:\Test\Strings\Function.vbs"
Now we know the position of the first and the last slash:
'-1 in case we don't want the ":" in the resulting drive letter
s_DriveLetter = Left (s_File, i_FirstSlash -1)
These function removed white spaces from the left, right or both sides of the string:
Replace
This function is also useful in cases of parameterization. Suppose we input a XML to a system and want to parameterize
some value in the XML. In that situation, use Replace function as follows:
Space
String
Page 5 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This function generates a string of specified length for the given character
Array
Join
This function joins the contents of an array into a string. Each array element placed in the string is separated by an
optionally defined delimiter character—if none is specified a space character is used:
'Get an array
x = Array("Tarun","Lalwani","wrote","this","book")
Split
This function performs the opposite actions of the Join function, thus creating an array of strings from an input string:
'Text to be split
s_Text = "Tarun_Lalwani_wrote_this_book"
Problem 14-4: Let's revisit the page number extraction problem again. How can we find the current page and
the total page values from the string "Page 4 of 15"?
In this approach we use the Split function to place each non-space sub-string into an individual array element. Thereafter
we can easily extract the 1st and 3rd array elements to extract the current page number and the total number of pages
respectively.
'String page numbers
X = "Page 4 of 15"
The VBScript Split function of VBScript allows one delimiter character to be specified. In case we want to split a string into
words we need multiple delimiters. Next we create an extended version of Split to achieve this task
Page 6 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Parmeters
'pText - The text to be splited
'Delimiter - This is a set of characters which will be considered as
delimiters.
'each character in the delimiter string will be taken as a delimiter and not
the
'complete string
'IncludeDelimiter - If set to True the resulting array will contain delimiters
also
'revDelimiter - If this is set to True then any character other than specified
in
'delimiter are considered as delimiters
Public Function SplitEx(ByVal pText, ByVal Delimiter, ByVal IncludeDelimiter,
ByVal revDelimiter)
'If a blank delimiter then split the whole string into array
'of characters
If Delimiter = "" Then
iCount = Len(pText)
ReDim outarray(iCount)
For i = 1 To iCount
sChar = Mid(pText, i, 1)
outarray(i - 1) = sChar
Next
Else
'Variable to store the word
sword = ""
iCount = Len(pText)
ReDim outarray(0)
Page 7 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
End If
Next
Now to split a statement into words or line we can use the SplitEx function in following ways:
'Usage:
'Returns Array("You","can't","do","this","can","you")
x = SplitEx("You can't do this, can you?", " ,?;.",False,False)
'Returns Array("You", " ", "can't", " ","do"," ","this", "," , " ", "can", " ",
"you", "?")
x = SplitEx("You can't do this, can you?", " ,?;.",True,False)
Filter
This function returns a sub-set array of the search array containing the specified substring:
'Get an array
X = Array("Tarun","Lalwani","wrote","this","book")
Escape/ UnEscape
This function converts all special characters to their escape values. For example a " " is converted into "%20" where 20 is
ASCII code of " ". This is used in HTML to encode special character and pass it as a part of the URL. UnEscape method
can be used to decode these string and convert the "%XXX" characters back to the actual character
'encode a string
'x="http%3A//mycompany.com/cart%3Faction%3DAdd%26ProdId%3D12%26QTY%3D2"
x = Escape("http://mycompany.com/cart?action=Add&ProdId=12&QTY=2")
Conversion Function
These functions convert one data type to another data type. Although VBScript uses Variant as its only primary data type, it
does have a sub-type which can be dynamically changed by using the functions described in this section.
CBool, CByte, CCur, CDate, CInt, CLng, CSng, CStr
Page 8 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
X = "12/13/2006"
Asc
Chr
Hex/Oct
'returns F5 hexidecimal
x = Hex(245)
These functions are used get the current date, time or both:
Date
Time
Now
Day/Month/Year
Page 9 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Hour/Minute/Seconds
Weekday
This function returns the number corresponding to the day of the week. For Sunday the value is 1 and for Saturday it's 7.
DateDiff
This function is used to determine the difference between two dates. The difference can be based on weeks, months, days
etc…
' returns 2
x = DateDiff ("d", "12/13/2006","12/15/2006")
Note The later or newer date should be provided as second argument to produce a positive difference; otherwise the
value returned will be negative.
Problem 14-6: How can the number of business/working days be calculated between two dates (i.e. difference
should exclude the weekends)?
This problem can be broken down into two parts. The first is getting the difference between two dates, which is easy. The
second, and the more difficult part is getting the number of weekdays only between the date intervals. We get the number
of days by dividing the difference between the dates by 7 and what is left is to determine if the day exists in the interval
which is left when the difference is not an exact multiple of 7. We know that the weekday function returns a numeric value
representing the day of the week where Sunday is represented using 1 and Saturday as 7. Now let's create a small graph
to understand how we can check if a weekday comes between a interval or not
The above table shows the days and their day values for an interval between 10/1 through 10/12. Now if we want to
determine if Monday is present in the interval 10/3 to 10/7. Monday has a value 2 and my start date has a value 3 while the
end date has a value 7, so if I check that 2 (Monday) exists between 3(Tue) to 7 (Sat) then I will be able to tell if that day is
present in between the interval or not. Now the problem arises when the interval is say 10/5 to 10/9. Now my start date has
a value 5 and the end date has a value 2 which is less than the value of start date. Now if I am looking to check for the
existence of a day then I should be checking that the day does come between the 2 and 5 (i.e. 1, 3 and 4 are not present in
this interval). So here is the HowManyWeekDays function:
'Function to check how many times a day appears between
'a given date interval
Function HowManyWeekDays(ByVal startDate, ByVal endDate, ByVal DayToCheck)
Dim startWeekDay
Dim endWeekDay
Page 10 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
startWeekDay = Weekday(startDate)
endWeekDay = Weekday(endDate)
Note It's a good habit to always use ByVal when ByRef is not needed as the default arguments are ByRef.
So here is the final function that computes how many business/working days exist between any two dates:
Timer
This function returns the number of seconds that have elapsed since 12:00 AM (midnight). It can be used to calculate the
time difference between the start and the end of the task..
Note If the task starts before the 12:00AM and ends after the 12:00AM, the time difference calculated would be
incorrect.
Misc
TypeName
This function returns a string that provides the Variant subtype name of a variable:
'Covert to double
x = CDbl(4)
'returns "Double"
MsgBox TypeName(x)
Page 11 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Convert to string
x = CStr(4)
'returns "String"
MsgBox TypeName(x)
VarType
'Convert to interger
x = CInt(4)
Refer to the VBScript Online HELP for a full list of TypeName and VarType values.
GetRef
GetRef method can be used to create a pointer object to a function. The Code below shows the usage of the same
Text1 = "TarunLalwani"
Text2 = "Tarun Lalwani"
'Displays True
MsgBox IsEqual(Text1,Text2, GetRef("ComparePartText"))
'Displays False
MsgBox IsEqual(Text1,Text2, GetRef("CompareText"))
In the above code we are passing a pointer to the comparison function to be used by IsEqual method when doing the text
comparison.
CreateObject
Page 12 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Declare variable
Dim ExcelSheet
sRemoteSever = "127.1.1.1"
'Create an COM object for ProgID "Excel.Application"
'on a remote server
Set ExcelSheet = CreateObject("Excel.Application", sRemoteSever )
GetObject
This function returns a reference to an Automation object from a file or an already open application:
For example, a string contains "DEL (DELHI)", and we want to get the text between the parenthesis "(" and ")". Our function
will also take the start position in the string to start the search
'Function to get a sub-string in a string between
'to specifed characters
Public Function GetStrBetweenChar(ByVal Start, ByVal s_Text, ByVal s_StartChar,
ByVal s_EndChar)
GetStrBetweenChar = ""
If i <> 0 Then
i = i + Len(s_StartChar)
'Usage:
' This will return "DELHI"
MsgBox GetStrBetweenChar(1,"DEL (DELHI)","(",")")
For example - For this string "DEL (DELHI)" the function should return "DELHI)" when the start character is "(". The
algorithm for this is much the same as the function discussed above but the difference is that we don't look for an end
string this time:
'Get a sub string starting from a character
Public Function GetStrFromChar(ByVal Start, ByVal s_Text, ByVal s_StartChar,
ByVal ReturnSameForNotFound)
If ReturnSameForNotFound = True Then
GetStrFromChar = s_Text
Page 13 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Else
GetStrFromChar = ""
End If
If i <> 0 Then
i = i + Len(s_StartChar)
GetStrFromChar = Mid(s_Text, i)
End If
End Function
If the last argument, ReturnSameForNotFound=True, then the function returns the same string as if the start character is
not found:
' This will return "(DELHI)"
MsgBox GetStrFromChar (1, "DEL(DELHI)","DEL", False)
Problem 14-9: Write a function that reads a string word by word where two words would be separated by one or
more spaces.
The trick here would be to trim the string from the specified start position and then search for a space character in the
string and then return the string till that space character
'Function to Get a word starting from a position
Public Function GetWordFromPos(ByVal Start, ByVal s_Text)
GetWordFromPos = ""
Count = Len(s_Text)
If index Then
GetWordFromPos = Mid(s_Text, 1, index - 1)
End If
End If
End Function
Problem 14-10: Create a function TrimAll which trims not only spaces but other whitespace characters like new
lines, carriage returns, and line feeds etc.:
Page 14 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
TrimAll = ""
Dim i
For i = 1 To strLen
strChar = Mid(strText, i, 1)
Select Case strChar
Case vbCrLf, vbNewLine, vbTab, vbLf, vbFormFeed, vbCr, " "
Case Else
Exit For
End Select
Next
strText = Mid(strText, i)
strLen = Len(strText)
strText = Left(strText, i)
TrimAll = strText
End Function
Problem 14-11: Create a FilterStr function which takes a string and character set as input and will filter the string
based on the characters in the character set.
For example, using the string "212-203-9587", and the character set "0123456789", the function will return "2122039587"
or "--" depending on the flag set. The algorithm evaluates each character in the string and checks if it is present in the
character set and depending on the bInCharSet flag builds an appropriate return string:
'Function to filter a charset from a string
Function FilterStr(ByVal strText, ByVal strCharset, ByVal bInCharSet)
Dim strLen
Dim strChar
strLen = Len(strText)
FilterStr = ""
Dim i
Page 15 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
For i = 1 To strLen
strChar = Mid(strText, i, 1)
If InStr(strCharset, strChar) = 0 Then
FilterStr = FilterStr + strChar
End If
Next
End If
End Function
Problem 14-12: Create two functions, one which returns the path portion and another the file name, when
passed a fully qualified path or filename:
Problem 14-13: Write a function that compares two string ignoring new line, line feeds, tab etc. whitespace
characters:
'Usage:
If CleanText(text1) = CleanText(text2) then
Msgbox "String equal after cleaning"
End if
Page 16 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Problem 14-14: Write a function that replaces repeated occurrences of a given character by another character.
Example: this function will return "Tarun_Lalwani" when a input string "Tarun Lalwani" is given for replacing repeated
<Space> characters with a single underscore, '_', character:
'Function to replace continous character occurance of
'a specified character by a replacement character
Function ReplaceMultipleByOne(ByVal strText, ByVal strSearch, ByVal strReplace)
Dim i, strLen, strChar
Dim bFlag
bFlag = False
strLen = Len(strText)
For i = 1 To strLen
strChar = Mid(strText, i, 1)
Sample Code:
X(0) = "This"
X(1) = "is a"
X(2) = "test"
The LBound and UBound functions return the values of lower and upper bound of an array respectively, which in above
example would be 0 and 2.
Dynamic Arrays
'Before using the array the first time the array must be initialized with some
dimension
ReDim X(2)
X(0) = "This"
X(1) = "is a"
X(2) = "test"
We can ReDim a dynamic array to change its size as often as we want. But each time this is done, the values in the array
Page 17 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The above statement resizes the array while preserving the values of the first 3 elements.
In the case of a multi-dimensional array, the Preserve keyword can be used if only the last dimension of the array is
changing.
'Dynamic array
Dim X()
ReDim X(2,3)
'This will work fine as we are only changing
'the last dimension while preserving the array
ReDim Preserve X (2,5)
Problem 14-15: How can we get the UBound/LBound values of multi-dimensional array?
Consider the multi-dimensional array X(4,5,6). UBound(X) will return 4, the upper bound of the 1st dimension. To get the
other dimension we can use the optional parameter of UBound
'returns 4, if the second argument is not
'specified it is defaulted to 1
MsgBox UBound(X, 1)
Execute Statement
VBScript provides a very useful statement, Execute, which is used to execute any statement(s), defined as strings, at run-
time:
Execute [statement]
'Global variable x
Dim x
MsgBox x
'We need to use " as a escape character to specify a " inside a string
x = "Browser(""micClass:=Browser"")"
MsgBox x.Exist(0)
Similarly we have an ExecuteGlobal Statement which executes the statement in global scope:
Page 18 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Global variable x
Dim x
x = 4
Call Func1
Sub Func1()
Dim x
x = 3
'Will give output as 3, local variable
As the execute statement executes in the Local Scope the message box displays a value which is 3, while the
ExecuteGlobal statement executes in the Global Scope and displays a value 4.
Eval Function
'assigns a value 2 to x
Execute "x = 2"
Problem 14-16: How can we declare and initialize a read only variable at run-time?
x = "http://www.noone.com"
VBScript does not support optional parameters but there are some workarounds that can be used to achieve similar
functionality:
n Method 5 - Optional arguments using an Array of Hybrid (key, value or key:=value) pairs
Using Null/Empty Values
Page 19 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'In case of error assume that it's a object and return false
If err.Number <> 0 Then IsMissing = False
End Function
'Usage:
This method defines an array as the input parameter and then uses one or more Array elements and the actual parameters
'Usage:
The problem with this approach is that if the last parameter is missing we have to pass a Null value every time. We can
improve that by expanding the array automatically in case there are missing parameters
Dim Params
Page 20 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Arguments = Array(Arguments)
End If
Params = Arguments
'Usage:
In this method we pass the arguments as a value pair, one as the name and another as its value. The number of
arguments in this case needs to be even. We would create a dictionary from the array and use it as parameters. Let's first
look at the parameter conversion from array to dictionary.
Dim Params
Params = Arguments
'Usage:
'Method to demonstrate
Public Function OptParameter_Method3 (Arguments)
Set Params = CreateObject("Scripting.Dictionary")
Page 21 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Usage:
Call OptParameter_Method3 (Null)
Call OptParameter_Method3 (Array "FirstName","Tarun","LastName","Lalwani"))
Call OptParameter_Method3 (Array("FirstName","Tarun"))
Call OptParameter_Method3 (Array("LastName","Lalwani"))
In this method function arguments are passed as key:=value pairs. The function which converts the passed values to a
dictionary would change:
Dim i, iCount
iCount = UBound(Arguments)
For i = LBound(Arguments) to iCount step 1
valPos = InStr(Arguments(i), ":=")
ParamName = Left (Arguments(i), valPos - 1)
ParamValue = Mid (Arguments(i), valPos + 2)
'Method to demonstrate
Public Function OptParameter_Method4 (Arguments)
Set Params = CreateObject("Scripting.Dictionary")
'Usage:
Call OptParameter_Method4 (Null)
Call OptParameter_Method4 (Array("FirstName:=Tarun","LastName:=Lalwani"))
Call OptParameter_Method4 (Array("FirstName:=Tarun"))
Call OptParameter_Method4 (Array("LastName:=Lalwani"))
In this method we support passing function parameters using both (Key,Value) or Key:=Value pairs. The advantage of this
method is the ability to pass arguments in any order and the ability to pass objects at the same time using (Key, Value)
pairs.
Page 22 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Dim i, iCount
iCount = UBound(Arguments)
For i = LBound(Arguments) to iCount step 1
valPos = InStr(Arguments(i), ":=")
If valPos = 0 Then
'It's a key,value pair
ParamName = Arguments(i)
'Move to the value
i = i + 1
ParamValue = Arguments(i)
Else
'It's a Key:=Value pair
ParamName = Left (Arguments(i), valPos - 1)
ParamValue = Mid (Arguments(i), valPos + 2)
End if
'Method to demonstrate
Public Function OptParameter_Method5 (Arguments)
Set Params = CreateObject("Scripting.Dictionary")
'Usage:
Call OptParameter_Method5 (Null)
Call OptParameter_Method5 (Array("FirstName:=Tarun","LastName:=Lalwani"))
Call OptParameter_Method5 (Array("FirstName:=Tarun"))
Call OptParameter_Method5 (Array("LastName:=Lalwani"))
Page 23 / 23
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
When the application under test takes some time to respond to an action, QTP might execute the next step for which the
application is not yet ready. In this situation QTP might throw an error. For example, if in the Step1 QTP selects a value
from a list that will cause a button to be enabled after some processing, QTP's attempt to click the button before it gets
enabled will result in QTP throwing an "Object is disabled" exception.
Synchronization Points are used to insert pause time or wait time before executing certain steps within a test. These points
help avoid unnecessary errors due to the higher response time of the application under test. QTP provides three different
types of Synchronization Points:
'Select Option1
Browser("..").Page("..").WebList("List").Select "Option1"
But sometimes the Sync method may itself throw an error. In such cases the On Error resume next constructs should be
used as shown below:
'Select option1
Browser("..").Page("..").WebList("List").Select "Option1"
'Select option 1
Browser("..").Page("..").WebList("List").Select "Option1"
Page 2 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
In case the object does not exist before the operation starts we can also use the Exist method:
'Select option 1
Browser("..").Page("..").WebList("List").Select "Option1"
Using the above code, users who specify a good login and password, which is normally the case, these users will waste 5
seconds waiting for a Login failure message that will not occur. In this example, a "Logout" link appears when the login is
successful, so if we test for both conditions we can proceed as soon as either occurs:
Page 3 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The above code might seem lengthy, but putting the code in a function and re-using it will reduce the time wasted during
execution.
There is no documented difference between Sync on browser and a Page. Though these two seem to be different on what
they wait for. Page sync will wait for the page to load which will work in cases where there are no frames inside the page.
While a Browser Sync will wait for the page to load and also for all the frames inside the web page.
Events
There might be times when synchronization does not help. This might happen because of events not being fired. Let's look
at an example of an HTML code
<HTML>
<BODY>
<INPUT name=txtName type=text size=10 onkeyup="cmdClick.
disabled=false">
<INPUT name=cmdClick type=button DISABLED value="Click me">
</BODY>
</HTML>
The page behaves in such a way that when a user presses any key in the text box the Click Me button gets enabled. Let's
record typing something into the textbox:
But when we re-run this code the Click Me button won't get enabled as shown in the next figure:
When we run the above code in QTP, we observe that the text is set but the button does not get enabled. This happens
because QTP has an event configuration which tells it to optionally record an event. Looking at the HTML source code we
used above, we find that its onkeyup event needs to be triggered to enable the button. So we can use the QTP code below
to cause this event to occur:
Page 4 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Browser("..").Page("..").WebEdit("..").Set "Test"
If we don't know which event has been defined for the edit we can fire all of them:
When we use descriptive programming we always need to add the fire event ourselves. And in the situation where the
code is added by QTP then it will only record the FireEvent statement based on the Web Event Recording Configuration.
There are three possible profiles for this (Low, Medium & High). To change the configuration, go to Tools→Web Event
Recording Configuration… and click the Custom Settings… button. Select the test object we want to modify as shown in
the Figure 15-2
Notice that even in the High configuration only onkeydown is supported. But in our example the onkeyup event must be
fired, but QTP does not support recording this event. QTP only supports the following—all others need to be fired
manually:
onchange, onblur, onfocus, onmousedown, onmouseup, onmouseover, onmouseout, onsubmit, onreset and
onpropertychange.
Replay Options
By default QTP is configured to replay against web objects using browser events and that is why we had to explicitly use
FireEvent in the above code. But we can configure QTP to replay events using the mouse. To change the replay type go
to Tools→Options…→Web(tab)→Advanced…(button) and select the ReplayType radio button value as Mouse, as shown
below:
Page 5 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Page 6 / 6
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Test Results provides a summary of a QuickTest run session. The results are stored in an XML file format. QTP provides a
Test Results viewer tool used to review and print these results. Test Results optionally contain image snapshots, based on
QTP configuration settings. Figure 16-1 shows a typical test result summary:
The left hand pane provides summary information about each step performed during the test run. Icons to the left of each
step provide the following information as well:
n Smart Identification: If Smart identification is used to identify an object then that step is assigned the warning icon
n Error: If a step encounters any error, it will be assigned the failed icon
n Custom events: Custom events are used to directly assign a step an explicit status
It is possible to control what types of steps are written to the test results using the following statement:
Page 2 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The <Filter Value> must use one of the following QTP built-in variables:
The following code shows how to suppress a single checkpoint's pass/fail status:
If chkStatus Then
MsgBox "Passed"
Else
MsgBox "Failed"
End If
We can insert our own steps in the Test Results using the following statement:
The <EventStatus> should use one of the following QTP built-in variables:
While the <ReportStepName> and <Details> parameters are plain text strings, it is possible to embed HTML tags into
these strings as follows:
'Add to reporter
Reporter.ReportEvent micDone, "Link", sHTML
Page 3 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
QTP also supports one more undocumented EventStatus, micInfo. Using micInfo creates a step with an "i" icon for the
step. This is useful to report just information in the report, which we may want to visually segregate from the similar
micDone entries.
'Clean up
Set file = Nothing
Set FSO = Nothing
Running the above code will display the file as shown below:
Page 4 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This section describes various ways of inserting screen snapshots into the Test Results.
Method 1
Configure QTP to save a screen snapshot for every step. Go to Tools→Options…→Run (Tab) and set the option for "Save
step screen capture to results:" to "Always" as shown in the Figure 16-3.
This is a disk intensive option when the script contains even a modest number of steps, as each screenshot taken
increases the size of the results folder.
Method 2
In this approach we use the SnapshotReportMode setting. This allows us to selectively determine when a snapshot is
captured. The trick here is to use the Exist method on the object's whose snapshot needs to be captured:
Setting("SnapshotReportMode") = 0
Method 3
This approach saves an explicit snapshot using the CaptureBitmap method in the Test Results folder. After adding the
snapshot we also add an HTML image tag to the results to display the image.
Page 5 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note Problem with using above approach is that we use absolute file path for the image. So when the test results folder
is transferred to any other location, the above path will become invalid and the test results would become invalid.
Unfortunately QTP does not provide any way of using Relative paths for such situation.
QTP creates Test Results in XML format in a proprietary folder structure that can't be viewed without the using QTP's Test
Results viewer tool. But results can be converted into HTML format using XSLs. QTP provides three such XSLs which can
be used to convert a XML file to HTML:
n PDetails.xsl
n PShort.xsl
n PSelection.xsl
We can apply the first two XSL using the ApplyXSL function created in Chapter "Working with XMLs". Using the
PSelection.xsl is beyond the scope of this book.
QTP has a Logger routine which sends events to all installed and enabled media. Each reporting library is called as Media
and is a COM library. QTP by default provides the following media:
By default the HTML media is disabled. To activate the HTML results open regedit.exe and Navigate to
"HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\QuickTest Professional\Logger\Media\Log" and change the
"Active" value from 0 to 1. Now QTP will generate results in HTML format as well.
We can create our own custom reporting media templates also. Refer to QTP Plus help for further information on this.
The QTP Reporter object supports the following methods and properties:
n Filter
n ReportEvent
n ReportPath
Additionally the Reporter object also supports the following undocumented methods:
n GetContext
n GetParentId(Id)
Page 6 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n RestoreContext
n SetContext(EventId)
n SetRegistryRoot (Root)
n StoreContext
n UnStoreContext
The two methods from this list we are interested in are GetContext and LogEvent. The Context method defines the id of
current node in the tree structure of the results.
n pDescription – Dictionary of parameters and their value for given event type
The function returns the context id of a newly created node in the report. By using this return value in ParentId we can
report nested events. Earlier we saw that we cannot use relative paths while reporting images to results.
But we can use relative paths when using these undocumented methods as described below:
'Capture the desktop to the Report folder in current test results path
Desktop.CaptureBitmap Reporter.ReportPath & "\DesktopImage.png", True
'Enable Filter when set to False will display the node even if the
'filters are set in report viewer
oEventDesc("EnableFilter") = False
'Icon details
oEventDesc("DllPAth")="C:\WINDOWS\system32\shell32.dll"
iconIndex = 23
oEventDesc("DllIconIndex") = iconIndex
oEventDesc("DllIconSelIndex") = iconIndex
oEventDesc("IconIndex") = iconIndex
oEventDesc("IconSelIndex") = iconIndex
Page 7 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
oEventDesc("Status") = micGeneral
These techniques have the following advantages over the ReportEvent method:
n Inserts HTML step information without having to use "<" and ">", etc. HTML tags.
The Test Results produced using the script above is shown in the Figure 16-4
Note The images inserted using above method are also visible when results are viewed from Quality Center. This was
considered a impossible task till QTP 10.
QTP creates the results in the test results folder. We may want to access these results at the end of the test script to save
them to another location or to send them through email. Let's say we want to copy the Results.xml file which is created in
the Report folder. We can write the following code to perform this task in a QTP script:
Page 8 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
sResultDir = Environment("ResultDir")
When we run this code, it executes without error, but when we inspect "Copy_Results.xml" file the size is 0. This occurs
because QTP does not save the Test Results to disk until the script has terminated. This means we can only export the
results when QTP has finished script execution. But we can't execute the code to export the test results with QTP stopped.
There are two possible workarounds for this problem.
Method 1
In this method we create an external VBS file. The source and destination location of the results is then passed to the
external VBS file that we created. The script waits for QTP to finish execution and then copies the results to the specified
destination. Here is what the VBS file looks like:
'C:\CopyResultsAtEnd.vbs
'Get the input arguments to the script
sSourceFile = WScript.Arguments.Item(0)
sDestinationFile = WScript.Arguments.Item(1)
In QTP we use the following code to execute the above VBS in asynchronous mode:
Note The above code should be put in a VBS File and associated with the test, so that the code only runs once during
the test. Refer to the "Library Files" chapter on how to load a library only once.
Page 9 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Method 2
This method is a never recommended compared to method 1 but it allows us to copy the results from QTP itself. As
discussed in the earlier problems, we know that QTP sends an "EndTest" and "EndRepLog" to all the media. The media
then finalize the report. So if we can send these events to the media from QTP itself this means we can finalize the results
and then copy it from within the QTP script itself using the following code:
Note If the above code gets executed at every iteration then it will not create the complete test results. This should be
run only on the last iteration of the test case.
Page 10 / 10
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
The Microsoft Windows Application Programming Interface (API) provides building blocks used by applications written for
Windows. Windows APIs provide various functions to do operations like getting cursor coordinates, window handles,
colors, etc. QTP supports calling these functions defined within the DLL file, but due to VBScript limitations only a limited
set of APIs can effectively be used within QTP.
Additional details and information about APIs used in this chapter can be obtained from MSDN or the API Viewer tool that
comes with Visual Studio.
Extern Object
QTP provides an Extern utility object which is used to declare APIs and then call them,
Syntax
Looking at this API we need to determine parameters suitable for use with the QTP Declare method:
RetType = micLong (Return type of the function)
MethodName = "GetForegroundWindow" (we can use any name but it's a good practice to use the actual API name)
LibName = "user32.dll". In situations where we are not using a windows system DLL then we must specific a fully
qualified filename, for example "C:\MyApp\Lib\mylib.dll"
Alias = "" or "GetForegroundWindow". Since the MethodName we provided is the same as the Alias name, we can
leave the Alias name blank.
Extern.Declare micLong,"GetForegroundWindow","user32.dll","GetForegroundWindow"
Some examples are provided below to show how we can use APIs to solve commonly encountered problems.
Problem 17-1: How can we determine if the topmost window on the desktop is a browser window?
If isBrowser then
Msgbox "The top most window is a browser"
End if
Page 2 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Problem 17-2: How can we get the value of a Windows Environment variable? (Note that QTP environment
variables differ from Windows environment variables).
'Variable declaration
Dim s_EnvValue
Problem 17-3: How can we check (select) an item in a List box using a Windows API?
Problem 17-4: How can we get the background color of a text box (helpful when a color for a mandatory field id
different than an optional color)?
Dim hDCSource
Dim hWndSource
Dim backColor
'Get the handle of the control
hWndSource = Window("Window").WinEdit("MandatoryField1").GetROProperty("hwnd")
'bring the window to foreground. This is important as GetPixel
'works only on visible pixels
extern.SetForegroundWindow hWndSource
MsgBox backColor
'Release the device context handle
Extern.ReleaseDC hWndSource, hDCSource
Page 3 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Problem 17-5: How can we simulate a keyboard event using the Windows APIs?
Sub KeyDown(KeyAscii)
keyCode = extern.MapVirtualKey(KeyAscii, 0)
'Fire the key down event
extern.keybd_event KeyAscii, keyCode, KEYEVENTF_KEYDOWN, 0
End Sub
Sub KeyUp(KeyAscii)
keyCode = extern.MapVirtualKey(KeyAscii, 0)
'Fire the key up event
extern.keybd_event KeyAscii, keyCode, KEYEVENTF_KEYUP, 0
End Sub
Sub KeyPress(KeyAscii)
KeyDown KeyAscii
KeyUp KeyAscii
End Sub
SystemUtil.Run "calc.exe"
Window("title:=Calculator").Activate
Call KeyPress(vbKey1)
Call KeyPress(vbKeyAdd)
Call KeyPress(vbKey2)
Call KeyPress(vbKeyReturn)
Call KeyDown(vbKeyControl)
Call KeyDown(vbKeyAlt)
Call KeyDown(vbKeyS)
Call KeyUp(vbKeyS)
Call KeyUp(vbKeyAlt)
Call KeyUp(vbKeyControl)
Problem 17-6: How can we prevent a PC from being locked by its screen saver?
Sometime it's necessary to run scripts unattended for long periods of time. This can be a problem when the screen saver
policy causes the PC to become locked after a few minutes without keyboard or mouse activity. QTP will not execute a
Page 4 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
script while the PC is locked. We can avoid this situation by simulating keyboard or mouse events as follows:
'C:\PreventPCLock.vbs
Const micVoid = 0
Const micByte = 26
Const micLong = 3
Const KEYEVENTF_KEYUP = &H2
Extern.Declare micVoid,"Sleep","kernel32","Sleep",micLong
While True
extern.keybd_event 0, 0, KEYEVENTF_KEYDOWN, 0
Extern.Sleep 20000
Wend
Note The above code may produce an error indicating that the specified module could not be found. This happens
because information about the DLLs hosting these classes in registry is stored without the complete path. To
overcome this issue the bin folder of the QTP installation should be added to windows PATH environment
variable.
We can also add the QTP bin folder to windows PATH environment variable using the code below
Next
End Function
AddToSystemPath "C:\Program Files\Mercury Interactive\QuickTest Professional\bin"
Sending a keyascii 0 to keybd_event causes a keyboard event but no key press. The above script can be run as a
VBScript file
'Declarations
Private Const SW_MAXIMIZE = 3
Extern.Declare micLong, "ShowWindow", "user32.dll", "ShowWindow", _
micHwnd, micLong
Page 5 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
sSourceURL = "http://mysite/logo.gif"
sTargetFile = "C:\logo.gif"
Since VBScript only supports variant data types it imposes restrictions when attempting to call APIs that use structures.
This section discusses workarounds to these limitations.
We can execute the GetCursorPos API which uses a Point structure to obtain the current mouse coordinates. First we
create a COM object in VB6 using the steps given below and then we use the just created COM object in QTP to execute
the API.
Launch VB6 and create a blank "ActiveX DLL" project as shown in the Figure 17-1
Page 6 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
By default a class will be added to the project. Rename the project and class as appropriate. Here we arbitrarily name the
project "WindowsAPI" and the class as "API".
Open the Visual Studio API Text Viewer and add the required API (GetCursorPos) and Structures (POINTAPI) as shown in
the Figure 17-3
Page 7 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Now we must create a function inside the class which executes the API and returns the result. We will pass X and Y
arguments 'by reference' to this function. The function will now call the API and use the values returned in the structure to
assign it to the X and Y parameters. The code below needs to be added to the class module (remember to keep the
arguments as variant, otherwise a "Type Mismatch" exception is thrown when used in QTP):
We could add functions for other APIs as well. Once done we need to create a DLL of the library. Go to the File→Make
WindowsAPI.dll and save it to the desired location:
Once done the DLL must be registered on each PC where it will be used. Copy the DLL into a folder on the target PC and
register it using the REGSVR32 utility, as shown next:
To access this new DLL in QTP we need to create its object. The ProgID that needs to be used with CreateObject would
be "<ProjectName>.<ClassName>", as shown below:
Dim x,y
winAPI.GetCursorPosition x,y
Page 8 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n The need to copy and register the DLL on each PC where the script will be executed. This often requires Administrator
rights
n ActiveX objects sometimes present issues like "ActiveX component can't create object"
n VB6 or a similar tool, which often requires an additional license, is needed to create the custom COM library
This section presents a solution which is easy as compared to creating a custom COM library, because Microsoft Excel is
widely used and it is available on most PCs. The solution is to embed the needed function(s) inside an Excel spreadsheet
and execute it using Excel COM APIs.
Use the steps below to create an Excel spreadsheet wrapper containing the same functionality that we developed in the
previous custom COM library example:
Create a new Excel spreadsheet and open the VBA editor by pressing ALT + F11 or by going to menu Tools → Macro →
Visual Basic Editor
Add a module and then copy the following API declaration into that module:
Go to "ThisWorkbook" sheet and write the functions that we want to execute as shown in the Figure 17-5
Page 9 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Save this sheet to a desired location—in this example we will use C:\APICode.xls.
Use the QTP code below to execute the function inside the just saved spread sheet:
n The code can be added to the QTP test script's data table itself, which is always available on each PC where the test
script is configured to be executed by QTP
n The code can be easily modified and there is no need to recompile as it is in the case of a custom COM library
Note Macros should not be saved in the Data table sheet (usually Default.xls found in the script directory), as these
sheets are overwritten when test cases are saved.
Some QTP developers may see this 2nd approach as an unwanted dependency. So the next section describes a third
approach that generates the needed macro at the run-time using VBE automation classes.
Page 10 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'C:\MyCode.bas:
Attribute VB_NAME = "MyCode"
Option Explicit
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" Alias "GetCursorPos"
(lpPoint As POINTAPI) As Long
Note We could also create the above file at run-time within QTP using the FileSystemObject.
Note: The above code will error out if the Excel Macro security has the "Trust access to Visual Basic project" disabled.
To change the settings go to Tools→Macro→ Security…→Trusted Publishers (Tab) and check the checkbox for "Trust
access to Visual Basic project" as shown in the Figure 17-6
Page 11 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Warning We should always make sure that the key is deleted after this code is executed, so that the system is
protected against any kind of threats when the option is enabled.
Method 2:
Page 12 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note In this we can use the TestThis function/method as a normal function accessed using the Workbook. In Method 1
we had used the Application object to run the code instead of the workbook object.
n There is no QTP/VBScript limitation in terms of API usage and other availability of VBA supported functionality
n This technique can also be used to run code specific to Excel inside Excel as it eliminates any external process
communication and increases code performance
n This technique can be used to create generic functions with optional parameters as VBA support optional and
ParamArray parameters
QTP can't proceed in situations where it is waiting for a modal dialog box to close, Consider the following page of html
code:
<HTML>
<BODY>
<P> Select the file
<INPUT type=file name=mod>
</BODY>
</HTML>
Now we attempt to execute the following QTP code, when the above page is open:
MsgBox "2"
QTP waits forever for the click event to complete and can't execute the MsgBox statement. A QTP Recovery scenario does
not help because no error occurs while QTP waits indefinitely for the dialog to close. In this situation the dialog has to be
closed either manually, or externally through another program, or the click has to be done using mouse events.
This API is used to get a child object of a specified window. This will be used to get the handle of the button inside the
message box.
PostMessage
Page 13 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This API activates the specified window and brings it to the top of the desktop.
Now we combine these APIs in the following code to close a non-QTP message box. This code finds the handle of the
dialog with a specific title, then finds the handle of the child button to close the dialog and then sends a message to click
that button:
'API declarations
Extern.Declare micLong,"FindWindow","user32.dll","FindWindowA", _
micString,micString
Extern.Declare micLong,"FindWindowEx","user32.dll","FindWindowExA", _
micLong,micLong,micString,micString
Extern.Declare micLong,"PostMessage","user32.dll","PostMessageA", _
micLong,micLong,micLong,micRef+micLong
Extern.Declare micLong,"SetActiveWindow","user32.dll","SetActiveWindow", _
micLong
If hwndButton Then
Msgbox "Got the button, Activating the window and clicking the button"
'Activate the window
Extern.SetActiveWindow hwndWindow
'Post the BN_CLICK message twice. We are doing it twice as
'sometimes the first message is missed
Extern.PostMessage hwndButton,BN_CLICK, 0, 0
Extern.PostMessage hwndButton,BN_CLICK, 0, 0
Else
Msgbox "Cannot find the button"
End If
Else
Msgbox "Cannot find the window"
End If
We can test this code by creating a VBScript file that contains the following code:
Run the VBScript and see that the message box is appearing. Now run the script we created in QTP and see that the
message box disappears as QTP clicks on the button. But there are some limitations to this solution:
n It runs in QTP and hence we cannot do anything else while running the code
n If we are not sure when the window will appear then the above code can't be successfully used
To overcome these issues we need to write the code in VBS file and invoke it from QTP asynchronously using the WSH
Page 14 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Shell object. It means that the script does not execute in the QTP environment and therefore the Extern object is not
available. As it turns out the QTP Extern object is simply the "Mercury.ExtrenObj" COM object, so we can replicate this
functionality in a VBScript, as long as the QTP is installed on the execution PC. Since this solution does not use the QTP
environment so we need to declare all needed QTP constants in the script as follows:
'C:\AutoClick.vbs:
Const micLong = 3
Const micString = 8
Const micByRef = 32768
Extern.Declare micLong,"FindWindow","user32.dll","FindWindowA", _
micString,micString
Extern.Declare micLong,"FindWindowEx","user32.dll","FindWindowExA", _
micLong,micLong,micString,micString
Extern.Declare micLong,"PostMessage","user32.dll","PostMessageA", _
micLong,micLong,micLong,micRef+micLong
Extern.Declare micLong,"SetActiveWindow","user32.dll","SetActiveWindow", _
micLong
If hwndWindow Then
'find the handle to the button inside the window
hwndButton = Extern.FindWindowEx(hwndWindow,0,vbNullString,sWindowButton)
If hwndButton Then
'Activate the window
Extern.SetActiveWindow hwndWindow
'Post the BN_CLICK message twice. We are doing it twice
'as sometimes the first message is missed
Extern.PostMessage hwndButton,BN_CLICK, 0, 0
Extern.PostMessage hwndButton,BN_CLICK, 0, 0
AutoClickButton = True
End If
End If
End Function
Page 15 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note We won't explain how WScript works as that is beyond the scope of this book. Refer to a VBScript reference for
more details about the Wscript object.
When we run the above code the message box get closed automatically. The script we created is only good for a single
use as it quits if it's successful once. In case there are more than one message box we must make multiple calls using the
following code:
We can also utilize the same concept to work on the security dialogs that pop up when we use outlook to send emails.
Page 16 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QTP provides a COM interface which allows automating QTP itself. This can be used to write code that performs tasks like
launch QTP, configure QTP, run a script etc. QTP provides a "QuickTest Automation Reference" that explains all objects,
properties and methods supported by the QTP AOM.
Problem 18-1: How can we use AOM to run a QTP test case?
'Launch QTP
qtpApp.Launch
'Open a test
qtpApp.Open "C:\Tests\Sample Test", True
Note We will use the qtpApp object in the remainder of this chapter.
Problem 18-2: How can we use AOM to change the starting and ending iterations for a test case?
qtpApp.Test.Run
Just as parameters can be passed to Actions, we can also pass arguments to a test case. We specify test arguments using
the Test → Settings… → Parameters (Tab) as shown in the Figure 18-1:
Page 2 / 4
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We use test arguments by accessing the TestArgs collection. Here is the example using the just defined arguments
'...
'...
Note The input and output arguments are displayed in the test results summary.
Passing Test Arguments
The first method is to specify it in the "Input Parameters" tab when we run the test case as show in the Figure 18-2.
Page 3 / 4
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The second method is to use the QTP AOM and pass the arguments as show in the next example:
Problem 18-3: How can we use AOM to launch QTP on a remote machine?
We can run QTP on any remote machine which we can connect to and on which QTP is installed, as by doing the
following:
'Remote IP
Const remoteMachineIP = "127.2.3.4"
Any operation that we do now using the qtpApp object will be performed on the remote machine.
Note Make sure the checkbox "Allow other mercury products…" is checked in the Tools Options… → Run (Tab) on the
remote machine.
Page 4 / 4
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
The HTML DOM is a platform and language independent Document Object Model for HTML documents. It defines a
standard set of objects in a tree structure of elements which provide a standard way to access and manipulate HTML
documents. All elements, along with their text and attributes, can be accessed and manipulated through the DOM tree.
The QTP Page Test Object's Object property provides access to the HTML DOM:
Sometimes a QTP Test Object fails to provide a property that is needed to solve a particular problem or implement a
solution. Consider the following situations:
n QTP only provides access to radio buttons through its WebRadioGroup Test Object, rather than providing access to
the individual radio button elements
Using the HTML DOM is faster in terms of performance. Consider a web page where 500 text boxes need to be filled with
same data. A QTP script using Descriptive Programming would look like:
The same script using the HTML DOM would look like:
The HTML DOM version will be substantially faster because there is no object recognition overhead needed to find and
interact with each WebEdit object on the page.
Performance will also be improved when extracting values from a large WebTable using the HTML DOM for the same
reason.
Sometimes QTP throws a general exception—for no obvious reason—while working with a web Test Object. Using the
HTML DOM to interact with that object can provide a workaround in these situations.
n When QTP Test Object is doing the job fine and performance is not an issue
n Using the HTML DOM may make it difficult to maintain our script by other test engineers on the team who do not know
the HTML DOM and its elements
HTML Node
Every TAG in the HTML source represents a node in the HTML DOM tree. Once a TAG is opened, all the tags following it
become child nodes of the starting node. Each TAG can have a variety of attributes, some of which are predefined and
Page 2 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
some user-defined.
Here the pre-defined attributes are type, value and name. The myval attribute is user defined for the INPUT tag.
<html>
<head>
<script type="text/JScript">
function ChangeColor()
{
document.body.bgColor="yellow"
}
</script>
</head>
<body onclick="ChangeColor()">Click on this document!</body>
</html>
Figure 19-1 shows the DOM tree structure for the above page
The Document object represents the entire document. It is the top most node in the DOM tree. The Document node doesn't
have any sibling nodes as it's the root node.
It provides various collections for Links, Anchors, Scripts, Images etc., in the document. It also provides various functions
that we can use to access an element using the name of the element
The HTML Element object refers to any particular node in the DOM. Depending on the type of node the element refers to,
it provides access to methods and properties related to that type of element. Every element object supports these
properties - outerText, outerHtml, innerText, innerHtml, tagName etc.
The HTML Element Collection object is a collection of one or more elements. Consider the following HTML code:
We can access the above DOM objects using the following code:
Page 3 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
For i = 0 to txt_Boxes.Length - 1
txt_Boxes.item(i).value = "Tarun"
'The default property is item so it can skipped
txt_Boxes(i).value = "Tarun"
Next
For i = 0 to txt_Boxes.Length - 1
txt_Boxes.item(i).value = "Tarun"
txt_Boxes(i).value = "Tarun" 'The default property is item so it can skipped
Next
We will be using the Document object directly in the next several explanations, so the following code shows how to get the
Document object using several different techniques:
'Method 1
Set Document = Browser("").Page("").Object
'Method 2
Set Document = Browser("").Object.document
'Method 3
Set Document = Browser("").Page("").Frame("").Object.document
There are several ways to get this element and the following code shows most of them:
Page 4 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The last four lines will throw an exception if there is no element with and INPUT tag or with the name of "txt_Name". To
avoid this we can first check the length of the collection returned by the getElementsByTagName or getElementsByName
methods using the following code:
Text Box
The various ways of changing the value of the text box are:
Combo and list boxes have a list of options that a user can select. Sample HTML source code is:
Page 5 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The different methods of selecting the value in the Combo box or list box are:
Checkbox
Radio Button
Radio buttons offer a user a list of choices, from which only one can be selected. To group all related radio buttons the
elements are given the same name. Sample HTML source code is:
To select a radio button, we need to assign the appropriate value to its object:
HTML Table
Page 6 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n rows provide an access to all the rows present in the table. Rows also provide a 'cells' collection to access a specific
cell present in a row
'To access the 1st row and 1st column cell, use the following code
Set objTable = document.getElementById("myTable")
objTable.rows(0).cells(0).outerText
objTable.cells(0).outerText
'To access the 2nd row and 1st column cell, use the following code
objTable.rows(1).cells(0).outerText
We have now discussed the most common DOM elements and will now look into some other uses for the DOM.
The HTML DOM sourceIndex property is the index value of an object in the DOM tree and can be used to get its
corresponding QTP Test Object. The following code shows various techniques for getting a DOM sourceIndex:
Once we have the sourceIndex and know what type of object we are working with we can then use the following code:
Page 7 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note There is a difference in the names in DOM and QTP. The DOM uses sourceIndex while QTP uses source_Index.
But we can access objects using the either technique by using the code above.
QTP Test Objects do not provide any method for accessing the style sheets in an HTML element. But this can be done
using the currentStyle and Style objects of every element.
Certain pages hide HTML elements using their style sheets. Using the QTP Exist method on these elements always
returns a True value. Consider the following style sheet fragment:
<style>
.visi1 { visibility:"visible" }
.visi2 { visibility:"hidden" }
.disp1 { display:"block" }
.disp2 { display:"none" }
</style>
Notice the class for the element is disp2 and as per the styleSheet the disp2 has display set to 'none'. There are different
ways to check for this situation.
Technique 1
'We neet to know that the class of the potentially hidden object is disp2
If oPg.WebElement("html id:=checkHidden").GetROProperty("class") = "disp2" then
Msgbox "The object is hidden using style disp2"
Else
Msgbox "The object is visible"
End if
Technique 2
Technique 3
This technique directly checks for the sytleSheet properties using the DOM:
Page 8 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note The currentStyle object can be used to validate many things like font name, font size etc… using this object can
also make an automated test case to validate the CSS specifications of Application under Test AUT. Here are the
few examples:
currentStyle.backgroundColor
currentStyle.fontFamily
currentStyle.fontSize
currentStyle.textAlign
Radio buttons in HTML are only associated with value properties and not with the text appearing with them. Consider the
following HTML source code:
Case 1
So, the QTP code to select a radio button in this grouping would be:
Now if we want to select a radio button using its associated text, e.g. "Home Address" or "Office Address", we can use the
DOM, which provides the getAdjacentText method to obtain text adjacent to an element. In this situation it will be the radio
button element which is used to get the reference text. But this might not always be the case. Consider the following HTML
code:
Case 2
<TABLE>
<TR>
<TD>
<INPUT type=radio name=addressType value="hm">
</TD>
<TD>
Home Address
</TD>
</TR>
<TR>
<TD>
<INPUT type=radio name=addressType value="ofc">
</TD>
<TD>
Office Address
</TD>
Page 9 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
</TR>
</TABLE>
In the above HTML, the Home Address text is not next to the radio element but is inside a TD element. In this situation, we
need a path to the reference object from the radio button, which would be Parent node (with TD tag) → Next node (with TD
tag). Now we need a function to get a reference object for a given object and path. The following function can be used to
do that:
Page 10 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Exit Function
Else
If sTag<> "" Then
'If there was tag sepcified then get the first child with
'the given tag
If GetDOMObjectByPath.getElementsByTagName(sTag).Length <> 0 Then
Set GetDOMObjectByPath = GetDOMObjectByPath.getElementsByTagNam
e(sTag).Item(0)
Else
'No such tag present
Set GetDOMObjectByPath = Nothing
Exit Function
End If
Else
'No tag specified retrun the first child node
Set GetDOMObjectByPath = GetDOMObjectByPath.childNodes.Item(0)
End If
End If
End Select
End If
Next
End Function
Once we have the reference object we need to the location of the Text. It can be the outerText/innerText of the object or
text on the left or right of the tag. The getAdjacentText takes a string parameter with 4 possible values "afterEnd",
"afterBegin", "beforeBegin" and "beforeEnd". To select the radio button we can use the below function
'Pattern to be matched
RegEx.Pattern = Text
'Ignore the case
RegEx.IgnoreCase = True
Page 11 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
oRadio.checked = 1
Page 12 / 12
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Web Tables
Consider the following web table HTML syntax shown below in Table 20-1:
<TABLE border="1">
<TR>
<TD>COLUMN 1</TD>
<TD>COLUMN 2</TD>
<TD>COLUMN 3</TD>
</TR>
<TR>
<TD>100</TD>
<TD>200</TD>
<TD>300</TD>
</TR>
<TR>
<TD>400</TD>
<TD>500</TD>
<TD>600</TD>
</TR>
</TABLE>
Each TR tag represents a row and each TD tag represents an individual cell within its parent row. QTP identifies this
syntax and structure as a WebTable object and provides several methods to work with this type of table, the most
important of which are summarized below:
n ChildItem – returns the type of test object residing in a selected cell. For example this function allows us to find and
then get access to a WebTable nested within another WebTable
n ChildItemCount - returns the number of specified test objects, of a specified object type, present in the selected cell.
For example, it returns the number of WebEdit objects located in a cell
Next we use these functions to evaluate the contents of the above WebTable:
Page 2 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
MsgBox objTbl.ColumnCount(1)
'Displays 200, the data value in the 2nd column in the 2nd row
MsgBox objTbl.GetCellData (2,2)
The biggest problem faced by QTP automation engineers is to gain a reference to a specific table. Many pages contain
web tables which are dynamically generated, so the properties used to identify the WebTable should be chosen in such a
way that the table can be consistently identified for one test run to the next one. This section discusses different methods
for identifying and accessing web tables reliably.
Using Index
This method can be used when we know the web page is static in nature, or that the table's position, relative to other
WebTable's on the page, is static. QTP can be used to access a table using an Index when other properties like name or
html id are not available. The Index property should never be used when a web page is dynamic in nature. Below is an
example of using the Index property to access a page's third web table:
The most effective method for accessing a WebTable is to use its name or HTML ID. Unfortunately developers rarely name
tables, but doing so really eases the job of an automation engineer and makes it possible to write much more robust
scripts.
Using innerText/outerText
This method can be used when we know a table's row heading text will be constant:
Referring to Table 20-2, notice that the heading row will always have the words "Attribute", "Value" and "Description".
Therefore we can use the regular expression, "Attribute.*Value.*Description.*", to search for and then access the web table
based on its outerText property, which is the text displayed for a DOM object on the HTML page.
' Access a table object using its innerText with a regular expression
Set objTbl = Browser("..").Page("..").WebTable("innerText:=
Attribute.*Value.*Description.*")
Page 3 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Bgcolor rgb(x,x,x) Specifies the background color of the table. Deprecated. Use styles instead.
#xxxxxx
Colorname
But this approach might not be successful at all times, for the reasons described in the next few examples:
Case 1
<TABLE><TR>
<TABLE><TR>
<TABLE>
<TR>
<TD>Attribute</TD>
<TD>Value</TD>
<TD>Description</TD>
</TR>
<TR>
<TD>align</TD>
<TD>left</TD>
<TD>Alignment of the element</TD>
</TR>
</TABLE>
</TR></TABLE>
</TR></TABLE>
In this case the table we need to access is nested inside another table. So if we use the following code:
It won't work, as there are three Table tags which have the same innerText property. So we have to use the index property
to get a desired match. The index would be 2 in our case (which is the 3nd table). But in case we have more tables then
we would need to handle this situation at run-time. The code below shows how to do this:
Case 2
This case is bit more challenging than Case 1. Consider the next table:
<TABLE><TR>
<TABLE><TR>
<TD>Attribute</TD>
<TD>Value</TD>
<TD>Description</TD>
Page 4 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
</TR></TABLE>
<TABLE><TR>
<TD>align</TD>
<TD>left</TD>
<TD>Alignment of the element</TD>
</TR></TABLE>
</TR></TABLE>
The fixed header row is just above the table containing the data. We can locate the header table using the techniques
used in Case 1 but getting the next table is a bit tricky. We need to get the index of the table relative to the entire page. For
example, if the header table we are looking for is recognized as WebTable("Index:=19") then the table containing the data
will be WebTable("Index:=20"). In this situation we need to use the DOM to get all the TABLE elements and then compare
the sourceIndex with our header table to get its index. The code below shows how we can do this:
i = 0
'Loop through each of the tables
Exit Function
End If
The code we will use to work on the case #2 table is given below:
Page 5 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Using OR
This method is not always perfect but can be used in situations where it's difficult to apply the methods discussed in the
previous section.
To add a WebTable to the Object Repository (OR), open the OR and click on Add Objects and then click in one of the cells
in the target WebTable. After clicking in the web table's cell we see an object hierarchy window similar to the one shown in
the Figure 20-1
We should now be able to add the last WebTable, that appears in the hierarchy, to the OR. In the OR we will see the
properties QTP used to recognize this new WebTable object, similar to that shown in the Figure 20-2
Page 6 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Notice that QTP used the Index property, which might not be reliable on a page composed of dynamic content. But we can
change this in the OR by clicking on the "Add/Remove…" button and selecting the "outerText" property, or any other
unique and appropriate property as shown in the Figure 20-3
The outerText property has the value for the whole WebTable (including the data as well), so we need to use a regular
expression. We do this by clicking on the "configure value options" button for the outerText property and then changing the
value to an appropriate regular expression. Lastly select the "RegularExpression" checkbox as shown in the Figure 20-4
Page 7 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Now the only thing left to do is to configure the Index value. Change the index value to 0 and execute the code below in
QTP to:
If the displayed row count is incorrect then increment the index value by 1 and execute the code again, until the correct row
count is displayed. Once the index calibration is completed we can use the table reference in our scripts.
Note We should run off Smart Identification for this WebTable, as it may lead to incorrect web table selection at runtime.
This method is useful when we have a known object which resides inside the target table. This technique uses the DOM to
reference the object's parent table tag. Consider the code below:
'Return the object found, else return Nothing if a tag is not found
Set GetParentOfElement = oParent
End Function
In the next example we access a table by first referencing a known Image object inside the target table:
Page 8 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The above technique can also be used to locate the exact position of an object inside the table:
'Get the row and column index from the dom objects
'Add 1 to both of them as DOM indexes as 0 based
'while QTP Web Table indexes are 1 based.
Row = Row.rowIndex + 1
Col = Col.cellIndex + 1
End Function
Note The above method returns the DOM table object and not its QTP test object.
Usage:
Page 9 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
srcIndex = oDOMTable.sourceIndex
Set oWebTable = Browser("..").Page("..").WebTable("source_Index:=" & srcIndex)
The above method is quite useful in cases where there is an array of controls (like checkboxes) which might be present
inside a WebTable. When we use the ChildObjects function on a Page object it does not provide the elements present
inside a WebTable. But we can use the DOM to get the element collection and then get the WebTable. Consider the table
show in the Figure 20-5:
Let's assume that the checkbox name is "product". As the above figure indicates, these products can exist in different
tables. Here is an example on how to handle this situation:
iCount = oChkProd.length - 1
'Get the table, row and col where the checkbox exist
Set oTable = GetTableFromElement (oChkProd.Item (i) ,Row, Col)
There are no built-in functions provided by the QTP WebTable object to click a cell but there are several ways, as
described below, to achieve this needed action.
Method 1
Page 10 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Method 2
We can use the QTP click method by getting the WebElement object for a table cell and then click it:
Row = 1
Col = 1
Method 3
This method uses the concept of object identification hierarchy. Each Row is a child object of a Table and each cell is a
child of its table row. So to click (1, 1) we can use the following code:
Row = 1
Col = 1
'Get the Cell WebElement of the object from the row element
Set oCell = oRow.WebElement("html tag:=TD","index:=" & (Col -1))
Method 4
This method can be used when we want to click an object located inside a table cell:
Row = 1
Col = 1
If iEditCount = 0 Then
MsgBox "No WebEdit present in 1, 1"
Else
'Get the 1st WebEdit present in 1, 1
Page 11 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Some pages use asynchronous data loading, where all the objects on the pages are loaded and the data is then populated
in chunks. In this situation the page is loading data asynchronously, so using ".Exist" or ".Sync" or "WaitProperty" on one of
the objects of the web page can't be used to determine when data loading is complete.
In the next example, we have an object reference to a WebTable being updated with data asynchronously. The trick here
is to evaluate the RowCount of the WebTable after a specified interval—when the count stabilizes data updating is
presumed to be complete. Consider the code below:
oldRowCount = 0
The above mentioned code gets and evaluates the web table's row count every 3 seconds. Data loading is presumed to be
complete when the row count is the same for two iterations of the loop.
The next function reads the contents of a WebTable and exports that data to a DataTable:
Page 12 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Next
Next
End Function
Usage:
QTP 8.x does not provide any Find method to locate a text string in a table. But we can extend these by creating new
methods. There are various parts were the functionality can be extended and we would be discussing them one by one. I
would be using the functions we created earlier in this chapter
The GetTableFromElement we created earlier returns the DOM Table object, so let's create another function which will
return mapping QTP WebTable test object instead of DOM table object.
Each cell in a Table is a TD tag element. Use the following code in situations where we need to find a cell by using its text
value:
Page 13 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We can determine if the table we found is the original table or a child of that table:
In case we don't find a match using the above method, we can loop through the entire table and see if a matching row can
be located. In case there are multiple matching rows then we can use a matchIndex:
SearchText = Trim(LCase(SearchText))
If Row = 0 Then
'We need to search in all the rows
startRowSearch = 1
endRowSearch = iRowCount
ElseIf Row < 0 Then
'We need to search just in specified row only
startRowSearch = Abs(Row)
endRowSearch = Abs(Row)
Else
'A positive row # indicates to search starting from
'specified row till the end
startRowSearch = Row
endRowSearch = iRowCount
End If
If Col = 0 Then
'We need to search in all the rows
startColSearch = 1
endColSearch = iCellCount
ElseIf Col < 0 Then
'We need to search just in specified column only
startColSearch = Abs(Col)
endColSearch = Abs(Col)
Else
Page 14 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
endColSearch = iCellCount
End If
FindTextBySearch = True
Exit Function
Else
'Increase the current matching index by 1
curIndex = curIndex + 1
End If
End If
Next
Next
Examples:
Col = -2
Call FindTextBySearch(objTable, SearchText, 0, Row, Col)
iMatch = 0
'Find all the matching text in a column 2 of a table
While FindTextBySearch(objTable, SearchText, 0, Row, -2)
MsgBox "Found in Row - " & Row
Page 15 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
iMatch = iMatch + 1
'Search from the next row
Row = Row + 1
Wend
Page 16 / 16
Reprinted for OET7P/891298, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
XML is a markup language for documents containing structured information. XML is used to implement many solutions,
such as defining program settings, providing input to or receiving output from a system using a well known protocol. QTP
provides a built-in utility object which allows parsing and manipulating files containing XML. While QTP has a good set of
functions to manipulate XML, those function are not documented in the QTP user manual—but online Help provides
adequate information to use them effectively. The remainder of this chapter is intended to provide the missing overview, as
well as to explore some of the more useful QTP functions for working with XML.
Sample XML
<Environment>
<Variable>
<name>601A4</name>
<value type="savings" bank="abc">602126609042</value>
</Variable>
<Variable>
<name>631A5</name>
<value type="checking" bank="def">602126609043</value>
</Variable>
</Environment>
The first node in an XML file is called the root node. A valid XML file can have only one root node. In our example, the
"<Environment>" node is the root node. Note that this, and all other fully formed nodes, are terminated by matching the
"</Environment>" tag.
Child Nodes
Child nodes are the children of an enclosing parent node. In our example the "<Variable>" node is a child node of the
"<Environment>" parent node; while the "<name>" and "<value>" nodes are children of the "<Variable>" node. This
parent/child hierarchy is what gives structure to XML syntax/files.
Node Values
Node value is the value assigned to a given node. A node may only have a value assignment if it does not have any child
nodes. Here the first "<name>" node has a value assignment of "601A4" and <value> node has a value assignment of
"602126609042".
Attributes
A node can have attributes. If we look at the first "<value>" node which is <value type="savings" bank="abc"> here "type"
and "bank" are attributes and "savings" and "abc" are their attribute values respectively.
QTP provides a rich set of utility XML objects, the most important of which are described next.
n XMLUtil - This is the object which is used to create or read an XML file. Like HTML, XML also has a document object
model (DOM). But this object provides a much smaller set functions as compared to the HTML DOM. The XML DOM is
beyond the scope of this chapter
n XMLAttribute - Provides access to the name and value of attributes of a specified node
n XMLItemColl - Provides a collection of XML Items. XML Items are used for CDATASection and comments in the XML
Page 2 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n XMLData - Represent an XML Block. XML Data contains the complete XML file loaded using XMLUtil or from WebXML
test object
n XMLElement - Represent an XML Element. An XML element can have attributes, a value, and/or one or more children,
all of XMLElement type
Rather than attempt to define each and every function supported by each of these objects, we use the more common ones
in the examples in the remainder of this chapter. For details on all the methods and properties supported by these objects
refer to the QTP Help.
Problem 21-1: How can we copy an XML file and save it to another XML file?
'Method 1:
'Create an empty XMLData object
Set xmlDocument = XMLUtil.CreateXML
'Method 2
'Create an XMLData object with file data in a single step
Set xmlDocument = XMLUtil.CreateXMLfromFile ("C:\source.xml")
xmlDocument.SaveFile "c:\destination.xml"
Set xmlDocument = Nothing
Problem 21-2: How can we get an entire XML file into a string and then save it to another XML file using that
string?
Problem 21-3: How can we create the following XML code at run-time in QTP, and then save it to an XML file?
<Environment>
<Variable>
<Name>FirstName</Name>
<Value>Tarun</Value>
</Variable>
<Variable>
<Name>LastName</Name>
<Value>Lalwani</Value>
</Variable>
</Environment>
The code given below will create the specified XML at run-time:
' Create an empty XMLData object
Set xmlDoc=XMLUtil.CreateXML
'Create a document with Environment as the root node
Page 3 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
xmlDoc.CreateDocument "Environment"
'Get the root nod element.
'The data type returned would be of type XMLElement
Set xmlRoot = xmlDoc.GetRootElement()
Problem 21-4: How can we load environment variables from multiple XML files?
QTP's Environment.LoadFromFile has a disadvantage, that is, it does not allow loading multiple environment files. But we
can overcome this shortcoming by creating our own function to read and create environment files.
'Function to add environment files at run-time
'Overwrite flag allows overwriting variables which
'already exist in the environment
Public Function AddENVFromFile(ByVal FileName, ByVal Overwrite)
On error resume next
Dim xmlDoc, xmlRoot, xmlElement
Dim sName, sValue
'Load the xml file
Set xmlDoc = XMLUtil.CreateXMLFromFile (FileName)
Set xmlRoot = xmlDoc.GetRootElement()
'Get all the variables node
Set xmlValues = xmlRoot.ChildElementsByPath("Variable")
'Loop through all variable nodes
For i= 1 to xmlValues.Count
Set xmlElement = xmlValues.Item(i)
sName = xmlElement.ChildElementsByPath("Name").item(1).value
sValue = xmlElement.ChildElementsByPath("Value").item(1).value
'Check if the environment already exist
If IsEnvExist(sName) Then
If Overwrite Then Environment(sName) = sValue
Else
Environment(sName) = sValue
End If
Next
End Function
Page 4 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
IsEnvExist = False
End If
On error goto 0
End Function
Usage:
'Add all the environment varaiables and allow overwrite
AddENVFromFile "C:\Env_All.xml", True
Now this will add a variable in both the XMLs and will overwrite any existing ones
Note These XMLs should not contain any environment variable which was loaded from any XML using LoadFromFile or
any Environment variable associated with the test as QTP loads them in the read only mode.
The above AddENVFromFile function is very useful when we want to create test cases for different environments. Consider
the folder structure shown below:
Each folder can have its own Config.xml and the Common folder will have variables which are shared by all the scripts.
Dev and Test can override shared variables that are unique to the Dev or Test environments and the script can select an
environment as follows:
Now consider the next QTP code that can be used to modify the above XML definitions:
'Create the XML document object
Page 5 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
msgbox xmlDoc.toString()
The ChildElementsByPath method allows using relative paths for an XML node. We use the same concept in the above
code and enumerate all the variable nodes. The path that is passed to ChildElementsByPath methods is XPath. More
information on XPath can be found at http://www.w3schools.com/xpath/. To validate a unique name in the XML we use
"\\<NodeName>" as the XPath and validate its value. It is very helpful to have knowledge of XPath when creating XML
validation functions
Like the previous problem we use the ChildElementsByPath method to get an array of nodes. We use the same concept
and export values from each child of the nodes in the array to the DataTable.
'Function to export XML to Data Table
Public Function ExportXML2Table(ByVal oDataTable, ByVal envFile, ByVal keyNode)
If xmlCols.Count<> 0 Then
On error resume next
Set xmlCol = xmlCols.item(1)
iCount = xmlCol.ChildElements().Count
'First loop through all the elements and creat the data table parameters
For i = 1 to iCount
oDataTable.AddParameter xmlCol.ChildElements.item(i).ElementName(), ""
Next
Page 6 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Usage:
'Export the Environment varaibles from environment XML to Data table
ExportXML2Table DataTable.GlobalSheet, "C:\ENV.xml", "/Environment/Variable"
Note We can also use XMLUtil in an external VBScript by using the following QTP COM object:
Set XMLUtil = CreateObject("Mercury.XMLUtil")
Problem 21-7: How can we extract XML from a URL or Web browser?
To extract XML from a URL, or one displayed in the web browser, we must get the document object of that XML. Here is an
example of using the QTP WebXML test object to do this:
'URL of the XML
sURL = "http://mywebsite/set.xml"
Comparing XML
Problem 21-8: How can we compare two XML documents for equality?
The QTP XMLData object provides a method to compare two XML documents:
'Load both XMLs and
Set xmlDoc1 = XMLUtil.CreateXMLFromFile ("C:\File1.xml")
Set xmlDoc2 = XMLUtil.CreateXMLFromFile ("C:\File2.xml")
'Use the compare method of the XML to check if they are equivalent
isEqual = xmlDoc1.Compare (xmlDoc2, xmlResults)
'If return value of compare method is 1 that mean the files are equal
If isEqual = 1 Then
Msgbox "The documents match"
Else
Msgbox "The documents don't match"
End if
Problem 21-9: How can we compare two xml file with different ordering of nodes?
Page 7 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
File1.xml
<Environment>
<Variable>
<Name>FirstName</Name>
<Value>Tarun</Value>
</Variable>
</Environment>
File2.xml
<Environment>
<Variable>
<Value>Tarun</Value>
<Name>FirstName</Name>
</Variable>
</Environment>
These two XML files won't compare for equality because of their node ordering differences. The same issue exists for XML
checkpoints created through QTP. A workaround is to sort the XML file using XSL (XML StyleSheet):
To use this workaround we need to use Microsoft XML Version 2.0 lib "MSXML.DOMDocument" document object and
apply the above XSL to our XML
'This should always work. Bu there are different version of XML Lib
'that we can use. Chnage the Lib name as per the library available on
'the system
sXMLLib = "MSXML.DOMDocument"
'Load the XML document
Set xmlDoc = CreateObject(sXMLLib)
xmlDoc.async = False
xslDoc.async = False
'Load the XSL file
xslDoc.load inputXSL
Page 8 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Page 9 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QTP does not provide any built-in support for databases. But since it uses VBScript as its scripting language, we can use
that tool's support (ADODB) to interact with databases. Explaining ADODB is beyond the scope of this book, but this
chapter provides examples that give a general idea on how to use ADODB to perform common database operations.
n ADODB.Command – Used to execute a DB command, for example an SQL query or to run a stored procedure
Connecting to a Database
A connection string is one of the most important properties used by ADODB to connect to a database. Different databases
often require different types of connection strings. There are two methods to construct a connection string. The first
method is to get the string from the database documentation which may not always be readily available. The second
method is to use a connection string builder Wizard.
Connection Wizard
Use the following steps to create an empty Microsoft Data Access service's Data Link file and then use its Wizard to create
a connections string as described in this section.
Create a blank file with name "mycon.udl" and double click on that file to open the Data Link Properties dialog. Then select
the Provider tab as shown here:
Page 2 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
After selecting a provider, click the Next>> button and move to the Connection Tab. After filling in the details on
Connection tab, click on the Test Connection button to ensure that the connection is working as shown in the Figure 22-2
We can also configure more options in the Advanced tab and All tab like Read only mode or write only or access database
user name or password etc…
Now when the myCon.udl file is opened in Notepad we will see the connection string just used to connect to the database
Page 3 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
as shown next:
We can now copy the above connection string into our QTP code to connect to the DB.
Note In all the upcoming examples we will be assuming that we already have an adoCon object present which is
connected to a DB instance.
Method 1
This method uses the Recordset object to execute the query and extract the results:
'Access the values of the fields. We can either use the name
'of the column in the query or use the index
Msgbox "Val1: " & adoRecordSet.Fields("Val1").value
Msgbox "Val2: " & adoRecordSet.Fields("Val2").value
Page 4 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Method 2
'Variable declaration
Dim adoRecordSet, adoCommand
'Run the query through the command object and get the recordset
Set adoRecordSet = adoCommand.Execute
Method 3
This method uses the connection object directly to get the Recordset.
'Variable declaration
Dim adoRecordSet
strSQL = "Select Val1, Val2 from Table2"
Set adoRecordSet = adoCon.Execute (strSQL)
Note adoRecordset.Close should not be used in case of UPDATE or DELETE queries as when these queries are
execute the Recordset is not open and closing a closed Recordset will throw an error.
Problem 22-2: How can we determine the number of rows altered by an update or a delete query?
Page 5 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This is useful in situations where we need to determine if the last query altered any rows. For example, if we ran a
syntactically correct update query which didn't alter any rows for any reason:
'Delete query
strSQL = "DELETE from Table1 where Val1 in (2,3,4)"
dim rowsAffected
If rowsAffected = 0 then
Msgbox "No rows were deleted"
Else
Msgbox rowsAffected & " row(s) were deleted"
End if
We can export the Fields collection of a Recordset to a QTP data table. One issue that we might want to avoid is the
spaces in the column name of the data table. To do that we should replace each space character in the column name from
a query with an "_" character:
Dim fld
'Loop through each field and get the name
'to create the data table parameters
For each fld in adoRecordSet.Fields
outSheet.AddParameter Replace(fld.name," ","_")
Next
Note The query should not result in any field which cannot be handled normally like BLOB/CLOB etc…
Stored procedures can be executed using the Command object. Care must be taken to properly define the required input
and output parameters of the stored procedure. Consider the following stored procedure:
Page 6 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Needed constants
Const adVarChar = 200
Const adInteger = 3
Const adParamInput = 1
Const adParamInputOutput = 3
Const adParamOutput = 2
Const adParamReturnValue = 4
s_UserID = 37362
s_Password = "Test"
s_ProjID = "Project 1"
.CommandTimeout = 30
.CommandType = 4 'adCmdStoredProc
Page 7 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
http://www.w3schools.com/ado/
http://msdn.microsoft.com/library/default.asp?url=/library/ en-us/ado270/htm/mdmscsection1_ado.asp
Page 8 / 8
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
The next diagram shows the part of the Excel Object model we will use in this chapter:
n Application – The main object which references the Excel application itself
n Workbooks – This object references a collection of currently opened Excel workbooks (i.e. spreadsheet files)
Problem 23-2: How can we create a new excel sheet and then save it?
Page 2 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Dim xlApp
Dim xlWorkbook
Dim xlWorkSheet
'Add a new workbook. The add method returns an object referencing the
'just created workbook, and can be used to interact with the workbook.
Set xlWorkbook = xlApp.Workbooks.Add
'Add a new worksheet. This add method returns an object references the
'just created added worksheet.
Set xlWorkSheet = xlWorkbook.WorkSheets.Add
'Save the new workbook. The SaveAs method is used because thw workbook has
'never been saved. In situations where we open and the re-save an
'existing workbook, the Save method should be used.
xlWorkBook.SaveAs "C:\NewBook.xls"
Note We won't use complete code in the remaining examples for the sake of brevity. Most notably we will assume Excel
invocation and termination, creation of basic objects, etc.
Problem 23-3: How can we determine if an Excel file exists, and if not, how to create one?
If bFileExist then
'If the file exist open it
Set xlWorkBook = xlApp.Workbooks.Open (sSourceFile)
Else
'If the file does not exist create a new one
Set xlWorkBook = xlApp.Workbooks.Add
End If
'...
'...
'Check if opened a new file
If bFileExist Then
'Use the Save method in case
xlWorkBook.Save
Else
'Use the SaveAs method as the file has never been saved
xlWorkBook.SaveAs sSourceFile
End if
Page 3 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Problem 23-4: How can we access all non-blank row values in a specific column?
There are two methods to do this. The first method is to loop through each cell in a selected column and stop when a blank
value is encountered. The second method is to get the count of all non-blank values in the selected column.
Method 1:
'counter for row
I = 1
Method 2:
'Use Evaluate function to determne how many rows have non-blank values
iRowCount = xlWorkSheet.Evaluate ("COUNTA(A:A)")
'In the above statement, A:A specifies all rows in column A, while
'1:1 would mean 1st row and A1:A100 would mean 1st to 100th row of column A.
For I = 1 to iRowCount
Msgbox xlWorkSheet.Cells (I, 1)
Next
Problem 23-5: How can we search for a text string and then update another cell's value in that row?
For example, let's say we want to update the Age for Tarun. Here is how we could do that:
'Find the text "Tarun" in column A
objFind = xlWorkSheet.Range ("A:A").Find ("Tarun")
Page 4 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Problem 23-6: How can we use an Excel sheet as a QTP output Data Table?
Let's assume that we have opened the above file and now want to populate the data for various rows. But we are not sure
about the ordering of the columns i.e. Name could be defined as column 1, column 2 or any other column. What we need to
do first is to evaluate the first row's column titles and then create a Dictionary entry for each column title with its related
column number.
'variable to store column dictionary index
Dim oCols
'...
'...
Page 5 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
xlsApp.Quit
In Excel we can record macros which generate Visual Basic for Application ( VBA ) code.
Macro Recording
Excel provides the ability to record macros which are used to automate various actions in the application. This capability,
built into Excel, can be used to determine what code needs to be written in QTP to implement a desired operation. This
section describes how to perform a macro recording and then convert those steps in QTP VBScript code.
After opening Excel with a new blank worksheet, go to Tools Macro Record new Macro… and press Ok to start recording
a macro.
Enter some values for Name, Age and Sex in the second row and then select all the cells and add borders also. Select the
header row and give it some background color.
Press ALT + F11 to open the VBA editor. Browse to the Module file that contains the recorded macro.
'Recorded macro
Sub Macro1()
'
' Macro1 Macro
' Macro recorded 7/1/2007 by Tarun_Lalwani
'
'
ActiveCell.FormulaR1C1 = "Tarun"
Range("B2").Select
ActiveCell.FormulaR1C1 = "16"
Range("C2").Select
ActiveCell.FormulaR1C1 = "Male"
Range("D2").Select
ActiveCell.FormulaR1C1 = "N/A"
Range("A2:D2").Select
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
Page 6 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Interiorz
.ColorIndex = 35
.Pattern = xlSolid
End With
End Sub
To accomplish the same thing using VBScript in QTP we need to filter out things that we don't want to do, as well as
convert VBA to the VBScript.
Since VBA code always executes within Excel we don't need to specify a WorkSheet object. But the equivalent QTP code
using VBScript needs to explicitly reference a worksheet object, as in:
Let's convert the following VBA code so that it will work in QTP with VBScript:
With Selection.Interior
.ColorIndex = 35
.Pattern = xlSolid
End With
The above code uses a constant, xlSolid, defined in Excel but not available in QTP. Therefore we need to define it
ourselves. But in order to do that, we need to determine the constant's integer value. There are two ways to achieve this.
Method 1
Page 7 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
In the VBA Editor view press CTRL + G to launch the immediate window pane.
Type"?xlSolid" inside the window and press Enter to display the constant's value:
The window will display the value of the constant which we can now use in a QTP script:
'Constant declaration
Const xlSolid = 1
Method 2
In the VBA editor view, press F2 key to launch the object browser. Type xlSolid to search for the constant as shown here:
Page 8 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We can avoid the Select and With Selection objects in the last VBA code fragment by directly referring to the object we
want to set in the VBScript code. So the VBA code can be converted as below:
'Constant declaration
Const xlSolid = 1
xlWorkSheet.Range("A2:D2").Interior.ColorIndex = 35
xlWorkSheet.Range("A2:D2").Interior.Pattern = xlSolid
The VBA to VBScript conversions gets easier when we more fully understand the objects that we need to work with and
where those objects resided in the Excel object model.
Note We can use the Excel object browser to look at the various methods that are supported by the different types of
object.
If we were to observe the macro recorded VBA code for saving a new file to a specific location, it would appear something
like this:
'Save workbook as
ActiveWorkbook.SaveAs Filename:="C:\SheetExample.xls", FileFormat:=xlNormal _
, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False, _
CreateBackup:=False
Notice that VBA supports passing parameters without regard to the position order using "ParamName:=ParamValue"
syntax. But VBScripts does not support this type of parameter passing. So we need to make sure that all function
parameters are passed in the order specified in the function's definition. Use the Object browser to review a selected
function's definition. For example the SaveAs function definition is:
Page 9 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This VBA statement would be converted to a VBScript statement using the following simplified syntax, since all but the first
parameter can normally use the default values:
But in a case where we want to define a password for the sheet we would use this syntax:
Note We didn't provide a value for the 2nd parameter, so it will use its default value.
Problem 23-8: How can we access an Excel spreadsheet embedded in Internet Explorer?
Internet Explorer and Explore can render many different types of documents. It could be a local folder, shared folder, ftp
folder, web URL, word document etc. What both of these applications mainly do is to render a document object. And the
document object differs based on the type of the URL being referenced.
For a browser displaying a web page, we can use the following statement to access the document object:
'Document object
Set objDoc = Browser("CreationTime:=0").object.document
But when the browser is displaying an embedded document then the above statement will cause QTP to throw a "General
run error" exception. To access the embedded document object we need to use IE's COM interface. The following function
provides an access to IE's COM interface through its window's handle:
'Function to get IE Object from window handle
Function GetIEObjectFromhWnd(ByVal hWnd)
Dim objShell
Dim objShellWindows
'Create a shell application object
Set objShell = CreateObject("Shell.Application")
'Set the object to Nothing in case the code below can't find any IEs
Set GetIEObjectFromhWnd = Nothing
We can now use the function given above to get the COM interface of the IE window which is displaying a spreadsheet:
'Get browser handle
hWnd = Browser("CreationTime:=0").GetROProperty("hwnd")
Page 10 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
But if we don't know what this document object actually contains, then how do we determine its object type? We have to
just add the next statement and then run the code to review its output:
'This will give WorkBook
MsgBox TypeName(objDocument)
Note An embedded Excel sheet needs to be open in a browser, in order to get the above output.
Using the TypeName function we can determine that the document is a workbook object of the Excel application.
Thereafter we can access all workbook properties and methods:
Msgbox objSheet1.Cells(1,1)
The above code is now able to operate against the embedded spreadsheet. The same technique can be used to evaluate
and manipulate other embedded documents such as Microsoft Word documents, Microsoft PowerPoint presentations and
many more.
Performance Enhancements
Each QTP call to an Excel object has its cost because it is an out-of-process communication. Consider the QTP code
below:
The above code took 27 seconds on the author's PC. The performance problem with this code is that we make 7000 calls,
each accessing a single spreadsheet cell. So if we can reduce the number of calls we can improve runtime performance.
Consider the next improvement:
Dim iArray
ReDim iArray(6)
For i = 1 To 1000
'create all column values for the next row
For j = 1 To 7
iArray(j-1) = i * j
Next
'Write all the cells in the next row with new values
xlWorksheet.Range("A" & i & ":G" & i) = iArray
Next
Page 11 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The above code executed in 4 seconds on the same PC. This improved function now updates the sheet row by row, which
saves substantial time over writing each cell individually.
Finally a further performance improvement can be achieved by writing the spreadsheet a column at a time, which reduces
the QTP to Excel object calls to 7. The only difference would be that we need to transpose the array before assigning it to
the range, using the following function:
Dim iArray
ReDim iArray(1000)
This 2nd improvement took only 0.21 seconds to execute. Still not fast enough? Well we can make one final performance
improvement by using a 2 dimensional array and assigning it to the Excel spreadsheet in a single access, as in:
This third and final improvement took 0.04 seconds to execute, which is approximately 590 times faster than the cell by cell
code we initially started with.
Note We should always try to minimize calls to any external COM component as it involves data marshalling from
Page 12 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Page 13 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Figure 24-1 shows objects from the Outlook object model that will be used in this chapter:
The Application object is the top level object and is used to create an instance of Outlook. The most commonly used child
objects of the Application object are:
n Folders – Is a collection of folders under the namespace (Mail folders, Public Folders, PST)
The first step required to work with the Outlook application is to create its COM object using the following code:
Once the Application object is created we need to get its Namespace object. The only namespace that Outlook supports is
MAPI:
Page 2 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note We will use the just created olApp and olMAPI objects in the remainder of this chapter without any further
comment.
We do not need to log on when Outlook is already launched or when Outlook logs on to the default profile automatically
The Namespace object provides the Folders collection for the top level folder. We can enumerate all the folders using the
following code:
We can also access these folder using their name or their index. So to access the "Public Folders" we can also use:
All these statements return an object of type MAPIFolder. MAPIFolder objects provide a Folders collection of their sub-
folders. So we can create a function to get a folder from its path using the following function:
Page 3 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
If Err.Number Then
Set CurrentFolder = Nothing
Exit For
End If
End Select
End If
Next
'Usage
Set oFolder = GetSubFolderByPath(olMAPI, "\\Mailbox - Tarun Lalwani\Inbox")
'Prints "Inbox"
Print oFolder.Name
We can then use the Namespace object's PickFolder method to present a dialog and get a folder selection from a user with
the following code:
'If the user presses the Cancel button then the function returns Nothing
If oFolder Is Nothing Then
MsgBox "User pressed the Cancel button"
Else
MsgBox "User selected the " & oFolder.FolderPath & " folder"
End If
Page 4 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Const olFolderSentMail = 5
Const olFolderInbox = 6
Const olFolderCalendar = 9
Const olFolderContacts = 10
Const olFolderJournal = 11
Const olFolderNotes = 12
Const olFolderTasks = 13
Const olFolderDrafts = 16
Const olPublicFoldersAllPublicFolders = 18
Const olFolderConflicts = 19
Const olFolderSyncIssues = 20
Const olFolderLocalFailures = 21
Const olFolderServerFailures = 22
Const olFolderJunk = 23
We can access e-mail messages inside a folder using the folder's Items collection as shown in the following code:
Page 5 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
unreadCount = 0
The above code displays the number of unread e-mail messages in the Inbox folder. This code loops through each
message in the folder, so the code will take proportionally more time as the message count increases. But the Items
collection provides a restrict method which can be used to filter emails based on various parameters, as shown in the
following code:
'Restrict the collection to unread emails which have a name in the CC field
Set unreadEmails = allEmails.Restrict("[Unread] = True And [CC] <> ''")
The Restrict method supports OR, AND, NOT operators. But there is no LIKE operator which means we cannot filter based
on regular expression syntax. In such cases the filter should be set to limit the emails collection to a minimum and then loop
through the selected messages to get just those we are looking for. The Unread flag is commonly used to limit the
collection and in case the email is not required again it can then be marked as Read using the following code:
Once we have an e-mail message we can access its various properties. Some of these properties are shown in the Table
24-1
Table 24-1: Email properties
Page 6 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Property Description
Attachments Collection of attachments in the email
Body BodyFormat Text of the email body
Format of the email text (Rich text, HTML and plain text)
CC CC of the email
Conversationlndex Index of the mail in conversation
ConversationTopic Subject of the conversation (Without the Re:, Fw: etc…)
HTMLBody HTML text of the body
ItemProperties Collection of all the properties associated with the email
Parent Get the parent folder in which the email exist
Recipients Collection of all the recipient in the email
SenderEmailAddress Email address of the sender
SenderEmailType Sender's Email address type. eg – SMTP
SenderName Name of the sender
Size Size of the email
Subject Subject of the email address
To Display name of addresses in TO list
UnRead Tells whether email is unread or not
Downloading Attachments
An e-mail message's attachments can be downloaded by accessing its Attachments collection, using the following code:
To send e-mail messages using Outlook we need to first create the message and then fill in all the details associated with
the message and then send it using the following code:
newMail.CC = [email protected]
newMail.BCC = "[email protected]"
Page 7 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
When we attempt to execute the above code to send the e-mail message, a security modal dialog is presented as shown
below. This is a security feature of Outlook. QTP code will be blocked from further execution until either Yes or No is
clicked by a user or another program.
Click Yes is a third party tool available at http://www.contextmagic.com/. This tool automatically clicks yes on outlook
security dialogs.
Method 2
Use a third party library which works with low level MAPI APIs and works around the limitation of Outlook security patch.
One such library is Outlook Redemption available at http://www.dimastr.com/
Method 3
Send the email through the Outlook UI. When we create an email using the code above, it is created in a hidden window.
But Outlook does not raise the security popup when a user clicks on the Send button in its own UI. So we need to display
the email and then use QTP to click on the Send button just as a real user would. So the QTP code will change as follows:
'Create a description
Set oMailWindow = Description.Create
oMailWindow("title").Value = emailCaption
oMailWindow("title").RegularExpression = False
Page 8 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
sTitle = "title:=.*Spelling.*"
'Check if a spelling check window is present
If Window(oMailWindow).Window(sTitle).Exist(2) Then
Window(oMailWindow).Window(sTitle).Close
End If
Method 4
The Outlook security dialog blocks QTP execution, therefore the QTP Recovery Scenario can't be used to dismiss the
dialog. The workaround to such a situation is to use an external VBScript to do the email work and then use QTP code or a
Recovery Scenario to dismiss the security dialog.
Method 5
Use the approach of "Working with Modal Dialog boxes" as discussed in the "Working with APIs" chapter.
Method 6
We can use the CDO or CDONTS library to send the emails. The method is pretty similar to the one used with Outlook
with the only difference being the additional code needed to specify the Configuration:
'Constants declaration
'Send message using the local SMTP service pickup directory.
Const cdoSendUsingPickup = 1
'Send the message using the network (SMTP over the network).
Const cdoSendUsingPort = 2
Page 9 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
.Update
End with
To get email addresses from the messages, we access the Recipients collections. The following function shows how to get
the addresses present in the To and CC collections.
To get the sender's email address in Outlook version 2003 or higher we can use the following code:
But in Outlook versions prior to 2003 there is no such property. But we can use the Outlook Redemption library or CDO to
obtain the address. Each email item in Outlook is assigned a 48 character ID. These IDs can be use to get an email. So the
trick here is to get the ID from the Outlook email object and then get the email in CDO object using the retrieved IDs. We
can get the ID of the email and then get that email in CDO using the following code:
Page 10 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
When getting addresses from an Exchange Server Contacts, the address can be in an extended format.
For example:
network/postoffice/user
/c=US/p=mycompany/o=Finance/ou=Purchasing/s=Furthur/g=Joe
To get the SMTP email address we would need to use CDO again, using the following code:
emailAddress = GetSMTPAddress(oAddressEntry)
Next
The above function uses the AddressEntry type object to get the SMTP addressees.
Note The technique described above will cause few security dialogs to popup.
Outlook Email messages support three different formats: Plain text, RTF and HTML. To click a link inside a message we
need a method to get the link. Outlook can use different editors to display email – HTML, Word etc. Whatever the format of
the email may be, the Outlook object model allows us to get it as HTML content. So we can actually get the email's HTML
content and then write that onto an IE browser. This will display the email as a page inside the browser and then we can
use the normal QTP code to click the link. The following code shows how this is done:
'Launch a browser
SystemUtil.Run "iexplore.exe"
Page 11 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
When remote activation of a QTP script is required we can host code in Outlook and create various commands to perform
this task. Outlook rules support running a VBA script when the conditions of a rule are met.
The first step is to create a function which is called when the conditions of a rule are satisfied. The function should have
the following prototype:
'Function prototype
Public Sub Rule_Function1(Item as Outlook.MailItem)
End Sub
Open outlook and press ALT + F11 to launch the VBA macro editor. Create a new module and add a new function with the
prototype shown in the Figure 24-4
Now go to Tools Rules & Alerts … and Click on the New Rule.,. button. Configure the rule as needed. Check the checkbox
for 'run a script' and select the function Rule_RunQTPScript_ABC as shown in the Figure 24-5
Page 12 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Once the rule is triggered the VA function will be called. But we don't want to block Outlook to by running a QTP script
directly from the VBA function. So the best method is to add the majority of the QTP activation codes in a VBScript file and
then execute the VBScript file asynchronously as shown in the following code:
The above code will run the same script again in case where the multiple emails are received. In cases where QTP might
not be available to execute the request from a new email trigger, code should be added to create a request queue. This
technique provides a very simple mechanism to execute QTP scripts on a remote PC using the email mechanism described
above.
Page 13 / 13
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Figure 25-1 shows a high level picture of few basic objects in word object model
n Documents: A collection of all the Document objects that are currently open in Word
n Document: Represents a document. The Document object is a member of the Documents collection
n Range: Represents a contiguous area in a document. Each Range object is defined by a starting and ending character
position
n Selection: Represents the current selection in a window or pane. A selection represents either a selected (or
highlighted) area in the document, or it represents the insertion point if nothing in the document is selected. There can
be only one Selection object per document window pane, and only one Selection object in the entire application can be
active
Page 2 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Dim oDoc
Problem 25-5: How to get reference toan already existing word document?
Method 1
This method uses GetObject function to get reference to the existing word file
'Get the reference to existing word file using GetObject
Set oWordDoc = GetObject("C:\Test.doc")
Page 3 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Method 2
This method uses the Open method of the Documents collection to open the word document
'Create the word application
Set oWordApp = CreateObject("Word.Application")
Problem 25-6: How to open a word document in the read only mode?
Note In further examples we won't be creating the oWordApp and oWordDoc objects and would consider them to be
available from one of the previous examples.
Problem 25-8: How to insert text into a word document from a pre-defined style?
With oWordSel
'Type some text with style as /Heading 1/
.Style = "Heading 1"
.TypeText "This is Heading 1"
.TypeParagraph
Page 4 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
.TypeParagraph
End With
Problem 25-9: How to insert an image in a word document and scale its size by 50%?
With oWordSel
'Insert the image and get the object reference to the inserted image
Set oImg = .InlineShapes.AddPicture ("C:\DesktopImage.bmp", False, True)
Problem 25-10: How to find and replace some text in a word document?
With oWordSel
.TypeText "Author name for this document is: %AUTHOR_NAME%"
.TypeParagraph
'Need to take the range from whole document since current selection
Const wdReplaceAll = 2
Const wdReplaceNone = 0
Const wdReplaceOne = 1
Page 5 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
One can create a template document with all configurable/updatable values to be written between some special characters
(%% in the above example). The document can be updated by the QTP test by replacing the parameterized values with
the actual values and then the document can saved to a different location using the SaveAs method of the Document
object.
Note It is advisable to either keep such a template document as read only or open the document in a read only format.
With oWordSel
'Add a new table and get the object reference to the newly added
'table. Table size: 5 rows X 3 columns
Set oNewTable = .Tables.Add(.range,5,3)
i = 1
End With
Problem 25-12: How to change the font for the text being written in a word document?
Page 6 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
With oWordSel
'Change the font to verdana (8)
.Font.Name = "Verdana"
.Font.Size = 8
Problem 25-13: How to preserve the text already present in a word document while writing?
All the examples that we discussed before this would overwrite any text that is already present in the document. This
happens because of the following line in our code
'Select the whole word document
oWordDoc.Range.Select
So any type operation on the Selection object will delete all the text that existed in the document. To avoid such a situation
we can move to the end of the document after selecting the range object. This can be done using following lines of code
'Select the whole word document
oWordDoc.Range.Select
With oWordSel
Const wdStory = 6
Const wdMove = 0
Page 7 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Internet explorer can be launched as an application or by using its COM library. Let's see how both of these techniques
can be used.
Method 1
Method 2
When we launch IE using the 2nd method, we can use the IE Window's handle to reference the browser as a QTP Test
object using the following code:
The IE Application COM interface provides many useful methods and properties. We list just a few of the more common
ones in Table 26-1 and Table 26-2
Table 26-1: IE COM Methods
Page 2 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n READYSTATE_INTERACTIVE: The object is interactive, but not all of its data is available.
n READYSTATE_COMPLETE: The object has received all of its data.
Note Table 26-1 and Table 26-2 don't give a complete list of method and properties provided by the IE COM interface.
Page Synchronization
We can use the IE COM object's Busy property to determine if IE is busy loading a page. The following example explains
how we can wait for page to load
'Create an IE Application
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
'Browse to a website
IE.Navigate2 "http://www.mywebsite.com"
Warning This method might not work properly when the page has frames.
Page 3 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We can enumerate all open IE windows using the windows shell application. The shell application provides a collection of
all open explorer windows (Microsoft explorer + Internet explorer). The following function enumerates all open windows and
returns a dictionary collection containing all IE windows:
Now we can use the above function to close all open IE windows
The code given above can work in pure VBScript (without QTP). But in QTP we can also close IE windows with a single
line of statement:
Finding an IE Window
We can also use the enumeration method given above to search for an IE window based on its Window's handle using the
following function.
Exit Function
End If
Page 4 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Next
End Function
Exit Function
End If
Next
End Function
Note In case multiple browsers have been opened with the same URL, the function given above may return any one of
the browser.
When we launch an IE window through QTP, there is no identification of the window returned to us. In situations where
there are already open IE windows we might not be able to determine which window was launched by QTP. We can create
a workaround by opening the browser with a random number URL and then searching the COM interface by using the
GetIECOMByURL function we just created.
Page 5 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
In case we want to use the browser using QTP test object only, we can do that using the code given below
'If using DP we can just use the handle to recognize the browser
sBrowser = "hwnd:=" & oBrowser.hwnd
Browser(sBrowser).Navigate "http://www.mywebsite.com"
The IE COM interface exposes the document object and thereby provides access to the entire web page. The following
example shows how the DOM elements are accessed by using this technique:
'Create an IE application
Set oIE = CreateObject("InternetExplorer.Application")
Note The code given above does not need QTP and can be run purely in VBScript.
<html>
<SCRIPT language="JScript">var PageName2 = {};
PageName2["val1"] = "Tarun1";
PageName2["val2"] = "Tarun2";
</SCRIPT>
<body>
<SCRIPT language="VBScript">
Const PageName = "Tarun Lalwani"
Dim arr(1)
Arr(0) = "Array 1"
Page 6 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
End Sub
</SCRIPT>
</body>
</html>
The web page given above has 2 scripts, one in JScript and one in VBScript. The HTMLWindow object has access to all
these variables and methods declared in these scripts. These variables can be accessed from QTP as shown in the
following code:
'Displays "Tarun1"
Msgbox oPG.object.parentWindow.PageName2.Val1
VBScript provides the InputBox method to obtain input from a user. But it is very limited as we can only get plain text
values. There is no option for the user to select values from a list or to enter a password with hidden characters. As a
workaround to this problem, we can create an HTML web page which has all the input controls which are needed to obtain
the desired user inputs. Consider the next HTML page:
'C:\Files.html
<SCRIPT language="vbscript">
Dim userAction
</SCRIPT>
<P>UserName:
<INPUT type=text name=username value="Enter user name">
<P>Password:
<INPUT type=password name=password>
<P>Environment:
<SELECT type=select name=env>
<OPTION>Test1</OPTION>
<OPTION>Test2</OPTION>
</SELECT>
<P>
The above HTML page has fields to take username, password and environment from user as shown in the Figure 26-1
Page 7 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We can use the webpage given above in QTP to obtain user input as shown in the following code:
oBrw.Sync
oBrw.object.Document.parentWindow.userAction = ""
IE Popup Dialogs
Page 8 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Depending on the user settings or the website being browsed, IE can generate several different popup dialogs. These
dialogs may vary from machine to machine depending on user settings and network authentication parameters. For
example, a web application might not ask for the user ID and password, if the user is already logged in using the Windows
Domain account. The same application might ask for the required authentication credential when a local system user is
logged in. Then there are several Security warning dialogs, Security information dialogs, and the list goes on. There are
two ways to handle these types of popup dialogs. One is to write code which checks for various dialogs and then take
necessary action to skip them. And the other way would be to change the IE settings manually or programmatically to
disable display of these popups.
Disabling IE Dialogs
We can disable the display of any IE dialog box using the silent property of the browser, as shown in the code given below
The problem with the approach given above is that it will take the default action on the dialog. So when IE displays a dialog
and the default button is No, then this will take action as if No was clicked. But often we want to click the Yes button. So
this solution is seldom the appropriate one.
Warning Using this technique will not allow browsing a website which requires authentication through the IE password
dialog.
The Window's Shell object provides the RegRead, RegWrite and RegDelete methods to access and modify the Window's
registry. We can change registry settings using the methods shown in the following code example:
Warning Accidentally deleting or modifying a key in the registry may crash your computer. These actions should be
performed with caution. And before trying out any code the registry should be backed up.
Let's discuss various different popup dialogs and how to disable them in the registry.
Popup Blocker
The IE popup blocker blocks popup windows generated by the web page. This sometimes causes problems when we need
the popup to be launched. The popup blocker bar is shown in the Figure 26-2.
This setting can be switched OFF or ON by using the following code to change the registry:
Page 9 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We can also add a website to the "popup allowed" list by using the following code:
If script error dialogs are enabled then any script error will be reported using an appropriate popup dialog. A typical script
error dialog is shown in the Figure 26-3
WshShell.RegWrite _
"HKCU\Software\Microsoft\Internet Explorer\Main\DisableScriptDebuggerIE", _
"yes" , "REG_SZ"
WshShell.RegWrite _
"HKCU\Software\Microsoft\Internet Explorer\Main\Error Dlg Displayed On Every Error", _
"no" , "REG_SZ"
Page 10 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Page 11 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
These settings are stored in a zone. There are five different zones in IE settings
n My Computer
n Internet Zone
If we are not sure which zone we would be working on then we can disable the settings in all the zones. Each setting has
its corresponding code. These codes can be found in Microsoft KB article 182569
(http://support.microsoft.com/kb/182569).
Page 12 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Disable the Security information secure non-secure popup in all the Zones
SettingCode = "1609"
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
The active content/Java script is popup bar instead of a window as shown in the Figure 26-8:
Page 13 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
When we try to download a file, IE pops up an information bar as shown in the Figure 26-9
To disable the above information bar we can use the following code:
We can also work with these IE popup dialogs by using a code when we know the dialog's title. The best way to handle
this situation is to use QTP Descriptive programming (DP). We can interact with any dialog displayed in IE using the
following DP code:
CleanBrowserPopups = False
If oPopDlg.Exist(0) Then
'There is a popup dialog
'Get its title
sPopTitle = oPopDlg.GetROProperty("title")
Page 14 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
End Select
End If
End Function
It would make it more convenient to integrate the above function with the Browser and Page sync methods. We can do that
by using the code given below
'Sync
oObject.Sync
'Re sync
oObject.Sync
End Function
n Save As
n File download
Page 15 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'We will use window handle because the title will change later
'From "File Download" to "Download Complete", but handle will remain
'the same
hWnd = oDlg.GetROProperty("hwnd")
Page 16 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
If bWaitComplete Then
'Once download is complete either the window is closed if the checkbox
'was checked or the Open Folder on the window will change get enabled
While .Exist(0) and Not .WinButton("text:=Open &Folder").
GetROProperty("enabled")
Wait 1
Wend
Usage:
QTP does not provided any direct method to check for broken images on a web page but there are certain properties in
DOM which can be used for this purpose. A broken image has following property values:
n fileSize = -1
n readyState = "uninitialized"
Page 17 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
pgTitle = oPage.GetROProperty("title")
Set allImages = oPage.object.Images
iCount = allImages.Length - 1
For i = 0 To iCount
Set curIMG = allImages.item(i)
sHTML = "HTML = " & curIMG.outerHTML
If curIMG.fileSize = -1 Then
'The image did not load
Reporter.ReportEvent micFail, pgTitle & "Broken Image", sHTML
Else
Reporter.ReportEvent micPass, pgTitle & "Valid Image", sHTML
End if
Next
End Function
'Usage
CheckBrokenImages Browser("micclass:=Browser","index:=0").
Page("micclass:=Page")
Note We have used the DOM in the example given above because QTP ChildObjects function will not search inside all
the WebTable objects. Some of the images inside the WebTable might get ignored while using the ChildObjects
method.
A browser Window is treated as a Browser object by QTP because of the Web add-in. If we disable the Web add-in and try
to work with a browser, all the actions will be recorded against the browser's Window object. Each Window has its own
unique handle which can be used to identify it. We can use the following approach to work with a Browser as a Window
object:
With this "conversion" technique we can then use all of the Window Test Object's methods, many of which are not directly
supported by the Browser Test Object:
Page 18 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Certain Windows applications host browsers inside them. By default QTP doesn't recognize the emebeded browser in
applications and identifies the whole browser as WindObject. To identify an embedded browser we need to first register
our application as a Browser. QTP provides a utility "Register New Browser Control" to register such applications. The tool
is located at Start Menu→All Prorgrams→QuickTest Professional→Tools→Register New Browser Control.
Page 19 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Page 20 / 20
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Quality Center (QC) is a test management tool from HP/Mercury. QC can be used to manage requirements, tests and
defects. Many companies prefer storing their scripts within QC and later running them from QC. Scripts stored in QC do not
behave exactly the same way scripts stored on Local or shared folders do. For our scripts to be able to run from either QC
or Local, some modification in the code is required. These modifications depend on type of actions a script might be taking.
The actions may include updating a file, creating a new test result file etc.
Quality Center
QC can be used to store different types of tests. These types include Manual, WinRunner, and QuickTest. QC has four
different primary tabs:
n Defects – This tab is to log defects and bugs found during testing
To work with QC we first need to connect QTP to QC. To connect QTP to QC, Open QTP and go to menu Tools→Quality
Center Connection… as shown in the Figure 27-1
Once connected, we can save the scripts in QC as shown in the Figure 27-2
Page 2 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
In case there is a need to switch from the QC test plan to the file system then we can click on the File System…button as
shown in the Figure 27-2
Saving scripts in QC provides a way to have a centralized repository for the scripts.
QC Paths
Once a test case is saved to the repository it will then be presented on the QC test plan tab. The root folder of this tab is
named "Subject". So any QC path referenced in QTP will start with "[QualityCenter] Subject". Once the test scripts are
moved to the QC repository all the folder paths on QTP's Tools→Options…→Folder (Tab) need to be changed to the
appropriate QC path for the scripts to work correctly. By default QTP takes the <CurrentTest> location as one of the paths
to search for various files. Any associated resources i.e. resource libraries, shared object repositories and data tables
stored as an attachment in the Attachment tab of the script inside QC, will be available to the test. These paths are also
used to resolve any external reusable action call.
QTP functions which use file path for reading purpose as parameter, can also use QC paths. All of the statements given
below are valid in QTP:
Note QC path won't work with functions like DataTable.Export, DataTable.ExportSheet etc. as they are writing files to
QC and not reading.
Relative Paths in QC
We can't directly use relative paths when working with QC for example if we use a path
"[QualityCenter] ..\Common\Common.vbs" it is considered invalid. QTP tries to find the each required resource in all the
folders specified in the tools folders options. Though we cannot specify a relative path in the folders options but we can do
it for the resource itself. Which means that we can specify the path of the VBS library for example -
"..\Common\Common.vbs" while the QC path mentioned in the Folder options would be the absolute path.
Page 3 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Relative paths are based on "." (Current folder) and ".." (Parent folder). So a relative path like "C:\All Test\Tests\Test1
\..\Common\.\Common.vbs" will finally resolve as "C:\All Test\Tests\Common\Common.vbs" using the following rules:
n Each "\.\" is replaced by a "\" as "." means the current folder only.
n Each "\..\" causes deletion of all text before it until a "\" character is encountered. In our case the "\Test1\..\" path
portion is replaced by a single "\".
We can implement the conversion rules given above by using the following function:
Do
'Replace all "\.\" with "\"
sPath = Replace(sPath, "\.\","\")
If iRelPath2 = 0 Then
sPath = Left(sPath, iRelPath-1) & Mid(sPath, iRelPath + 3)
Else
sPath = Left(sPath, iRelPath2-1) & Mid(sPath, iRelPath + 3)
End if
End If
'Loop untill all relative paths are resolved
Loop while iRelPath <> 0
'Return the resolved path
ResolveRelativePath = sPath
End Function
This function can be used as shown in the following code:
'Displays "C:\Tests\Common\Common.vbs"
MsgBox ResolveRelativePath("C:\Tests\TestCase1\..\Common\Common.vbs","")
QCUtil Object
QTP supports the QCUtil utility object which provides the following properties:
n IsConnected – This is a Boolean value and indicates if QTP is connected to QC. This only indicates connectivity status
and not whether a QC test case is running or not
n TDConnection – returns a reference to the Quality Center COM object of the QC Open Test Architecture (OTA).
Page 4 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Discussing the OTA is out of the scope of this book but we will take a look at few basics of OTA later in this chapter
n CurrentTest – returns a reference to the current QC OTA Test object. This is a reference to the test present in the Test
Plan tab
n CurrentTestSetTest – returns a reference to the current QC OTA TSTest object, which represents an execution
instance. The CurrentTestSetTest is present on the Test Lab tab
n CurrentTestSet – returns a reference to the current QC OTA TestSet object, which represents a group of tests. The
CurrentTestSet is present on the Test Lab tab
n CurrentRun – returns a reference to the current QC OTA test Run object.The test Run contains properties of the Test
(inside test sets) in the Test Plan tab
The properties discussed above are valid, depending on how a test is running, as defined in Table 27-1:
Table 27-1: QCUtil properties existence
CurrentTest CurrentTestSetTest CurrentTestSet CurrentRun
Test not stored in QC Error -<Cannot Error -<Cannot Error -<Cannot Error -<Cannot
Evaluate> Evaluate> Evaluate> Evaluate>
Test(in QC) running manually with results OTA Object Nothing Nothing Nothing
stored in temporary folder
Test(in QC) running manually/through QC OTA Object OTA Object OTA Object OTA Object
with results stored in a QC Run
Note In the table given above, if results are getting stored in QC then we cannot determine if the test was run through a
QC TestSet or it was run through QTP. In case this information is required we can check if the test is opened in
read only mode or not. Read-only mode would mean the test was run through a QC TestSet. To check if the test
is opened in read-only mode, we can use 'Setting("isreadonly")'.
IsConnected can also be determined using the TDConnection property. If TDConnection property is not set then it means
QTP is not connected to QC. All these properties can be used as shown in the following code:
QC OTA provides a very large object model. Figure 27-3 shows a few selected objects from that model.
Page 5 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
TDConnection is the top level object in the model. This object is required to connect to the QC server and works with any
project. In QTP we obtain a reference to this object using the following statement:
Note This has been renamed to QCConnection in QTP 9.x. Though for backward compatibility it would still work in
QTP 9.x as QCUtil has a hidden object TDConnection.
But if we are not connected to QC then the above statement won't work and returns 'Nothing'. There are two ways to
connect to QC through QTP, one of them is to connect through the QTP UI which has already been discusses earlier. The
second method is to connect using the QTP Automation Object Model (AOM), which is shown using the following code:
Page 6 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
False
End If
Note In case we are running the code given above in QTP then we can also replace the last line as Set TDConnection
= QCUtil. TDConnection.
The code given above first determines if we are already connected to the desired project and if not then it performs the
required connection. If we don't want to use a plain text password then we can use the QTP Password Encoder tool
located in the QTP programs folder menu. The code lines that would be changed are as follows
'Encrypted password
sPassword = "46c8c47fc7c4cdc8b310968680abb263967e14b5f4d0"
The method given above uses QTP AOM to get a TDConnection object reference, but it is also possible to create the
object using the CreateObject function as follows:
'Connection details
sServerURL = "http://qcserver"
sDOMAIN = "DEFAULT"
sProjectName = "QualityCenter_Demo"
sUser = "username"
sPassword = "password"
The Command and Recordset objects allow us to get data directly from the QC project's database. Details about the QC
database tables are out of scope for this book but we will show how to make a simple query and process the results. The
following code shows how to get the Design Steps (i.e. Manual Steps) present in test plan for the current test:
Page 7 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
TDCommand.CommandText = _
"Select DS_DESCRIPTION, DS_EXPECTED From DESSTEPS where DS_TEST_ID = " &
TestID
We can use the above technique to pass parameters to the script using the design steps in an automated script. Note that
in the example given above the description and expected value returned from the database is in HTML format. We can use
the following function to convert the HTML to plain text:
Attachments present in an object can be accessed through the AttachmentFactory collection. The Object can be one of the
following:
n Test Plan Tab – Folder, Test in the folders and Design steps inside the tests can have attachments
n Test Lab Tab – Folder, TestSet, Test in the TestSet, TestRun of a Test, TestStep inside a TestRun can have
attachments
Downloading and uploading attachments to one of these objects is done in a similar manner.
But before we can download an attachment we need to locate a specific attachment in the collection. The following
function shows how to find an attachment inside a selected object. The function returns an array of attachment objects
which match the specified file name criterion:
Page 8 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'If there is a * present in the file name then treat it as regular expression
'*.txt will be invalid r.e. in VBScript. So convert to .*.txt
If InStr(FileName, "*") Then
'It's regular expression
regEx.Pattern = Replace(FileName,"*",".*")
Else
'Treat it as a complete file name by appending ^ at start and $ at end
regEx.Pattern = "^" & Replace(FileName,".","\.") & "$"
End if
'We create an extra element in the array for the last attachment. Removed
'the extra element
ReDim Preserve filesFound(UBound(filesFound)-1)
The function uses the NewList function to get the collection from an AttachmentsObject and then parses all attachments to
get an array matching the file. Use the following function to download specific attachments:
'If there is no \ at the end of the folder path then add one
If Right(TOPlace,1)<>"\" Then
TOPlace = TOPlace & "\"
End If
'Copy the file from temporary downloaded location to the TOPlace folder
FSO.CopyFile oFindAttachments(i).FileName, _
TOPlace & oFindAttachments(i).Name(1),True
Page 9 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Download all the VBS file starting with name as override from the
'current test set in which the test is present (test lab tab)
DownloadAttachments QCUtil.CurrentTestSet, "C:\Download", "Override*.vbs"
'Download TestData.xls from the current test (in the test lab tab)
DownloadAttachments QCUtil.CurrentTestSetTest, "C:\Download", "TestData.xls"
Downloading files from QC in QTP is not very complex. According to the QTP help, the PathFinder. Locate method returns
the full file path that QTP uses for the specified relative path (resolves the path) based on the folders specified in the
Folders tab search list (Tools > Options > Folders tab) of the Options dialog box Consider the paths present in the folders
tab:
<CurrentTest>
[QualityCenter] Subject\All Test\Common
Assume we have a common.vbs file in the QC path's common folder and we execute the following code:
We would intuitively expect the path to be "[QualityCenter] Subject\All Test\Common\Common. vbs". But after running the
code we will find that the MsgBox statement displays something like this:
"C:\DOCUME~1\tarun\LOCALS~1\Temp\TD_80\de8007cd\Attach\QTPro\ALL_LISTS_730_ Common.vbs"
So, what happened in here? PathFinder.Locate does something which is not documented in the QTP help. In case a file is
located inside QC then QTP downloads the file to a temporary location and returns that path. But what happens if we have
to download a file located in the "[QualityCenter] Subject\All Test" folder or some other folder? If we use the file's complete
path it too will be downloaded:
Msgbox sFilePath
Note The technique mentioned above can only be used on folders or tests present in the test plan tab.
Warning The method described above will not always download the file. This happens when the file with same name is
already present in the temporary folder. To fix this situation all the temporary files should be cleared.
Uploading Attachments to QC
The following function can be used to upload attachments to QC using the AttachmentFactory object:
Page 10 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
sFileName = GetLastNodeFromPath(FileName)
'If the attachment already exists and we are supposed to overwirte the
attachement then
'remove the attachment first
If UBound(oFindAttachment) >= 0 and overwriteExisting Then
oAttachments.RemoveItem oFindAttachment(0)
End If
When files are uploaded to QC and the file name already exists in the attachments then QC appends a number to the file.
To avoid this behavior we need to first remove the old attachment and then upload the new one. To achieve this, set the
overwriteExisting flag to True when using the AddAttachment function:
'This will delete old File.txt and uploade the new copy
AddAttachment QCUtil.CurrentTest, "C:\Test\File.txt", True
To get the current test's location we use the CurrentTest Object to locate for the test's parent folder path:
Page 11 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
testName = CurrentTest.Name
The QC OTA object model's TreeManager object manages the complete folder structure of the test plan tab. Each folder
can contain sub folders and/or tests. Tests inside a folder are managed by a TestFactory object:
We can enumerate the entire test inside a folder and its sub folders using the following function:
Note We can use any of the oTestPlanFolder or the oTest object with the DownloadAttachments function we created
earlier in this chapter.
Page 12 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The Test Lab folder structure is managed by a TestSetTreeManager object. These folders can further contain sub folders
and/or TestSet objects. TestSet objects are managed by a TestSetFactory objects. Each TestSet object contains one or
more test managed by a TSTestFactory object. This object model is shown in the Figure 27-5
Now we will create two recursive functions to enumerate all the Tests located in the Test Lab tab, one function to
enumerate all the test sets in a folder and another to enumerate all the tests present inside a test set:
'A root folder cannot have any test set. So we need not check
'for any testsets in case of the Root Folder.
If oTestSetFolder.name <> "Root" Then
Print oTestSetFolder.Path
Page 13 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
End Function
'Usage
'Enumerate all test sets and tests inside them for test lab tab
EnumerateAllTestSets ""
We can use the CurrentTestSet object in QTP to get the location of the test set in the Test Lab tab. The root folder of this
tab is named as "root" while the root folder in test plan is called "Subject". To get the test set location we can use the
following function:
Page 14 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Some complex system testing scenarios require QTP to coordinate its code execution activities with other scripts and
application which are executing independent of QTP. In this situation we need the various applications and QTP to work
together through a synchronization semaphore described in this section.
To create this solution we need to get progress information from a running QTP script. The QTP Automation object model
(AOM) exposes the Environment object, which we can use at run-time to implement a needed synchronization point (a
semaphore) to coordinate and control the script's execution. The following code show's how to get the environment of a
local or a remote PC using AOM:
Now when we want to wait for QTP to reach a certain point in the script we have the script update an Environment variable
after reaching that point. Consider the following QTP scripts:
QTP Script 1
'Script 1
'Create a SyncPoint environment variable here
Environment.Value("SyncPoint1") = False
VBScript 2
This VBScript waits for QTP Script 1 to reach its SyncPoint1 state to start its execution:
'Local machine IP
strCompIP = "127.0.0.1"
Page 2 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Run Script 1 in QTP and Script 2 in the Windows Script Host (WSH) environment. We will see that the Script 2 waits until
we dismiss the "Job 1 Completed" message box in the QTP script, thereafter Script 2 presents the "Script 1 has passed the
sync point" message box‥
We have already seen in the "Utility Objects" chapters that there are several documented Setting variables:
n Setting("AutomaticLinkRun")
n Setting("DefaultLoadTime")
n Setting("DefaultTimeout")
n Setting.WebPackage("ReplayType")
n Setting("SnapshotReportMode")
n Setting("WebTimeout")
Now we can enumerate the settings at run-time or we can use the registry to determine what settings are available. We will
notice how easier the job becomes after knowing these settings and things that were not looking possible earlier are
possible now. Let's take a look at both the methods
Method 1 – Looking for Settings in Registry
First launch REGEDIT.exe from the Windows Run dialog. There are two main keys where the settings variable exists
and
Let's see how to access these settings. Browse to the key as shown in the Figure 28-1
Page 3 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Now if we want to access the ObjRepType data inside the TSRManager key, we need to use the following code
Msgbox Setting("TSRManager")("ObjRepType")
By changing the object repository type in the script and running the code mentioned above we will notice
0 = Per-Action repository
The format is using the all the child keys after SettingInfo and the last value name
We believe QTP gets complete registry for the two specified keys (including sub keys). We can access any of the keys that
we want by using the format specified earlier
Warning Changing some of these settings at run-time might cause unexpected behavior. These should always be used
for read only purposes.
Method 2 – Enumerating Setting Objects and Variables
The Setting object is actually the "Mercury.ScriptSetting" COM library. This library provides two undocumented arrays for
enumeration. The arrays are named Keys (which contains all the keys) and items (returns all the object/value stored for a
given index/key).
A Setting value can be an object or a plain variable, so it's important to use the TypeName function to make this
determination.
The Setting.Keys property returns a 2 dimensional variant array with first dimension as 0. In the Figure 28-2 we enumerate
Page 4 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
all the keys and place them into the Global DataTable in the Key, Value and Type columns:
'ObjSetting is of Type
Public Function EnumerateSettings(objSetting)
'Get arrays of key
vKeys = objSetting.Keys
Run the code given above and the output will appear in the run-time data table. Export the sheet and open it. The sample
enumerated sheet is shown in the Figure 28-3
Page 5 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
If we notice the type of various keys we will notice that many of them have "IScriptSetting2" which is nothing but the
Interface for "Mercury.ScriptSetting". This means we can also enumerate that object using the same method we used for
the Setting object. Here is an example of how that is done:
Table 28-1 shows some of the settings and the description for them
Table 28-1: Settings
Setting Description/Value
Setting("FirstGloballteration") Starting iteration row number of the global data table from the run settings
Setting("LastGlobalIteration") Ending iteration row number of the global data table from the run settings
Setting("GlobalIterationMode") The iteration mode in the run settings
1 = Run on all rows
Setting("OnReplayError") Set what action needs to be taken in case an error occurs while replaying the script
Following are the possible values:
Dialog = pop up message box
Page 6 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
1 = enabled
Setting("TSRManager")("TSRFilePath") File path of the shared object repository in case objRepType is 1. The value might be present
even in case objRepType is 0 but it's not used in such a case
Setting("TSRManager") Default Type of object repository being used for all new test
("DefaultObjRepType") 0 = Per-Action repository
Setting("TSRManager") Default File path of the shared object repository in case objRepType is 1. The value might be
("DefaultTSRFilePath") present even in case objRepType is 0 but it's not used in such a case
Setting("ReplayRecovery")("Enabled") Recovery scenarios
0 = Disabled
1 = Enabled
False - Read/write
We can use it to disable the display of test results after the run is completed but that cannot be
re-enabled until QTP is closed and launched again
Setting Persistence
The Setting variables added at run-time in script are not destroyed when the test run completes. They are only destroyed
when QTP is closed or a new script is opened.
Page 7 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The first run displays the message "Session created" while all subsequent runs of the same QTP run display the "The
session exists" message. This demonstrates that the settings are persisted in memory.
Note Setting persistence only remains for a script session. Settings object is re-instantiated on closing of QTP or
opening up of new script within the same QTP session.
Setting persistence allows us to create a session based test. Now we exploit this capability to implement code which can
restart QTP programmatically.
n When a recovery scenario is added at run-time it doesn't get applied to the test until the test case is stopped and re-run
n When we are running multiple sessions for Terminal Emulator (TE). QTP does not allow running multiple TE sessions
within a single script run. To run on multiple sessions the script needs to be stopped at the end of each session code
and should be re-run from the point where the next session begins
The technique would be to call the restart QTP routine but only to run it for the first time. Now when we stop QTP we can't
execute any code to re-run it. So we will run an asynchronous script which will check if QTP is not in running mode and
then run it and the script will end.
Sub AsyncReRunQTP()
'Create the re-run script at run-time
Call CreateQTPRunScript()
Page 8 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
file.WriteLine "Wend"
file.WriteLine "qtpApp.Test.Run ,False"
file.close
set file = nothing
set fso = nothing
End Function
The StopAndReRunQTP function checks if the flag exists in the setting and stops QTP only if the flag does not exist in the
setting. This is where Setting Persistence plays a key role. Without it, it would not be possible to skip the restart code.
The AsyncReRunQTP function creates and executes a VBScript. The created script can now re-launch QTP at run-time.
Here is the code for the re-run
Recovery scenarios can be added at run-time using QTP Automation Object Model (AOM), but we need to use the stop
and re-run function as described above:
qtpApp.Test.Settings.Recovery.RemoveAll
qtpApp.Test.Settings.Recovery.SetActivationMode "OnEveryStep"
sRecoveryFileName = "C:\Program Files\Mercury Interactive\" _
& "QuickTest Professional\recovery\WebRecovery.qrs"
qtpApp.Test.Settings.Recovery.Add sRecoveryFileName, "Security Warning", 1
qtpApp.Test.Settings.Recovery.Item(1).Enabled = "True"
StopAndReRunQTP "AddingRecoveryScenario"
End If
QTP uses VBScript, which is not an event driven language, so we don't have script start or script end events. But
executing some codes at the start of a script is easy which is done by adding that code in a VBS file and then associating it
with the test resources.
Now we give an example of executing the code at the end of a script to export a data table; this is commonly done at the
end of the last Action in a script. But the problem is that when we are using global iteration that code will get called again
and again. On every iteration the sheet will get exported, which is something not desirable. The typical workaround is to
execute the code at the last iteration only.
The above code works fine in most situations but it fails when we have imported the global sheet as the 'Setting
("LastGlobalIteration")' is not updated at run-time.
Page 9 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
So next we describe a solution to this problem using code that will only be executed when the script terminates. We know
that a VBScript class has a built-in Initialize and Finalize subroutines, which are executed when the class is created and
destroyed respectively, as in:
Sub Class_Terminate()
MsgBox "Terminated"
End Sub
End Class
Dim oLoadUnload
Set oLoadUnload = New LoadUnload
If we run the code given above using the Windows Script Host (WSH) host we will be presented with both the "Initialized"
and "Terminate" message boxes. We didn't destroy the oLoadUnload object but still it was destroyed automatically by the
WSH Host.
Now we add this VBScript file to a QTP script on its Test Settings Resource tab and run the script for 3 or 4 iterations. We
will observe that only the "Initialized" message box is presented. QTP (version 8.x) didn't implicitly destroy the oLoadUnload
object after the test script was terminated. The finalized event does not fire which makes it even more important for it to be
able to execute a finalization code in QTP.
Note This issue is present in QTP 8.x but has been resolved in QTP 9.x, so no special additional coding is needed
while using version 9.x.
The following code provides a solution that works with both QTP 8.x and 9.x, because the built-in QTP Environment object
is always destroyed when a script terminates. So we change the code given above to store the oLoadUnload object
reference in a new QTP Environment variable:
Now if we run the QTP script we will be presented with both the "Initialized" and the "Terminate" messages.
Note If we need to access any of the methods or properties of the class we can use
Environment.Value("oLoadUnload").MethodName
Environment.Value("oLoadUnload").Property = Value
Warning If we assign the object from the Environment variable to another variable then this technique won't work in
QTP 8.x as the there will be multiple references to the object and only the reference stored in the Environment
object will be destroyed when the script ends.
For the optimal utilization of the above concept, the LoadUnload class should only be used to Load and Unload other
objects. Consider the following code:
'Variable declaration
Dim FSO
Dim xlApp
Dim oMyClass
Class MyClass
'....
End Class
Class LoadUnload
Sub Class_Initialize()
Page 10 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Sub Class_Terminate()
On Error Resume Next
'Clean up all the objects
Set FSO = Nothing
End Class
Dim oLoadUnload
Environment.Value("oLoadUnload") = New LoadUnload
Note The best thing about the approach mentioned above is that even if we click the stop button and the test is
aborted, the class termination sub routine will be called.
A Browser snapshot taken normally through QTP will only include that area of the web page which is visible on the screen.
This may not include our object of interest which is on the web page. QTP provides an undocumented MakeObjVisible
method for each TestObject which can be used to ensure that the object is visible in the displayed portion of the screen:
To create text checkpoints on the fly, we implement a custom checkpoint using classes. Consider the following information
we need about a Text checkpoint:
n ComparisonType – This can determine the type of comparison, for example few of the possible values can be
CONTAINS, EQUALS, CONTAINS, REGULAREXPRESSION
Since a page can have multiple checkpoints we will allow multiple checkpoints with same name.
We use the following class to implement a single row of checkpoint as shown in Table 28-2
Page 11 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The TreatFailAs and TreatWarningAs flag allows us to disable checkpoints. Setting these flags to Pass will force a
checkpoint to pass even when the checkpoint fails. Now we can create a TextValidations class which has a dictionary of all
TextValidation type objects. This class is used to store checkpoints with the same name.
Sub Class_Initialize()
'Create the Dictionary
Set oValidations = CreateObject("Scripting.Dictionary")
Ens Sub
Page 12 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
pVal.Value = pValue
pVal.ComparisonType = UCase(Trim(pComparison))
pVal.TreatFailAs = UCase(Trim(pTreatFailAs))
Case Else
pVal.TreatFailAs = micFail
End Select
pVal.TreatWarningAs = UCase(Trim(pTreatWarningAs))
Sub Class_Terminate()
oValidations.RemoveAll
Set oValidations = Nothing
End Sub
End Class
A single validation is executed using the following function within the class:
Page 13 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
sExpected = pValidation.ExpectedValue
Since we can have more than one validation with same name stored in the TextValidations class we need to have one
more function which will execute all of them one at a time. The following function is used for that purpose within the class:
Check = False
Reporter.ReportEvent micFail, oValidations("1").Name, "Object does not exists"
Exit Function
End if
Page 14 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
iCount = oValidations.Count
We load these checkpoints from an excel spreadsheet using the following function:
'
If xlApp is Nothing Then
Err.Raise vbObjectError + 2, "Unable to open excel","AddObjectsFromXL"
AddObjectsFromXLS = False
Exit Sub
End If
'In case sheet name is not specified then load the first one
If IsEmpty(sSheetName) Or IsNull(sSheetName) Then
Set xlWorkSheet = xlWorkBook.Sheets(1)
Else
Set xlWorkSheet = xlWorkBook.Sheets(sSheetName)
End If
Page 15 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
We now combine the functions described above as shown in the following code:
Note mChecks("Checkpoint 1") return an object of type TextValidations which may further contain series of checkpoints.
We can put an arbitrary number of functions into a custom class to extend test object functionality, as in:
'Returns the Index of a column by looking up for a given text in the header
Page 16 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
row
Public Function GetColIndex (ByVal Col)
'Check if input is string or a number
If VarType(Col) = vbString Then
Col = "Text:=" & Col
'Check if a column with given text exist in the header row
If oWebTable.WebElement("html tag:=TR","index:=0").WebElement("html
tag:=TD|TH",Col).Exist(0) Then
Set oCell = oWebTable. _
WebElement("html tag:=TR","index:=0"). _
WebElement("html tag:=TD|TH",Col)
GetColIndex = oCell.GetROProperty("attribute/cellindex") + 1
Else
GetColIndex = 0
End if
Else
GetColIndex = Col
End If
End Function
Method 2
This method registers the class as a function using the QTP RegisterUserFunc function.
'Register the Extend function as one of the methods for WebTable object
RegisterUserFunc "WebTable","Extend","exWebTable", True
'Now we can use extend function as
Msgbox Browser("..").Page("..").WebTable("..").Extend.GetCellDataDOM(4,4)
This approach provides means to extend QTP Test object functionality in a consistent way. And we still have the original
methods available to be used.
Page 17 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
As it is mentioned in the QTP Help, "The QTP Automation Object Model (AOM) can be used in any programming language
that supports COM components (VBScript, JScript, VB, VBA, VC,.NET Languages etc.)". But some people confuse this
statement and tend to believe that QTP test scripts themselves can be written in any language. QTP only supports writing
scripts in VBScript language. Though we can use a workaround and write partial code in JScript for a QTP Script. Before
we start doing that first let us see what we would gain if we were to use the JScript code in QTP:
There are few other differences between JScript and VBScript but those above are the only ones we will discuss in this
section. Since QTP uses VBScript as its main scripting engine, it is not possible to introduce JScript code inside the
current scope or context of a script. To be able to use JScript we need an external host which allows us to execute JScript
code at run-time and also allow us to make calls to the code added. Internet Explorer is one such host application which
allows the use of both JScript and VBScript within an HTML page. It allows accessing variables and methods inside any
scripting code using the window object of HTML. Let's first see how we execute a simple java script within QTP:
The code given above creates an HTML file in the memory and then gets the window object for the same. The window
object provides execScript method which is used to load JScript or VBScript code. By default the code is taken as JScript;
to use VBScript we need to pass another parameter to execScript:
The JScript function that takes a variable number of parameters in JScript and return there sum is given below:
Page 18 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
{
sum = sum + arguments[i];
}
return sum;
}
We can then use this JScript function in a VBScript environment using the following code:
Scope Differences
It is critical to understand the difference in Scope between QTP and the JavaScript code being executed. Since JScript
code executes in an external host, it has no access to any of the QTP objects like SystemUtil, Window, Browser, Print,
QCUtil etc. This does not imply that we cannot pass these variables to create them in JS scope. Consider the following
example which allows adding SystemUtil support to the JScript code
Similarly, to use OR objects or DP objects we need to pass the top most object into the JS scope. The following code
would throw an error because of the Browser object not being in scope
To make the above code work we need to introduce the Browser object into the JScript scope. This can be done using the
following code:
One big advantage of JScript over VBScript is the functionality of the JScript Try/Catch/Finally construct for effectively
processing errors. The following code demonstrates the usage of this construct:
Page 19 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This script would generate output in the print window as shown in the Figure 28-4
JScript arrays differ from VBScript arrays. So an array created in JScript can't be accessed in QTP like normal VBScript
arrays. The following code demonstrates how to use a JScript array in QTP:
'Create a JS array
JS.execScript "var arrTest = new Array(4,1,5,2);"
There is another way to enumerate through the elements of the array, using enumerators. The following code shows this
technique:
'Create a JS array
JS.execScript "var arrTest = new Array(1,2,3);"
Page 20 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
JScript supports creating classes using this object. The following code demonstrates the same
We can also assign methods to the class. The code given below demonstrates how to add Display method to a person
class
Note All the above methods need to be loaded using JS.execScript as done in the previous examples of this chapter.
At times, QTP does not recognize an object correctly. We can force QTP to map these objects to a specific QTP object
type by updating a few details in the system registry HKEY_LOCAL_MACHINE\SOFTWARE\Mercury
Interactive\QuickTest Professional\MicTest\Packages\StdPackage\ClassMap setting. A class mapping is shown in the
Figure 28-5.
Page 21 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
To create a mapping we need to create a REG_SZ entry with the object's class name (as shown by the Object Spy) and
an entry value which is the mapped-to QTP Test Object name. So if there is a Tree View object in a .NET application
which is being recognized as a SwfObject then we use the following steps to map this object to a QTP SwfTreeview Test
Object:
n Find the object class using Object Spy. In this example it will be a "Company.Shared.Controls.TreeView" object
n Open regedit.exe
n Create a value named "Company.Shared.Controls.TreeView" and assign a value "Mercury.SwfTreeView" to the same
as shown in the Figure 28-6
Page 22 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Warning Troublesome objects might appear to function like a particular QTP Test Object, but infact they are not
internally implemented using standard methods and therefore class mapping may not always work. Editing the
system registry can cause harm to the system, so always backup the registry before making any changes to it.
Page 23 / 23
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
This chapter describes additions and enhancements added between QTP 8.2 to QTP 11. It can be important for teams to
know the reason behind upgrading to QTP 11 as there has been an introduction of some important features with the latest
version. This chapter can also provide a reference for teams that are unsure whether the upgrade will be a worthwhile
process for them.
Note Some of the features listed in this section may have been introduced in versions 9. x or 10.0. This chapter,
however, provides a list of all features since QTP 8.2 to make sure your environment is using the latest version of
QTP.
IDE Enhancement
Comments
You can now comment and uncomment select blocks of code. This can be done using one of the following ways:
n Using the shortcut hot keys after selecting the code block:
Improved IntelliSense
QTP 11 has improved IntelliSense as compared to its previous versions. Now, IntelliSense also works when creating tests
using Descriptive Programming (which was not the case with QTP 8.x). QTP 11 also provides IntelliSense for COM objects
created using CreateObject as shown in Figure 29-1.
Page 2 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n Run to Step: This option allows QTP to execute the script upto a specific line of code and Pause where the option 'Run
to Step' was selected Shortcut for this option is available using the CTRL + F10 combination
n Debug from Step: This option starts the script in Pause mode from the specified line
n Run from Step: This options start the script in Run mode from the specified line
Note The 'Debug from Step' and 'Run from Step' options performs an event in background which can't be noticed
through the QTP IDE. When we use these 2 options, QTP does nothing bit removes all the code before the
current line executes the scripts from that point. This is a very crude way of implementing these options. Because
of this behavior, a few limitations arise. For example, it is not possible to run the script within a conditional If
statement since it would generate a syntax error because of the If statement being deleted.
Enable/Disable Breakpoints
QTP 11 allows you to disable and later enable existing breakpoints. In QTP 8.x you had to clear all CheckPoints to disable
them but in 11 after disabling the CheckPoint the CheckPoint are still present but remain inactive until re-enabled.
Renaming CheckPoints
QTP 11 allows renaming CheckPoints which was not allowed in QTP 8.x. This feature allows teams to easily alter their
code once its created without recreating the CheckPoint.
QTP 11 provides Function Definition Generator accessible through the Insert Menu. This feature can be used to define
functions in the following dialog:
A few pointers to note from the Figure 29-2 and the result after accepting the changes made to the Function Definition
Generator:
n The string added to the Description text box appears as a tool tip when selecting the function from the IntelliSense list
n The Documentation text is displayed in the documentation column when working in the Keyword View
n The function parameters <File> and <Folder> are replaced with actual values for the Documentation text
n To add description and/or documentation, it is not necessary to declare the function through Function Definition
Generator only. If we type the function manually into the IDE, then the below code snippe twill work in the same
manner:
Page 3 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
QTP 11 allows editing multiple libraries at the same time. It also allows debugging any library added to the Test Settings
Resource tab. However, debugging of libraries loaded using the ExecuteFile statement is still not supported. To overcome
this limitation, QTP 11 provides a new method called LoadFunctionLibrary to load a library at run-time while providing
debugging support.
QTP 11 now supports performing drag and drop operation on web objects. This can be done by use the Drag and the
Drop method on the test object.
Most of the Web and SAP objects now support methods for Middle click and Right Click. These methods make it easier to
perform operations which earlier required the use of DeviceReplay or the Click method with micRightBtn constant.
Note RightClick method will fire onMouseDown, focus, onMouseUp, and onContextMenu events in series to simulate
right click when the ReplayType is set as Events. To use it as proper mouse right click change the ReplayType to
Mouse Setting.WebPackage("ReplayType") = 2
QTP 11 allows accessing the Object property for Web objects in FireFox. This allows accessing the underlying DOM
architecture of the web page. So the below code statement which earlier would have work on IE browser only would now
work on FireFox as well:
Note IE and FireFox both use a different set of HTML DOM. Though they have few things in common but not all DOM
based code written in IE will work for FireFox. For Ex – FireFox DOM doesn't have any property called outerHTML
which is frequently used in IE. Though FireFox DOM does support the innerHTML property.
Page 4 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note The properties and methods when used in Firefox are Case Sensitive. For example: nextSibling can be used as
NextSibling, nextsibling or any other way in IE. However, with Firefox, it can only be used in its correct Case:
nextSibling.
QTP 11 also allows identifying web objects using XPATH. This makes it easier to specify few objects based on their DOM
hierarchy. Instead of identifying a web object using different properties, we can just use one XPATH for the same. Consider
the below HTML object
Now we can identify this object using combinations of various XPATHs. Consider few of them
n //INPUT[@class='hover']
n //INPUT[@id='s']
n //INPUT[@id='s',@class='hover']
By using such XPATHs, we can also limit our object search. For example: if we want access to an object inside a
WebTable cell, we know that the object will have a parent with a TD html tag. In that case, we can use a XPATH like
//TD//INPUT[@name='s']
QTP 11 added a regular expression testing tool. The tool can be launched from Tools→Regular Expression Evaluator.
The tools allows testing the regular expression on a sample text as shown in Figure 29-4
Page 5 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n Browser().EmbedScript
n Browser().EmbedScriptFromFile
n Page().RunScript
n Page().RunScriptFromFile
The EmbedScripr or EmbedScriptFromFile methods can be used to embed a JavaScript in a web page. QTP will load this
script every time a Page or Frame refreshs. These methods make sure the JavaScript is always available in the browser
memory. These methods should be used to inject reusable JavaScript methods into the browser that might be required for
testing.
The RunScript and RunScriptFromFile method provides a way to execute a JavaScript and capture its results. Consider
the below code:
Page 6 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Menu Updates
QTP 11 has added several changes to the IDE Menu structure. Table 29-1 shows these changes in respect to version
8.2.:
Table 29-1: Menu changes from QTP8.x to QTP 11
Record… Record…
Ø Ø
Run… Run…
Ø Ø
Stop Stop
Ø Ø
Run From Step… Run From Step…
Ø Ø
Update Run… Update Run…
Ø Ø
Page 7 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Ignore Browser
You can now configure QTP to ignore the Quality Center as well as other browsers, using settings on the Options Web tab
as shown below in Figure 29-6
QTP 11.0 (since 9.2) can be configured to capture a movie of a test run. This configuration is done using the Options Run
tab as shown in Figure 29-7:
Page 8 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This section describes Utility objects that have been added and/or enhanced in QTP 11.
QCUtil
You may remember that this object was used in the "Working with Quality Center" chapter. The only change made to this
object is that TDConnection property has now been renamed to QCConnection. So any places where we were using
QCUtil.TDConnection, we now need to use QCConnection. If you want to create version independent scripts you can use
the following approach:
SystemUtil
QTP 11 adds two new methods to the SystemUtil object: BlockInput() and UnBlockInput().
The BlockInput method allows you to block input from the keyboard and mouse while the script is running. This allows you
to avoid any accidental keystrokes or mouse events which can disrupt the behavior of the executing test. This method
should is suggested when using methods like Type or Set (with replay type set to mouse), etc. Input is blocked until one of
the following events occur:
Page 9 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n A Breakpoint is reached
With Window("title:=Calculator")
'Block any user input
SystemUtil.BlockInput
Similar to some of its previous versions (not including 8.2), QTP 11 retains the Print Log utility that allows sending
messages to a QTP dialog in real-time, most often for the purposes of debugging. It can be used as shown in the below
code:
This code opens the 'QuickTest Print Log' window and displays the Print message as shown in Figure 29-8
Page 10 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Once the log window is open, each additional call to the Print function adds a new line in the log window. The only control
available in the Print Log window itself is a Clear All command. This new utility is limited as follows:
n The window's contents can't be saved directly to a file (but you can interactively cut and paste the window contents to a
text editor and then save the file)
It is possible to overcome the above limitations by using pointers described in the next section.
We can use the ShowWindow API call to hide and show the Print log window programmatically. The code for this is shown
below:
'ShowWindow constants
Const SW_HIDE = 0
Const SW_SHOW = 5
Using the technique described in the previous section and the constant SW_SHOW, we can unhide the hidden log window
using the following code:
If QTPlogWindow.Exist(0) Then
hwnd = QTPlogWindow.GetROProperty("hwnd")
'Show the window
Extern.ShowWindow hwnd, SW_SHOW
End if
End Function
However, if we attempt to use the above code when the print log window is hidden the window will not become visible. So
what went wrong? If we observe closely we notice that QTPlogWindow. Exist(0) always return False. This happens
because QTP does not work on invisible windows unless it has been instructed to do so explicitly. Therefore, to
accommodate for the behavior, we can change the Window object in the function as described below:
Page 11 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
se")
Now though, the above code will fail if the window is currently visible. When the window is visible, we need not perform any
steps. But in case we want to check the existence of the log window regardless of it being visible or invisible then we can
use the following approach:
In the following functions we use the "visible:=True|False" approach for all objects so that our functions are compatible
regardless of the visibility of the window.
'Function to get the text from the QTP Print Log Window
Public Function GetPrintWindowText()
GetPrintWindowText = ""
Set QTPlogWindow = Window("regexpwndclass:=Mercury::Qtprn::PrintWindow",
"visible:=True:False")
'Check if the Log window exist
If QTPlogWindow.Exist(0) Then
'Get the text from of edit box
GetPrintWindowText = QTPlogWindow.WinEdit("nativeclass:=Edit","visible:=True:Fal
se").GetROProperty("text")
End if
End Function
Msgbox GetPrintWindowText
Page 12 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
QTP 11 allows loading and running an Action at run-time. This eliminates the need of inserting a call through the QTP IDE
for the re-usable action. The syntax of the method is as shown below:
This is useful when the Action to be called is based on some condition evaluated at run-time. This is quite a useful feature
for teams that rely significantly on Actions and want additional flexibility to decide which action needs to be executed after
an event occurs.
Shared Object Repository (SOR) uses Repository parameters for dynamic object identification property values. Once a
SOR is mapped to a Test, its Repository parameters can be mapped to constant, DataTable, Environment or
RandomNumber as shown in Figure 29-9
These parameters can be accessed and updated at run-time using the Repository object as shown in the code below
QTP 11 provides a Local System Monitors feature to measure various System Counters for a specified process within the
test and fail the test in case the value for these counters exceeds a specified limit. To enable monitors go to
Test→Settings…→Local System Monitor. Select a process and add the System counters that needs to be monitored as
shown in Figure 29-10. The test is configured to fail if the memory usage of Internet Explorer crosses the 700MB mark.
Page 13 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note This feature does allow some amount of performance monitoring with QTP but cannot be used for extensive
performance monitoring where server parameters or multiple applications need to be monitored. This is actually a
good way to track the performance of IE or any other application when the tests are run for longer durations.
Reporting Enhancements
Reporting Images
QTP 11 also allows reporting images into the Test Results summary. Consider the below code:
The Test Result shows the image as shown in Figure 29-11. This image is also retained when the results are exported to a
HTML file
Page 14 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
With QTP 11, it is also possible to add notes to the test summary. These notes can be used for reporting the key
highlights, issues or important information which may help analyze the test results easily. Consider a scenario where we
execute a test against a given test data and it produces an error which is specific to test data, in such case we can add a
note to the test reporting what kind of test data is supposed to be used
strErrorExists = Browser("KnowledgeInbox").Page("KnowledgeInbox").WebElement("Error").
Exist(0)
If strErrorExists Then
Reporter.ReportNote "The test data used is not valid. Please use a account which has
access to the premium services"
End If
The output of above code in the Test results summary is shown in Figure 29-12
Page 15 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
MercuryTimer
MercuryTimers is a new utility objects that allows you to create various timers. A timer is automatically created when it is
first used. An instantiated timer can then be accessed as shown in the following code:
Wait 1
Page 16 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Start the timer (this is equivalent to using Reset and then start)
MercuryTimers("Time1").Start
Wait 2
'Stop the timer
MercuryTimers("Time1").Stop
RepositoriesCollection
RepositoriesCollection utility object allows you to add any number of shared object repositories at Run-time to the current
action, in addition to any object repositories associated the Action as well. The RepositoriesCollection object provides
following methods:
Above code will add object repository to the Action in which the code is being executed. These changes are run-time only
changes and are reverted back when the test run ends.
Warning If you use the above mentioned code in an Associated library file then it will only associate the repository to
the first action of the script and also the changes will not be reverted. Which mean the object repository will
actually be added to the test and running the code again may throw an error as the object repository will
already exists.
DotNetFactory
QTP 11 provides DotNetFactory utility object which allows creating instance of .NET classes in QTP. The object provides
only one method, CreateInstance:
'Function Syntax
Set var_CreateInstance = DotNetFactory.CreateInstance (TypeName [,Assembly] [,args])
Page 17 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The DotNetFactory utility has greatly enhanced what can achieve in QTP and that's why this book has a chapter dedicated
to discussing this feature in detail.
n In case the object is not from repository and the application is running then it will return the default name that QTP
would have given it if added to OR. This name will be enclosed with square brackets [ ]
n In case the object is not from the repository and the application is not running then the micclass of the object enclosed
with square brackets [ ]
n TestObjGenType: Returns the generic type of the object. For example text box, list box, table, text label, etc.
These new properties prove very useful for debugging and logging purposes. The TestObjName property gives use the
power to regenerate the whole object statement from an object. We created a function GetObjectSTR in the "Recovery
Scenarios" chapter that allowed converting an object to its string definition. Now we enhance that function to include the
TestObjName property in the following code:
iCount = oTOProps.Count - 1
'Loop through and create a array for string description
For i = 0 to iCount
sProps(UBound(sProps)) = oTOProps(i).Name & ":=" & oTOProps(i).Value
ReDim Preserve sProps(UBound(sProps) + 1)
Next
Page 18 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
'Prints "Dialog("Run").WinEdit("Open:")"
Print GetObjectSTR(Dialog("Run").WinEdit("Open:"))
'Prints "Dialog("Run").WinEdit("text:=Open:")"
Print GetObjectSTR(Dialog("Run").WinEdit("text:=Open:"))
The TestObjGenType might not be required generally and has no use in the above function.
Working of Object Repositories in QTP changed a lot from QTP 8.2 to QTP 11 (actual change being from QTP 9.0).
Instead of being able to associate a single shared object repository (SOR) to a test now QTP allows associating multiple
object repositories. The association happens at the Action level instead of the Test level.
Every Action in a QTP script has an associated Local object repository. The LOR is stored as a .BDB file in the Action's
folder. Objects in a LOR can only be used in the Action it belongs to. While recording scripts in QTP, if the object doesn't
exist in the associated shared object repositories (SOR) or LOR then QTP adds it to the LOR. This behavior of QTP
adding objects to LOR cannot be changed.
LOR can be viewed by using 'Resources→Object Repository' from menu or by pressing the CTRL + R key combination. By
default the LOR shows all objects present in LOR as well objects present in SOR. Objects shown from SOR which are
grayed out objects denote they are read only. We can filter on to just Local objects by using the Filter dropdown in the LOR
UI.
A LOR object always takes precedence over the same object from SOR. Consider the below case where a SOR
associated with the test has 5 objects. We can copy the top level "KnowledgeInbox" Browser object by right clicking and
using "Copy to Local" option as shown in Figure 29-10. This creates the copy of the same object in the LOR.
Page 19 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The behavior can be demonstrated if we edit and change the identification properties of the KnowledgeInbox Browser
object in the LOR and add a title property as shown in the figure:
Browser("KnowledgeInbox").Page("Login").WebButton("Log In").Click
Page 20 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The KnowledgeInbox browser properties will be taken from the LOR and rest of the identification properties will be taken
from the SOR. This is one key reason for object not found defect as well: when by mistake objects are added to LOR and
object identification is altered at run-time. The problem cannot be caught by looking in just the SOR as the object may still
get highlighted in the application through SOR. However, during execution, it may not work as expected.
n "Export Local Objects…" – This exports all the objects in LOR to a TSR file.
n "Export and Replace Local Objects…" – This exports all the objects in LOR to a TSR file and removes them from LOR.
Note Exporting LOR to existing TSR file will overwrite the existing TSR and not merge with the existing objects.
Shared Object Repository is external repository which can be shared by various test scripts. Despite its name, this object
repository cannot be shared across users simultaneously as only one user at a time can modify it. For all other users
accessing the SOR, it is viewed only in read-only mode.
A SOR is associated with a test at Action level. Actions and SOR have a manytomany relation i.e. an Action can have
multiple SOR associated and an SOR can be associated with multiple actions
Note SOR or LOR cannot be associated with the startup code of global scope. So if we Browser("KnowledgeInbox")
object in our LOR or SOR and we place the below code Browser("KnowledgeInbox").Sync in one of our
associated library then the code will error out as the OR will have no meaning without any action being loaded in
memory and during execution of global libraries none of the actions exists.
SOR have TSR as the file extension. To create a new SOR go to 'Resources→Object Repository Manager (ORM)…' and
click on the New icon
Note One cannot record and have the objects created in the SOR directly. Objects can only be added to SOR manually
or through Navigate and learn feature of ORM.
Page 21 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
To associate a SOR with the test go to menu Resources→Associate Repositories… and click on the + button to add a new
repository to add a SOR. After adding the SOR select the actions with which the SOR needs to be associated. Multiple
actions can be selected at the same time by holding the CTRL key and clicking the actions in the list. After selecting all the
actions (as shown in Figure 29-17) click on the arrow (>) button to make the SOR available to selected actions. Clicking on
the double arrow (>>) selects all the actions.
Page 22 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note A SOR cannot be associated with the Test. It can be associated with actions only. When a new action is added to
the test it will not get associated with the SOR. But it is still possible to achieve auto association of the SOR to any
newly created action. To do so browse to one of the Actions with the SOR already associated. Go to menu
Edit→Action→Action Properties…→ Associated Repositories (Tab). Click on the Set as Default button, this will
make all the SOR associated with current action as the default SOR for new actions.
Objects can be added to SOR clicking the button and clicking on the object with the hand pointer. After clicking
the on the object QTP show the "Object Selection – Add to Repository" dialog as shown in Figure 29-18. From this dialog
the whole hierarchy of the object is shown and we can select which object we want to add.
Note QTP doesn't add all the objects from the listed hierarchy. It only adds those which it needs to re-identify the
object.
We can add objects by defining them manually as well. To do it manually, click on the Define New Test Object
button. This shows the "Define New Test Object" dialog as shown in Figure 29-19. In this dialog we need to select the
Class (the test object type), the Name (logical name) and the description property values
Page 23 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
QTP displays the list of Mandatory properties by default in this dialog. To add additional properties for identification we can
click the button and add more properties for identification
Note This method is useful when the application is not ready to add objects. Also in certain cases QTP displays the
object hierarchy but is not able to add the object to the OR. In such cases we can note down the property values
and add them using this method.
We can add objects directly from the Spy. Click on the Object Spy button to launch object spy. In the object spy we
can select the object that needs to add to the OR and then click on the button to add the object to OR as shown in
Figure 29-20
Page 24 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
When we spy again on objects using Object Spy, the object icon shows if the object is already present in the OR as shown
in Figure 29-21
Note The feature of adding objects directly from the Object Spy to OR is only available from QTP II.
Note If Object Spy is launched from QTP IDE then objects will get added to the Local OR of the active Action and if the
Object spy is launched through Object Repository Manager then the objects will be added to current active SOR.
Page 25 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This feature of ORM allows navigating in an application and learning all the objects in between. To activate Learn mode go
to Object→Navigate and Learn… menu or press the F6 key. This will show the small "Navigate and Learn" window at the
top of the screen
To learn objects from a screen select the main window and click the Learn button. QTP learns all the objects
based on the current filter set. To change the filters click on the Filter icon, this brings up the Define Object Filter dialog
as shown in figure
n Selected object only (no descendants): will learn only the top-most or the window we have activated
n All object types will capture all the objects from the application. This option should be used cautiously as it could create
many unwanted objects in the OR. This option also increases the size of the Object Repository so when there is a
better approach available, this option should be avoided.
n Selected object types let you customize the filter. Pressing the select button after the selecting the radio button
launches the "Select Object Types" dialog. This is a better and a more strategic way of adding target Test Objects as
opposed to the previous approach.
Page 26 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
In this dialog we can filter which objects we want to be picked and which ones we don't.
Note Navigate and Learn can makes things easier by adding all the objects at once but if not used cautiously, it can
also create a lot of unwanted objects in the SOR. This is not a good approach in case the screen has lot of
controls and our scripts only covers few of them. In such a case it is better to add this manually.
Highlighting the object in Application can be done by selecting the object in OR and clicking the highlight button. This
will highlight the object in application. If QTP is not able to identify the object then it will raise one of the two possible errors
as shown in Figure 29-25 and Figure 29-26.
n The first error is due to the fact that properties used for identification are not sufficient to identify any object in the
application.
n The second error occurs due to multiple matches of the target object from the current description. In this case, we
should add one of the ordinal identifiers to make the match unique or we should add additional relevant properties to
make the match unique.
Page 27 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note If QTP is not able to identify an object then it doesn't mean that identification properties of that object are wrong.
There is a possibility that QTP is not able to identify one of the parent objects in the hierarchy correctly. So one
should check the entire hierarchys to make sure that rest of the objects in the hierarchy are being identified
correctly.
Warning If QTP highlights the object correctly and the Smart Identification is enabled for the object, then there is a
possibility that QTP might have used Smart Identification for identification. In such cases, your script can throw
an error if Smart Identification is disabled. To make sure that object is being highlighted correctly always set
the Smart Identification for the object as False and then try to identify the object again.
We can also locate if a given object in the application is already present in the OR. To locate an existing object click on the
Locate in Repository button and then click on the object using the Hand pointer. If object already exists in the OR,
then QTP will locate and activate the same in the object tree. Otherwise, QTP will raise an error as shown in Figure 29-27.
In case an object got changed after adding it the OR we can update the properties again by clicking on the Update
from Application button
Warning We can update an object of the same object type though it might not be the same object we had earlier. Ex –
An existing textbox for username can be updated with properties from a password textbox. This would create a
object with logical name as username but would have the identification properties as that of a password
textbox.
Page 28 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
As mentioned earlier, QTP uses LOR objects first and then the SOR object. Consider a LOR shown in Figure 29-28 and
SOR shown in Figure 29-29. Both the ORs have a common root object "Microsoft Word". The only difference being the
value of regexpwndclass property. The SOR has an object named "Microsoft Word Document" as the child of the
"Microsoft Word" object. Now when we use the below statement
Page 29 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The definition/identification properties of the "Microsoft Word Document" object will come from the SOR. But the
definition/identification properties of the object "Microsoft Word" will come from the LOR
Warning When using SOR only approach if the parent object gets added to the LOR by mistake then it can interfere
with correct object identification.
Object repository parameters (ORP) can be used to add parameters to the SOR. These parameters can be used for
configuring the property values. To launch the ORP dialog go to Tools→Manage Repository Parameters… and it will show
the ORP dialog as shown in Figure 29-30
Clicking on the "+" button launches the "Add Repository Parameter" dialog as shown in Figure 29-31. In this we can
add the name of parameter and its default value.
Page 30 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Once the parameter is added we use it to map to the property values. To map parameter values click on the button in
parameter value or press CTRL + F11
In Configure value dialog map the value to Repository parameter as shown in Figure 29-33
Note In SOR we can't directly map parameters to DataTable or Environment variable as we do in LOR that is why the
need of Object Repository parameter arises.
When a SOR with object repository parameter is associated to the test, the object repository parameters are available for
mapping. In case there is no default value associated with a repository parameter it would be shown in the missing
resources tab as "unmapped repository parameters".
The mapping of parameters can be done for Entire Test or at Action level. The mapping can be done to a DataTable
Page 31 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
parameter or Environment variable or a Random Number. We can also do this mapping at Run-time using the Repository
utility object
Print Browser("KnowledgeInbpx").GetTOProperty("title")
Note Value changed using Repository object in code will have effect for the whole test. The value doesn't change to the
default value from one action to another action.
Page 32 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Warning One huge limitation of using Repository parameters is that we can't specify the value as a regular expression
pattern. I am not sure how HP missed this but this feature is not available with parameterize values in OR.
SOR can be exported as XML in a QTP defined format. The XML format is documented in QTP help file under the topic "
HP QuickTest Professional Advanced References > HP QuickTest Professional Object Repository Schema". To Export the
SOR go to File→Export to XML…
The exported SOR can be re-imported again using the File→Import from XML… option
Note Exporting and re-importing the OR can at times reduce the size of the SOR and is a good way to compact the
same.
Note Exporting SOR to XML includes CheckPoint information only in case of QTP 11. This is not true in case of QTP
10 or lower.
Note Importing the XML always creates a new SOR and doesn't merge the object with existing SOR.
We can merge objects from an existing test to the current SOR. Go to Tools→Update from Local Repository… in the menu
and click on the button to select the test. Once the test is selected the dialog shows all the Actions available in
the test
Page 33 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Note Multiple tests can be selected in the Update from Local Repository dialog.
Note Only those Actions from the test can be added to list which have the SOR associated in the tests. So if a Test has
two actions: Action1 and Action2, but the current SOR is only associated with Action1 then the dialog would only
show Action1 and not Action2.
Note Repositories for a Test which is currently open in QTP IDE cannot be merged without closing the test.
Clicking on the Update All… button shows the Merge window and Merge results
Page 34 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Click on the button to save the merge and move to the next merge. The merge dialog will ask for a confirmation
before saving the merge
Warning The merge process deletes all the objects from the LOR of chosen scripts. Only those actions get impact
which were shown in the Update from Local Object Repository Dialog.
There are 2 types of conflicts that can occur during the merge process
Description Conflict – In this case 2 objects with same hierarchy have different description. The resolution would either to
take the description from LOR or SOR or Keep both the objects
Page 35 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Duplicate Objects Lason-2013; In this case a duplicate object exist. The resolution would be either to keep the LOR or
SOR object or both the objects
Warning Choosing 'Keep both objects' option could mean that your scripts may not work as the object description
would have changed. In case the number of scripts used by a shared object repository is high the merge
process should be avoided as the logical name changes during the merge process can break the scripts.
Page 36 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Object Repository Merge tool allows merging multiple object repositories into one. To launch the tool go to Tools→Object
Repository Merge Tool… and the "New Merge" dialog will show up. Select the object repositories to be merged and press
Ok. Merge tool shows the merged repository and if there re any conflicts they can be resolved in a similar way as we did
earlier.
Note One huge disadvantage of the merge process is that the merge cannot be saved on to the primary file and has to
be saved to a new file. So in case we want to merge 10 object repositories, we will have to save merged OR to
new OR every time and then use it as a primary OR for the next merge. This poor design of merge process makes
it impractical to use such approach in real projects.
Note In case of merge the object are NOT delete from the secondary file unlike the "Update from Local Repository…"
option.
Note Checkpoints can never be added directly in a SOR. They can only be imported through a direct merge or indirect
merge from local object repository.
Object Repository Comparison tool can be used to compare two object repositories. To launch the tool go to
Tools→Object Repository Comparison Tool…
Page 37 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Comparison Results
Local OR Vs Shared OR
LOR versus SOR has always been huge topic of discussion. LORs can be used in cases where the test scripts being
created for Automation have unique flow and don't have objects in common. They can also be used in cases of use and
throw scripts. Ex – Data creation scripts which are only used once and after a huge set of the data is created the script is
no more required. In such cases to keep things simple one can go for recording and use the LOR.
Page 38 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Object Spy
The QTP 11 Object Spy displays test object properties when the mouse cursor is placed over a GUI object. This allows
interrogating multiple objects in a single spying session by just pointing the cursor at the objects of interest. QTP 11 also
introduced few new features in Object Spy which allows adding the object directly from the Spy window to the Object
Repository as shown in Figure 29-46. A new copy button also allows you to copy all the Identification properties in the list
view on to the clipboard.
Note Sometimes QTP does spy the object through Object Repository Add Object button but doesn't add the object to
the OR. In such a case one should try adding the object directly from the Object Spy.
Page 39 / 39
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
The DotNetFactory object itself only provides a single method, CreateInstance, used to create a specific .NET object
instance. CreateInstance is the default method so we do not need to use its name explicitly when we create a new .NET
object:
CreateInstance also supports a third optional parameter, ParamArray, which is used to pass an unlimited number of values
to the specified object' class Constructor when required.
Some class constructors require passing objects as parameters. Consider the following code:
The code given above creates an ImageFormat .Net object. But attempting to execute this code throws the following error:
When we inspect the constructor for the ImageFormat class in .NET documentation, it mentions:
The constructor takes a GUID structure object. The problem of passing a GUID object to the above function is that the
GUID is .NET structure and not a class. With the DotNetFactory we can only create .NET classes and not the structures.
But we know that an object can always be set to 'Nothing'. Now we can pass a dummy parameter equal to 'Nothing' to
create the ImageFormat object:
When we pass a parameter to a .NET object, .NET will search for the function/property whose definition matches the
passed data type. Consider the following code:
Page 2 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This error occurs because Password Char property expects a .Net character parameter and we are passing it a VBScript
string parameter. There are two possible workarounds for this issue.
Method 1
'Set the password character. Use Asc to get the int code of *
'And then use CByte to convert it to a Character
oTextBox.PasswordChar = CByte(Asc("*"))
Method 2
Another method is to use a .NET Convert object method to convert the VBScript string to a .Net character:
Passing Enums
The following code in a .NET module displays a .NET form on the center of the screen:
But we can't use this code in QTP because we do not have access to the FormStartPosition. CenterScreen .NET constant.
To develop a solution we need to see how the Enum FormStartPosition is defined in .NET:
Now that we know that the CenterScreen constant has a Value 1, we can try to execute the following code in QTP to
assign the StartPosition:
Const CenterScreen = 1
oForm.StartPosition = CenterScreen
But attempting to execute the code given above throws the following exception:
Page 3 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
This exception occurs because in .NET everything is an object and that includes enum values. So when we attempt to
assign a numeric value, the conversion from numeric to enum object does not occur and hence we get an exception. But
we can use a workaround here; we know that everything is an object in .NET which means if we use the StartPosition
property on right side of an assignment we get the needed Enum object:
The above technique works by first getting the StartPosition object which is of Type System.
Windows.Forms.FormStartPosition. So whenever we need to pass a .Net enum object to a function, we should try to find a
property that is a child of another object which returns the required data type.
.Net arrays are not similar to QTP arrays, and therefore can't use functions like Ubound or LBound with them. They also do
not support the 'For Each' iteration construct either.
The last two statements, which fail to access array values demonstrate that we cannot enumerate the .NET arrays in the
typical manner in QTP. To successfully access .Net array elements, we need to use the array' .Net Enumerator object as
follows:
Page 4 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
So far we have discussed solutions for some of the commonly faced issues when DotNetFactory is used. Now we will look
at some additional examples and explore various .NET classes.
Page 5 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Ping an IP Address
Before discussing the code to ping an IP address, let' first explore the IIf function, which reduces the lines of code we need
to evaluate several If/Else conditions:
The remaining examples in this chapter will use the 'IIf()' function without further comments.
The code given above checks the status of various keyboard Control keys, which can prove useful in the different testing
scenarios. For example, if the CTRL key is kept pressed during the start of a test we can a take special action like setting
an internal DEBUG flag to either True or false, or ask for the data input from a user etc.
Page 6 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
With arrArray
'Add few elements
.Add "e"
.Add "b"
.Add "c"
.Add "a"
.Add "d"
.Sort
Print "Index of A after Sorting array - " & .IndexOf("a")
.Reverse
Print "Index of A after reversing array - " & .IndexOf("a")
Index of A - 3
Index of A after Sorting array - 0
Index of A after reversing array - 4
Value at index 1 - d
x = Stack.Pop
'Prints Varun
Print x
x = Stack.Peek
'Prints Tarun
Print x
x = Stack.Pop
'Prints Tarun
Print x
Page 7 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Queue.Enqueue 1
x = Queue.Dequeue
'Prints Tarun
Print x
x = Queue.Peek
'Prints 1
Print x
x = Queue.Dequeue
'Prints 1
Print x
'GMTTime
Print "GMT Time (MM/dd/yyyy hh:mm tt) - " & DateTime.Now.ToUniversalTime.
toString("MM/dd/yyyy hh:mm tt")
'Current Time
Print "Date (dd-MMM-yyyy) - " & DateTime.Now.toString("dd-MMM-yyyy")
Print "Date (dddd, dd-MMMM-yyyy) - " & DateTime.Now.toString("dddd, dd-MMMM-
yyyy")
Print "DateTime (dd-MMM-yyyy hh:mm:ss tt) - " & DateTime.Now.toString("dd-MMM-
yyyy hh:mm:ss tt")
Set DateTime = Nothing
The code given above produces the following output on my machine
We earlier saw how to send emails from QTP using the Outlook COM object in the "Working with Outlook" chapter.
Outlook has security issues wherein security warning popups whenever the code attempts to send a mail or read email
addresses. We will now see how to send an email in QTP which does not produce any security warning dialogs.
We do this by first creating a .NET MailMessage object and then populating it with the necessary details:
Page 8 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Once the MailMessage object has been constructed we can send the message using a SmtpClient object as shown in the
following code:
oSmptClient.Host = "smtp.nowhere.com"
oSmptClient.Port = 25
We can also use a simpler and shorter technique to send a single recipient a plain text email message using the following
code:
We can also set the priority of the email to high using the following code:
Converting a file from one format to another is a simple task using .NET objects described in this section:
Dim oImage
'Clean up objects
Set oImage = Nothing
Set oImageLib = Nothing
Set oImageFormats = Nothing
End Function
Page 9 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
newFileExtension = GetFileExtension(lcase(fileName))
To do the conversion of the source image this function first loads it and then does the conversion based on the destination
filename extension. Following is an example showing how to use these functions:
We can create and then display a .NET form using the following code:
Page 10 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
With oForm
'Title of the form
.Text = "Enter environment details"
.Show()
The code given above creates and then displays a .Net form in the center of the screen for 5 seconds and then closes the
form. But to obtain user input from the form we need to display the form until the user has entered some data. To do this
we use the ShowDialog method instead of the Show method. The ShowDialog method displays the form as a modal dialog
and inhibits QTP code execution until the form is closed. We create controls on the form using .NET classes and add them
at run-time. But since we are not executing in a pure .NET environment we cannot handle form events, like adding a button
and then responding to its click event. So the only option available to us is to add the needed controls and let the user
close the form after they have added the requested data.
The following code creates a form which requests a user to enter a login name, password and environment:
Page 11 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
deltaHeight = 30
'Create an input text box object for the requested user name
Set oTxtUserName = DotNetFactory("System.Windows.Forms.TextBox","System.Windows.Forms")
'Create a Label for the requested Environment and set its properties
Set oLabelEnvironment = Dotnetfactory("System.Windows.Forms.Label","System.Windows.Forms")
With oLabelEnvironment
Page 12 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
.Text = "&Environment:"
.Size = GetSize(labelWidth, controlHeight)
.Location = GetPoint(lStartX, StartY)
.TabIndex = 4
End with
With oLstEnvironment
'Name the list box
.Name = "1stEnvironment"
.Size = GetSize(controlWidth, controlHeight)
.Location = GetPoint(lStartX + cDelta, StartY)
.TabIndex = 5
With oForm
'Title for the form
.Text = "Enter environment details"
.Controls.Add oLabelPassword
.Controls.Add oTxtPassword
.Controls.Add oLabelEnvironment
.Controls.Add oLstEnvironment
Page 13 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
The code given above creates a dialog as shown in the Figure 30-1
Note This method is not preferred over the user input method discussed in the "Working with Internet explorer" chapter,
because the IE approach is simpler and faster.
Page 14 / 14
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Design Guidelines
This section covers different desirable requirements of a good framework design‥ This may not be an exhaustive list for
all the project needs; we can add or remove more requirements as the need arises
Selection of a Framework
n Data Driven framework – It is used when flow of the application remains constant, only the data changes. The data is
provided by external medium e.g. - excel sheet, XML etc…
n Keyword driven framework – This framework provides generic keywords that can be used with any type of
application. It also provides abstraction from the type of automation tool used and the type of application being tested,
e.g. - it can test a similar Web and Windows application with the same test case
n Hybrid framework - A hybrid framework is the one which takes advantage from both Data Driven and keyword driven
frameworks. These frameworks do not implement generic keywords but implement business logic keywords based on
the application being tested. For example – Login, Logout could be application specific keywords that can be used
Don't Reinvent the Wheel
A framework should try and use the power of the automation tool rather than re-defining the whole language by
implementing new keywords. Developing a keyword driven framework is time consuming and costly. A Hybrid framework
can be developed in a shorter time period and with less cost.
Reusability
The framework should allow highest possible reusability. Combining individual actions into business logic provides re-
usability. E.g. – Combing actions like "Enter username", "Enter password" and "Click Login" into one re-usable component
"Login".
A framework should allow re-use of baselines scripts in case different versions or flavors of an applications are to be
tested. There are two different ways to support different applications
n Copy and Modify –This method involves creating copies of the baseline scripts and modifying them for a specific
application version
n Re-use and Upgrade –This method involves re-using baseline script and providing an upgrade code for the specific
version of an application. This ensures maximum re-usability and should be preferred
Support of Script Versioning
Scripts should be stored in a version control system like CVS, Microsoft® VSS etc…This ensures recovery from any
disaster.
Different Environment for Development and Production
Automation should be considered as any other development project. Test scripts should be created and debugged in Test
environment‥ It should be deployed to the production environment after the testing is complete on the test environment.
This holds true for any emergency releases also
Page 2 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Externally Configurable
Configurable items of a script should be kept in an external file. This would contain configuration like Application URL,
version, path etc. This allows running the same script against different environment. Ensure that the location of the
configuration file is not hard coded. Hard coded files would allow running on any environment, but only one at a time.
Keeping the configuration relative to current test path allows overcoming this limitation
Self Configurable
Ideally a framework should be self configurable. Once deployed to a system, no manual configuration changes should be
required and scripts should automatically configure the required settings.
Minimal Changes Required for Any Object Changes
Most common issues faced during automation are object identification changes. Framework should be able to patch such
changes easily. This can be achieved by storing all object identification settings at a shared location. This could be an
external XML file, excel file, database or automation proprietary format. There are two possible way to load this object
identification configuration
n Static – In this all the object definitions are loaded into the memory at the start of the test. Any changes made to object
definition can only be loaded by stopping and re-running the test
n Dynamic –Object definition is pulled as per request. This approach is a bit slow as compared to the static one. But in
case of huge scripts where the fix needs to be made at run-time this approach is suitable
Execution
Framework might need to cater to the requirements (on need bases) given below:
n Execution of a test case/test batch based on result of another test case/test batch
There could be many other needs, based on the project requirement. A framework might not implement all of them, but
should be flexible enough to accommodate such requirements in future.
Status Monitoring
A framework should allow monitoring the execution status in real time and should be capable of sending alerts in the case
of failure. This ensures quick turnaround time in event of a failure.
Reporting
Different applications have different reporting needs. Some require combined results for a test batch and some require
individual level test report for each test case in test batch. The framework should be flexible enough to generate required
reports.
Minimum Dependency on Automation Tool for Changes
Some fixes can only be made by opening the script in the automation tool and then saving it. Scripts should be developed
in such a way that modification is possible even without the unavailability of the automation tool. This deflates company
cost by reducing the number of licenses required. It also allows anyone to make changes to the script without having the
need to setup the tool.
Easy Debugging
Debugging takes a lot of time during automation and hence special care needs to be taken for this part. Keyword driven
frameworks which use external data source, like an Excel Spreadsheets to read and process script keywords might be
difficult to debug.
Logging
Page 3 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Log generation is an important part of execution. It is very important to generate debug information at various points in a
test case. This information can help find the problem areas quickly and reduce the time to make the bug fixes at the same
time.
Easy to Use
The framework should be easy to learn and use. It is time consuming and costly to train the manpower on a framework. A
well documented framework is easier to understand and implement.
Flexible
Framework should be flexible enough to accommodate any enhancements without impacting existing test cases.
Impacts on Performance
A framework should also consider its impacts on the overall performance of the automation scripts. A complex framework
which increases the load time or the execution time of the scripts is never desirable. Techniques like caching, compiling all
libraries into a single library during execution etc. should be used to improve performance whenever possible.
Framework Support Tools
External Tools can be developed to perform tasks that help in framework design. Some example tasks would be
Coding standards ensure scripts that are consistent, readable and easily maintainable. Coding standard should define all
the things listed below
n Naming convention for variables, subs, functions, file names, script names etc. Ex – i_VarName for integer,
fn_i_FuncName for function returning integer
n Library, subs, functions comment header. This should include information like version history,, description, parameters,
example(s), created by, last modified by, last modified date etc
QTP Examples
This section discusses implementation details of the few design guidelines discussed earlier. The implementation would be
based on automation tool HP QuickTest Pro 9.2
Reusability
Page 4 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Function LoginDef()
'Call using the default parameters
LoginDef = Login (DataTable("UserName",dtGlobalSheet), _
DataTable("Password",dtGlobalSheet))
End Function
n AppName_PageLogin_Logi –This function is what does the actual job. The naming convention for this is followed in
such a way that it is easy for a developer to locate the code
n Login –This function is a wrapper around AppName_PageLogin_Login and allows an English based keyword for
implementation
n LoginDef –Most of the time, a script would call Login with parameters being taken from the same location. To increase
reusability we make a LoginDef function which knows which location to pick the parameters from. This allows us to
modify all scripts at the same time by just modifying the LoginDef function. It also gives flexibility to directly call Login
when parameters are not to be taken from the default location
This can be achieved by using concepts of Override Files. An Override File is loaded just before the start of the test. This
Override File would contain any changes to the old functionality in addition to the new functionality.
For example – In QTP we load Override Files using the code given below
Dim filesOverLoaded
filesOverLoaded = False
Const MAX_FOLDERLEVEL = 3
Do
Set allFiles = oFolder.Files
If iFolderCount > MAX_FOLDERLEVEL Then
Exit Do
End if
iFolderCount = iFolderCount + 1
Page 5 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Externally Configurable
Now this APP_URL can be defined in an External XML file, which is loaded at run time
Logging
Self Configurable
A self configurable framework would make sure that all configurations needs for a script to run correctly would be done
automatically by the script itself. Let see two different examples for the same
Our script might be using a 3rd party library which if not installed on destination system would fail the script. To make such
scripts self configurable, check if the object can be created or not, if not then register the DLL file on the current system
and create the object. The code given below, demonstrates the same
Page 6 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
End If
End If
Some application launch popup and IE popup blocker might block them up. In such a case before launching the application
we should make sure that Popup blocker is disabled. This can be done through disabling the same in the registry.
Page 7 / 7
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QTP 9.x comes with external QTP Script Editor which allows editing multiple QTP test scripts and libraries externally. It
lists all the functions available in the currently open library as shown in the Figure 32-1
VBSEdit
VBSEdit is another popular VBS file editor which has the following salient feature
n Intellisense for COM object created using CreateObject, and also for the user defined classes
n List available classes and methods available in the script as shown in the Figure 32-2
Page 2 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Notepad++
The editor has the following key features for the QTP users
Page 3 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
QTP Uninstaller
Uninstalling QTP using the usual uninstall option from a system's control panel does not remove QTP completely. Many of
QTP keys are left in the system registry and cause issue while upgrading or re-installing QTP. The process of cleaning the
registry manually is a time consuming task and could be dangerous in case wrong keys get deleted. QTP Clean uninstaller
automates the process of deleting the information left in QTP registry even and also un-installing QTP and any of it's Add-
ins. It deletes all the traces of QTP from the system for doing a fresh install, as shown in the Figure 32-4.
Page 4 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
ScreenCapture API
ScreenCapture API from KnowledgeInbox is a COM library developed in .NET which can be used to:
n Capture complete web pages in Internet explorer, including the invisible screen areas using vertical and horizontal
scrolling screen captures.
Cookies are used by websites to store information on a client machine, they are of 2 types, Persistent and Non-Persistent.
Persistent cookies are stored on the machine as files and can be cleared by deleting the files. Non-Persistent cookies are
stored in the browser memory and are cleared only when the browser is closed. Non-persistent cookies might prevent
using the same browser for different logins.
KnowledgeInbox IE Session Cookies Helper can be used to delete the non-persistent cookies from a running IE browser
without closing it. The COM API library is available on my website at the link given below
http://KnowledgeInbox.com/downloads/general
QTP provides extern object for declaring Windows API, but converting normal Windows API definitions to QTP extern
declaration statements can take a good amount of time. This tool can be used to convert VB API definitions to QTP Extern
declarations as shown in the Figure 32-5
Page 5 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
IE WebDeveloper
IE WebDeveloper is an add-on for Microsoft Internet Explorer. The rich web debugging toolset allows you to inspect and
edit the live HTML DOM and current cascaded styles, evaluate expressions and display error messages, log messages,
explore source code of a webpage and monitor DHTML Event and HTTP Traffic.
The tool allows QTP developers to look at the DOM tree of the webpage and see how to access an object on the page in
QTP. The tool is available as a 14 days trial version on
http://www.ieinspector.com/dominspector/
WebPage Inspector
WebPage Inspector tab allows viewing the tree DOM structure of the webpage and also allows selecting an object in the
hierarchy by clicking anywhere in the document as shown in the Figure 32-6. Object style information can also be viewed
in this tool.
Page 6 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Script Console
Script console allows evaluating JScript expression on the current web page. It is useful when trying to explore various
DOM object options that can be used in the QTP code.
I won't be discussing the rest of the features of this tool as they are not needed in respect with QTP.
TDS is the enhanced IDE for WinRunner and QTP, a product of Patterson Consulting, LLC. It provides a Visual Studio
style editor which provided enhanced code editing experience. This review will walk you through some of the key features
of the TDS
The tool has many features. Some of them are listed below
n Solution - A solution allows you to group various types of files into one solution. This includes QTP, WinRunner, VBS,
text, ini etc…
n Expand/Collapse functions
n Smart Indentation
n Track Modification
n Split Windows
n Enhanced Intellisense - TDS provides Intellisense for almost everything. It provides Intellisense for all QTP object even
when the machine does not have QTP installed. This allows automation developers to easily code there scripts on any
machine without being dependent on QTP. TDS also provides Intellisense on COM libraries available to be used with
the CreateObject function.
n Object Browser - Object Browser provides an easy reference to all the methods and properties available for a
class/library in the current solution.
n Quality Center Support - TDS allows adding different quality center servers. Once the server is added, you can access
any of the projects to which you have access.
Page 7 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
n Inbuilt Browser
RAD Software Regular Expression Designer is a free tool that helps programmers learn, develop and test Regular
Expressions. It is an interactive Windows application that is designed to be simple and easy to use. The tool is available at
following location
http://www.radsoftware.com.au/regexdesigner/
The tool can be used to test a regular expression that may be needed in QTP to identify an object or match a pattern.
Figure 32-8 shows how to match a date pattern in a string using the tool
Page 8 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Page 9 / 9
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
Appendix A
Problem 4-1. How to access a parameter from the global data sheet 38
Problem 4-6. How to export contents of a WebTable to a data sheet. Let's assume that the first 39
row of the data table contains the columns heading. We then add those as parameters of the data
table:
Problem 4-7. How to get value of a parameter from any specific row in the data table 40
Problem 4-8. How to execute a script for all Global Data Table iterations, when the script is set 41
to run for only one iteration:
Problem 4-9. How to get the number of columns that contain data: 41
Problem 6-5. How are QTP record and run settings changed using Environment variables? 55
Problem 6-9. How are environment variables loaded from an external XML file? 58
Problem 8-1. How can we check if a checkpoint passed or failed? 70
Problem 12-1. How can we get the status of an Action as Pass/Fail at the end of the action?
108
Problem 13-1. What will the regular expression be for a domain which can have possible value
of "test.app.com", "qa.app.com", "www.app.com" 120
Problem 13-2. What will be the r.e. matching a date in the format MM/DD/YY?
120
Problem 14-1. How can we find the current page and the total page values from the string "Page
4 of 15"? 131
Problem 14-2. How can we count the number of "if" phrases in the "if + if = 2 if" string?.
131
Problem 14-3. Given a complete file path specification, extract the filename, file path and drive
letter from the specification 133
Problem 14-4. Let's revisit the page number extraction problem again. How can we find the
current page and the total page values from the string "Page 4 of 15"? 134
Problem 14-6. How can the number of business/working days be calculated between two dates
(i.e. difference should exclude the weekends)? 139
Problem 14-9. Write a function that reads a string word by word where two words would b
separated by one or more spaces 144
Problem 14-10. Create a function TrimAll which trims not only spaces but other whitespace
characters like new lines, carriage returns, and line feeds etc.: 144
Problem 14-11. Create a FilterStr function which takes a string and character set as input and
will filter the string based on the characters in the character set 145
Problem 14-12. Create two functions, one which returns the path portion and another the file
name, when passed a fully qualified path or filename: 146
Problem 14-13. Write a function that compares two string ignoring new line, line feeds, tab etc.
whitespace characters: 147
Problem 14-14. Write a function that replaces repeated occurrences of a given character by
another character. 147
Problem 14-15. How can we get the UBound/LBound values of multi-dimensional array?
149
Problem 14-16. How can we declare and initialize a read only variable at run-time?
150
Problem 17-1. How can we determine if the topmost window on the desktop is a browser
window? 178
Problem 17-2. How can we get the value of a Windows Environment variable? (Note that QTP
environment variables differ from Windows environment variables) 178
Problem 17-3. How can we check (select) an item in a List box using a Windows API?
178
Problem 17-4. How can we get the background color of a text box (helpful when a color for a
mandatory field is different than an optional color)? 179
Problem 17-5. How can we simulate a keyboard event using the Windows APIs?
179
Problem 17-6. How can we prevent a PC from being locked by its screen saver?
181
Problem 18-1. How can we use AOM to run a QTP test case?
195
Problem 18-2. How can we use AOM to change the starting and ending iterations for a test
case? 196
Problem 18-3. How can we use AOM to launch QTP on a remote machine?
198
Problem 21-1. How can we copy an XML file and save it to another XML file?:
238
Problem 21-2. How can we get an entire XML file into a string and then save it to another XML
file using that string?: 239
Problem 21-3. How can we create the following XML code at run-time in QTP, and then save
ittoanXML file?: 239
Problem 21-4. How can we load environment variables from multiple XML files?:
240
Problem 21-7. How can we extract XML from a URL or Web browser?
244
Problem 21-8. How can we compare two XML documents for equality?:
244
Problem 21-9. How can we compare two xml file with different ordering of nodes?:
244
Problem 22-2. How can we determine the number of rows altered by an update or a delete
query?: 254
Problem 23-2. How can we create a new excel sheet and then save it?
260
Problem 23-3. How can we determine if an Excel file exists, and if not, how to create one?
261
Problem 23-4. How can we access all non-blank row values in a specific column?
262
Problem 23-5. How can we search for a text string and then update another cell's value in that
row? 262
Problem 23-6. How can we use an Excel sheet as a QTP output Data Table?
263
Problem 23-8. How can we access an Excel spreadsheet embedded in Internet Explorer?
268
Problem 25-5. How to get reference toan already existing word document?
293
Problem 25-6. How to open a word document in the read only mode?
294
Problem 25-8. How to insert text into a word document from a pre-defined style?
294
Problem 25-9. How to insert an image in a word document and scale its size by 50%?
295
Problem 25-10. How to find and replace some text in a word document?
295
Problem 25-12. How to change the font for the text being written in a word document?
297
Problem 25-13. How to preserve the text already present in a word document while writing?
298
Appendix B: Index
A
Actions 43
Input and Output Parameters 43
Insert Call to Copy… 49
Insert Call to Existing… 48
Insert Call to New… 47
actionsspath 349
AddAttachment 337
AddParameter 40–41
AddSheet 40
ADODB.Command 249, 253, 255
ADODB.Connection 249
ADODB.Recordset 249, 252
Advanced Text Checkpoints 354
API using COM Objects in VB6 182
API using Excel 185
ApplyXSL 245
Array 134
Asc 137
Automation Object Model (AOM) 195
Index
B
Browser Vs Page Sync 159
Index
C
CBool 137
CByte 137
CCur 137
CDate 137
Check 70
CheckBrokenImages 320
Checkpoints
Alternatives to QTP checkpoints 71
Types of checkpoints 69
Updating Checkpoints at run-time 71
ChildObjects 86
Chr 138
CInt 137
CleanBrowserPopups 316
CleanText 147
CLng 137
Page 2 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
CloseDescendentProcesses 65
CloseProcessByHwnd 65
CloseProcessById 65
CloseProcessByName 65
CloseProcessByWndTitle 65
Comparing XML 244
Converting a DOM object to QTP Test Object 208
Converting VBA to VBScript 264
CreateDescription 85
CreateObject 142
CreationTime 90
Crypt Object 61
CSng 137
CStr 137
CurrentRun 329
currentStyle 209
CurrentTest 329
CurrentTestSet 329
CurrentTestSetTest 329
Index
D
Database 249
Data Table 33
Data table formatting 38
Data table object model 38
Design time data table 35
Run-time data table 35
Setting data table iterations 36
When to use the global or a local data table 35
Date 138
DateDiff 139
Day 138
Debugging 97
Using Breakpoints 98
Working with the Command Tab 100
Working with the Variables Tab 99
Working with the Watch Expression Tab 98
DefaultObjRepType 349
DefaultTSRFilePath 349
Descriptive programming 83
Browser identification Issue 93
Browser Identification using a unique OpenURL
Property 93
Browser identification using OpenTitle 93
Converting an OR-based script to a DP-based script 87
Enumerating ChildObjects 86
Implicit Properties 84
Problems with Ordinal Identifiers 90
Page 3 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Index
E
Encrypt 61
EnumerateAllTestSets 340
EnumerateAllTestsinTestPlan 339
EnumerateSettings 347
Environment variables
BROWSER_ENV 55
ExternalFileName 52
LoadFromFile 52
URL_ENV 55
Value 52
Error Handling 113
Eval 150
Excel.Application 142, 187, 188, 260, 264, 353, 359
Excel Automation Object Model 259
Execute 57, 85, 149
ExecuteFile 76
ExecuteFileGlobal 77
ExecuteGlobal 78
ExecuteGlobalCode 78
Page 4 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Index
F
Filter 137
FilterStr 145
FindAttachment 334
FindWindow 190
FindWindowEx 190
FireEvent 160
FirstGlobalIteration 348
Fixed length arrays 148
Index
G
GenericSet 66
GetAddressesFromMail 285
GetBusinessDays 140
GetColumnName 271
GetCurrentTestPath 338
GetCurrentTestSetPath 341
GetCursorPos 185
GetDC 179
GetDOMObjectByPath 211
getElementsById 204
getElementsByName 204
getElementsByTagName 204
GetEnvironmentVariable 178
GetFileName 146
GetFilePath 146
GetForegroundWindow 177, 178
GetIECOMByhWnd 305
GetIECOMByURL 305
GetIEObjectFromhWnd 268
Page 5 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
GetObject 142
GetParameter 40
GetParentOfElement 224
GetPixel 179
GetRandomNumberByLen 306
GetROProperty 14, 23
GetRowCount 41
GetSheet 39
GetSMTPAddress 286
GetStrBetweenChar 143
GetStrFromChar 143
GetSubFolderByPath 277
GetTOProperties 22
GetTOProperty 23
GetVarXML 54
GetWindowDC 179
GetWordFromPos 144
GlobalIterationMode 348
GlobalSheet 38
Index
H
Hex 138
Hour 138
HowManyWeekDays 139
HTML Button 205
HTML Checkbox 206
HTML ComboBox 205
HTML Element Collection 203
HTML Element Object 203
HTML Link 205
HTML List Box 205
HTML Node 202
HTML Radio Button 206
HTML Table 207
HTML Text Box 205
Index
I
IEDownloadFile 318
InStr 130
InStrRev 132
Internet Explorer 301
Page 6 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
EnumerateIE 304
Popup Blocker 311
Using IE to get user input 308
InternetExplorer.Application 302, 303, 307
IsConnected 328
IsEnvExist 53
isParameterExists 39
IsRegEqual 123
Index
J
Join 134
JScript 363
Passing variable number of arguments to a function 364
Scope differences 364
Try…Catch block 365
Working with JS classes 366
Working with JScript Arrays 366
Index
K
keybd_event 179
KeyDown 180
KeyPress 180
KeyUp 180
Index
L
LastGlobalIteration 348
launchreport 349
Lcase 129
Left 130
Len 130
Library files 75
Associating a Library globally with a Test 75
Dynamically Loading libraries locally at run-time 76, 79
LoadFromFile 58
LocalSheet 39
LTrim 133
LTrimW 126
Index
M
MakeObjVisible 354
MapVirtualKey 179
Page 7 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
micclass 86
Mid 130
Minute 138
Modal dialog boxes 190
Month 138
Index
N
NewSync 317
Now 138
Index
O
Object Identification 27, 83
Object Spy 25
ObjRepType 348
Oct 138
On Error Resume Next 113
OnReplayError 348
Open Test Architecture (OTA) 330
Optional arguments in VBScript 150
Using an Array of (Key, Value) pairs 152
Using an Array of Key:=Value pairs 153
Using an Array of values 151
Using Null/Empty values 150
OptionalStep Object 62
Outlook.Application 276
Outlook Object model 275
Outlook Security Dialogs 282
Index
P
PathFinder.Locate 63, 336
PathFinder Object 62
PostMessage 190
Index
Q
QCUtil Object 328
Quality Center 325
ResolveRelativePath 327
QuickTest.Application 174, 195, 198, 331, 343, 344, 351
Index
Page 8 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
R
RandomNumber Object 63
Recovery_LoginProxy 109
Recovery object 111
RegExp 123
RegisterUserFunc Object 66
RegularExpression 23
Regular Expressions 117
ReleaseDC 179
Replace 133
ReplaceMultipleByOne 147
ReplayType 162
Reporter.Filter 166
Reporter.LogEvent 172
Reporter.ReportEvent 167
Reporter.ReportPath 170
rfDisableAll 166
rfEnableAll 166
rfEnableErrorsAndWarnings 166
rfEnableErrorsOnly 166
Right 130
RTrim 133
RTrimW 125
RunAction 45
Index
S
Scripting.Dictionary 77, 154, 155, 172, 175, 263, 304, 355, 360
Scripting.FileSystemObject 54, 167, 173, 174, 175, 246, 261, 335, 351, 353, 439
Seconds 138
SelectRadioByTextIndex 212
SendMessage 178
SetActiveWindow 190
SetCurrentRow 40, 41
SetForegroundWindow 179
SetSecure 62
Setting Object 63
SetTOProperty 23
ShowWindow 182
SnapshotOnErrorActiveUI 348
SnapshotReportMode 169
Space 134
Split 134
Page 9 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
SplitEx 135
StopAndReRunQTP 350
StrComp 129
String 134
StrReverse 130
Sync 157
Synchronization Points 157
SystemUtil Object 65
SystemUtil.Run 92
Index
T
TDAPIOle80.TDConnection 332
TDConnection 328, 330
Test Arguments 197
Test Results 165
Accessing Test Results at the end 173
Configuring QTP to generate HTML results 170
Converting XML Results to HTML 170
Inserting Files in Test Results 167
Inserting Snapshots in Test Results 168
Time 138
Timer 140
Trim 133
TrimAll 144
TrimW 126
TSRFilePath 349
TypeName 141
Index
U
UBound 149
Ucase 129
URLDownloadToFile 182
UseExternalDataTablePath 348
Useful Tools 443
IE WebDeveloper 447
Internet Explorer Session Cookies 447
Notepad++ 444
QTP Script Editor 443
QTP Uninstaller 445
RAD Regular Expression Designer 450
ScreenCapture API 446
Test Design Studio (TDS) 449
VB 2 QTP API Converter 447
VBSEdit 444
Page 10 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
User-defined Objects 28
Index
V
ValueByRow 40
VarType 141
Index
W
Wait 158
WaitProperty 158
WebRegSelectValue 124
Web Tables 217
Access using OR 222
Asynchronous Table loading 229
Clicking inside a WebTable 227
Exporting WebTable to a DataTable 229
Finding a cell in a Table 231
FindTextBySearch 232
GetTableFromElement 225
Getting a QTP Table from a element 230
Getting the location of an object inside the table 225
GetWebTableFromElement 230
Using an object inside the table 224
Using Index 219
Using innerText/outerText 219
Using Name or HTML ID 219
WebUtil Object 65
Weekday 139
WScript.Shell 174, 189, 193, 288, 301, 311, 315, 351, 439, 440
Index
X
XMLAttribute 238
XML Attributes 238
XMLAttributesColl 238
XML Child nodes 238
XMLData 238
XMLElement 238
XMLElementsColl 238
XMLItemColl 238
XML Node values 238
XML Root node 237
XMLUtil 238
XMLUtil.CreateXML 238
XMLUtil.CreateXMLfromFile 239
Page 11 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
QuickTest Professional Unplugged, Second Edition
Index
Y
Year 138
Page 12 / 12
Reprinted for OET7P/839411, Accenture KnowledgeInbox, Mercury Interactive (Israel) Ltd. (c) 2011, Copying Prohibited
List of Figures
Chapter 1: Introduction (Updated)
Chapter 4: DataTables
Chapter 5: Actions
Chapter 8: Checkpoints
Chapter 4: DataTables
Problem 4-1: How to access a parameter from the global data sheet
Problem 4-6: How to export contents of a WebTable to a data sheet. Let's assume that the first row of
the data table contains the columns heading. We then add those as parameters of the data table:
Problem 4-7: How to get value of a parameter from any specific row in the data table
Problem 4-8: How to execute a script for all Global Data Table iterations, when the script is set to run for
only one iteration:
Problem 4-9: How to get the number of columns that contain data:
Problem 6-5: How are QTP record and run settings changed using Environment variables?
Problem 6-9: How are environment variables loaded from an external XML file?
Chapter 8: Checkpoints
Problem 12-1: How can we get the status of an Action as Pass/Fail at the end of the action?
Problem 13-1: What will the regular expression be for a domain which can have possible value of "
test.app.com", "qa.app.com", "www.app.com"
Problem 13-2: What will be the r.e. Matching a date in the format MM/DD/YY?
Problem 14-1: How can we find the current page and the total page values from the string "Page 4 of
15"?
Problem 14-2: How can we count the number of "if" phrases in the "if + if = 2 if" string?
Problem 14-3: Given a complete file path specification, extract the filename, file path and drive letter
from the specification
Problem 14-4: Let's revisit the page number extraction problem again. How can we find the current page
and the total page values from the string "Page 4 of 15"?
Problem 14-6: How can the number of business/working days be calculated between two dates (i.e.
difference should exclude the weekends)?
Problem 14-9: Write a function that reads a string word by word where two words would be separated
by one or more spaces.
Problem 14-10: Create a function TrimAll which trims not only spaces but other whitespace characters
like new lines, carriage returns, and line feeds etc.:
Problem 14-11: Create a FilterStr function which takes a string and character set as input and will filter
the string based on the characters in the character set.
Problem 14-12: Create two functions, one which returns the path portion and another the file name,
when passed a fully qualified path or filename:
Problem 14-13: Write a function that compares two string ignoring new line, line feeds, tab etc.
whitespace characters:
Problem 14-14: Write a function that replaces repeated occurrences of a given character by another
character.
Problem 14-15: How can we get the UBound/LBound values of multi-dimensional array?
Problem 14-16: How can we declare and initialize a read only variable at run-time?
Problem 17-1: How can we determine if the topmost window on the desktop is a browser window?
Problem 17-2: How can we get the value of a Windows Environment variable? (Note that QTP
environment variables differ from Windows environment variables).
Problem 17-3: How can we check (select) an item in a List box using a Windows API?
Problem 17-4: How can we get the background color of a text box (helpful when a color for a mandatory
field id different than an optional color)?
Problem 17-5: How can we simulate a keyboard event using the Windows APIs?
Problem 17-6: How can we prevent a PC from being locked by its screen saver?
Problem 18-1: How can we use AOM to run a QTP test case?
Problem 18-2: How can we use AOM to change the starting and ending iterations for a test case?
Problem 18-3: How can we use AOM to launch QTP on a remote machine?
Problem 21-1: How can we copy an XML file and save it to another XML file?
Problem 21-2: How can we get an entire XML file into a string and then save it to another XML file using
that string?
Problem 21-3: How can we create the following XML code at run-time in QTP, and then save it to an
XML file?
Problem 21-4: How can we load environment variables from multiple XML files?
Problem 21-7: How can we extract XML from a URL or Web browser?
Problem 21-8: How can we compare two XML documents for equality?
Problem 21-9: How can we compare two xml file with different ordering of nodes?
Problem 22-2: How can we determine the number of rows altered by an update or a delete query?
Problem 23-2: How can we create a new excel sheet and then save it?
Problem 23-3: How can we determine if an Excel file exists, and if not, how to create one?
Problem 23-4: How can we access all non-blank row values in a specific column?
Problem 23-5: How can we search for a text string and then update another cell's value in that row?
Problem 23-6: How can we use an Excel sheet as a QTP output Data Table?
Problem 23-8: How can we access an Excel spreadsheet embedded in Internet Explorer?
Problem 25-5: How to get reference toan already existing word document?
Problem 25-6: How to open a word document in the read only mode?
Problem 25-8: How to insert text into a word document from a pre-defined style?
Problem 25-9: How to insert an image in a word document and scale its size by 50%?
Problem 25-10: How to find and replace some text in a word document?
Problem 25-12: How to change the font for the text being written in a word document?
Problem 25-13: How to preserve the text already present in a word document while writing?