Wednesday, February 23, 2011

Using environment variables in QTP

Environment variables can be used during automation testing to have global level variables or constants available all the time to all scripts or business components. This can be used as part of any kind of automation test framework used. It will be part of definition of the framework.


They are used for having a global value stored at the windows OS level. The environment variables can be viewed as follows (in a typical windows XP machine):
1. Go to Control Panel
2. Click on “System”
3. Go to “Advanced” tab and click on “Environment Variables” button.

The environment variables will be listed in two sections: a) User Variables and b) System Variables.

All the environment variables defined in the scripts will be stored as part of “User Variables” group.

This should be used minimally as this may be maintenance overhead. It would be hard to explain it to the executor or maintainer unless they are same as the script developers.

The following gives the code snippet to define and use the environment variables in a QTP script.

'-------------------Declaration Section---------------------
'Create the WScript.Shell object
Set objWshShell = CreateObject("WScript.Shell")
'-----------------------------------------------------------

'-------------------Usage Section---------------------
' Access the User Environment property

Set WshEnv = objWshShell.Environment( "User" )
DSPath = WshEnv(strEnvName)

'-----------------------------------------------------------

Thursday, February 17, 2011

Reading XML Attribute Values

Scripting to read the content from an XML could be tricky as there can be many ways suggested out there in internet to do the same task. This, I would say is due the different possible usages in MS VBScript language.

I had a situation where I had to automate a Sterling application which had an XML thrown out and I had to read it in QTP. The situation was like this.

The portion of output XML:
xml version="1.0" encoding="UTF-8" ?>

<Items totalItems="14">
 <Item itemID="12345">
    <InventoryInfo description="door paint">
        <AdditionalInfo ExtendedDescription="lunar mist" />
    </InventoryInfo>
</Item>
<Item itemID="54321">
    <InventoryInfo description="window tint">
        <AdditionalInfo ExtendedDescription="dark blue" />
    </InventoryInfo> 
</Item>
 </Items>


Here in the XML the data is actually within the attributes rather than as values associated with tags. So it becomes very important to read the attribute of each node for all the set of similar nodes in the XML.

I wrote a simple function to solve this:

Firstly in the main script or business component declare a scalar variable.
Dim itemArray
'note that I am not declaring it as a dynamic array with a (). see my previous post for more info on this

'get data to get the entire xml from the screen into a string
outputXML = Browser("browserName").Page("PageName").WebXML("itemXML").GetData
Set xmlObject = CreateObject("Microsoft.XMLDOM")

'select single root element to get total number of records
Set node = xmlObject.DocumentElement.selectSingleNode("//Items")
numNodes = node.GetAttribute("totalItems")
'---one way of getting an attribute of a single node

'now off to the array assignment to get all node attribute values into an array
pNode = "InventoryInfo"
cNode = "AdditionalInfo"
attributeName = "ExtendedDescription"
arraySize = numNodes -1
itemIDArray = fun_GetAttributesFromXML (xmlObj, pNode, cNode, attributeName, arraySize)


And here is the function:

Function fun_GetAttributesArray(xmlObj, pNode, cNode, attr, arrSize)
    Dim nodeList
    Dim numnodes
    Dim currentNode
    Dim iLoopIndex
    Dim attributeArray()


ReDim attributeArray(arrSize)
Set nodeList = xmlObj.DocumentElement.SelectNodes("//" & pNode & "/" & cNode)
numNodes = nodeList.Length
If numNodes > 0 Then
For iLoopIndex = 1 to numNodes
Set currentNode = nodeList.nextNode
attributeArray(iLoopIndex-1) = currentNode.getAttribute(attr)
Next
End If
fun_GetAttributesArray = attributeArray    
End Function

This function returns the attribute value of the cNode that is sent to this function from the entire XML.
The output with the above example will be an array returned by this function with values:
itemIDArray (0) = "lunar mist"
itemIDArray (1) = "dark blue"

Catch about Dynamic Arrays

I found a catch with arrays, dynamic arrays and scalar variables that we use in VB Script while working with QTP.

Lets start with dynamic arrays:
We declare dynamic array somewhat this way:

Dim myArray()

Before using a dynamic array, the QTP help clearly states under "array variables" that "To use a dynamic array, you must subsequently use ReDim to determine the number of dimensions and the size of each dimension"

So before assigning values to elements in the dynamic array ReDim it this way:
ReDim myArray(10)

After this, you can assign values to the elements of this array by accessing through subscript.

The Catch:
You cannot assign an array to a dynamic array directly by a simple equal statement. This often happens when you try to assign an array returned by a function to an array declared as a dynamic array.


Example 1:
Dim myArray()

ReDim myArray(10)

myArray = fun_functionThatReturnsAnArray(var1, var2)
'assuming that the function returns an array of size 10

This will result in a "Type Mismatch" error. The reason being that the dynamic array declared will have its every element of type "User Defined Type".

Solution: do not declare the array as a dynamic array. Declare it simply as Dim myArray and assign the return value of function to this in this way: 
myArray = fun_functionThatReturnsAnArray(var1, var2)


Example 2:
In the example 1, if you assign the array in the following way:

myArray() = fun_functionThatReturnsAnArray(var1, var2)

this will result in a "Subscript out of range: 'myArray'" error.

Solution: Do not use braces in the assignment statement.

Wednesday, August 18, 2010

QTP and the SQL Database

How often have you landed up in a situation where you are required to extract a value from database and compare it with a value on the screen? How often has it been the "only way" of validating the integrity of data on screen?

Well I have come across such need umpteen number of times. We can use QTP to execute a SQL query and process the results within a script/ business component. It is the powerful VBScript that enables us to execute database queries within QTP. So here is an example to showcase how a value from database is retrieved using QTP. This is something I used in many of my business components that interact with database.

My recommendation is to include this as a function in the library and design a different function that stores user id and password and other database security information. In this example everything is in the same function just to give a picture to the reader.

Dim Con, RS
Dim strUserId
Dim strPassword
Dim strServer
Dim strDataBase
Dim strSQL
Dim strConnectionString
Dim dbFirstValue
  
strUserId ="userID"
strPassword = "password"
strServer= "SQLServerName"
strDataBase= "databaseName"

Set Con  = CreateObject("adodb.connection")
Set RS = CreateObject ("adodb.recordset")
       
Con.Open strConnectionString
rs.open strSQL,Con
Do While Not RS.EOF
    dbFirstValue=RS.Fields(0).Value
    reporter.ReportEvent micDone,"FirstDBValue - ",dbFirstValue
    RS.MoveNext
    Exit Do
Loop
Con.Close

Monday, August 16, 2010

User Defined Functions

1.       If you have repeatable steps in a component, consider using a user defined function. User defined functions makes your component look shorter, easier to maintain, read and design. A user defined function stored in a function library can then be called from within a component.
2.       Functions can be written manually or can be created using QTP’s function definition generator. The screenshot below shows the generator with various options.
3.       To use an Option Explicit statement in a function library associated with your component, you must include it in all the function libraries associated with the component. If you include an Option Explicit statement in only some of the associated function libraries, QTP ignores all the Option Explicit statements in all function libraries.
4.       Each function library must have unique variables in its global scope. If you have two associated function libraries that define the same variable in the global scope using a Dim statement or define two constants with the same name, the second definition causes a syntax error. If you need to use more than one variable with the same name in the global scope, include a Dim statement only in the last function library (since function libraries are loaded in the reverse order).
5.       By default, steps that use user-defined functions are not displayed in the test results tree of the Test Results window after a run session. If you want the function to appear in the test results tree, you must add a Reporter.ReportEvent statement to the function code. For example, you may want to provide additional information or to modify the component status, if required.
6.       If you delete a function in use from an associated function library, the component step using the function will display the “?” icon. In subsequent run sessions for the component or business process test, an error will occur when the step using the non-existent function is reached.
7.       If another user modifies a function library that is referenced by a component, or if you modify the function library using an external editor (not QTP), the changes will take effect only after the component is reopened.
8.       When more than one function with the same name exists in the function library, the last function will always be called. To avoid confusion, make sure that you verify that within the resources associated with an application area or component, each function has a unique name.
9.       If you want to call a function from additional test objects, you can use the RegisterUserFunc option which is usually placed immediately after the function in question and replace any relevant argument values. It is recommended to include it in the function library so that the method will be immediately available for use in any component using that function library.
10.   You can re-register the same method to use different user-defined functions without first unregistering the method. However, when you do unregister the method, it resets to its original QTP functionality (or is cleared completely if it was a new method), and not to the previous registration.
11.   For example, suppose you enter the following statements:
RegisterUserFunc "Link", "Click", "MyClick"
RegisterUserFunc "Link", "Click", "MyClick2"
UnRegisterUserFunc "Link", "Click"
12.   After running the UnRegisterUserFunc statement, the Click method stops using the functionality defined in the MyClick2 function, and returns to the original QTP Click functionality, and not to the functionality defined in the MyClick function.

Saturday, July 17, 2010

Automation Strategy

Test automation strategy forms the most important stage in any project. It is always important to draw boundaries before hand since the scripting to provide solution can be endless. Some of the important points to consider in a strategy is:

1. Define beginning of testing of application.
2. Limit test data so that scripting complexity is reduced.
3. Handling of errors and different conditions
4. Last and most important - number of test cases to be automated.

These are some basic points to consider defining strategy no matter how experienced or how new you are as an automation engineer.

Next the automation details:
1. Automation approach
2. Automation deliverables
3. Estimation for analyzing, framework design, scripting, unit testing, integration testing and final suite delivery. Estimated maintenance effort for a regular period of time will be an added advantage to mention.

The remaining points to consider in strategy are in the interest of general testing which usually the test leads/ analysts will be interested in.
1. Prerequisites
2. Assumptions
3. Risks
4. Time line details
5. Environmental requirements/ details
6. Issues and other logs


The last portion of the strategy could be about the return on investment - which is a complex and subjective calculation. Every company/ project can calculate these on various methods and scales depending on how it is implemented and used.

Tuesday, November 17, 2009

Types of Automation Frameworks

The primary heads that govern the definition of framework are:

1. Automated Test case design – or the test case flows
2. Testing tool used
3. Test Data Supply and Volume
4. Test Management
    a. Test Scripts’ structure and their storage
    b. Test Case/ Script Creation
    c. Execution
    d. Error logging
5. Defect Creation
6. Crash Recovery Scenarios
7. Reporting Mechanism

All these activities have to be clearly defined and taken care of by one or the other tool with or without user intervention. Not in all kinds of applications have all these automated. Some may require to be done manually depending on the environment and budget for the project.

Apart from the above, some of the attributes of application under test (AUT) also plays a role in selecting or designing a test automation framework. For example: technology of the application, ease with which an automation tool can interact with it, the type of front end and backend, etc. These will be specific to the AUT and can only be determined while working on it.

Test Automation framework can be classified into the following based on point #1 in conjunction with point # 3 in the list mentioned above.
  1. Simple Test Automation Framework
  2. Keyword Driven Framework
  3. Data Driven Framework
  4. Hybrid Framework

Simple Automation Framework:

A simple automation framework has the entire set of test cases or flows grouped into different scripts. The scripts will have a hierarchy and may be called by one another at different stages. The definition of the structure and interoperability of these scripts is fairly simple and may reside in a folder structure normally based on the hierarchy itself.

For convenience this can have commonly accessed code lines written as functions and stored into library files in another folder within the root structure.


This kind of framework is used when the test cases and their flows and the AUT itself are simple and easily manageable.

Keyword Driven:


This is also known as data table driven framework. The application under test will be supplied with the input data using the data table feature of QTP (quick test professional). The data table works just like an excel work sheet with rows and columns containing data pre entered by the user. QTP internally uses a keyword driven framework. The script concentrates on two things: objects and operations. An object can be a button, text edit, combo box, radio button, check box, etc. and an operation can be click, enter, set, select, etc. The operation examples mentioned here are the keywords defined in QTP. We do operations on different objects using keywords and the data is input to them in loop through the data table. For example form filling on a website includes these different fields and using QTP’s data table, multiple forms can be filled using a loop with variance of data saved in the data table. An example below shows this better. [Not in any computer language. This is for concept understanding only]

Loop Begin
 TextEdit.Enter “John Smith”
 RadioButton(“Male”).Select
Loop End

This can be written using data table as:

Loop Begin [Run for 2 times]
 TextEdit.Enter DataTable(“Name”)
 RadioButton(DataTable(“Sex”)).Select
Loop End

Data table can be like this:


Scripts can be created in keyword driven methodology mostly by recording the scripts and creating variance of data for the various operations. This can be the best approach when the users have less technical knowledge in expert mode scripting or need a quick automated script created to do a set of simple operations over and over again.