Showing posts with label QTP tutorial. Show all posts
Showing posts with label QTP tutorial. Show all posts

Saturday, 15 September 2012

Library Files

This is a continuation

In an automation framework architecture library files plays an important role. Normally people try to built most generalized function and place them at separate and common place.

I see that people always ask me questions which one is good to use Action or functions? I have personal view on these to use Functions instead of Actions. Of-course every aspects have its own pros and cons. Some people may feel comfortable to use Actions rather than Functions.

Whenever I create a functions I always have an intentions in my mind whether I can make this functions more generalized? I have developed an habit to have function's maximum usability. But be caution think to make generalized function should not change your motto of creating it ;)


A function doesn't meant to only have the VBscript codes, of-course you can always have QTP script codes . Functions are often treated as keywords in QTP, now a keyword can be placed separately in excel file, text file, or XML file. so that you can design keyword driven framework.

While automating (developing script) a particular workflow/E2E test case, first I create scripts in Linear manner in a particular action. Later on I break down these workflow in smaller script parts, of-course to divide these you need to know other test cases also so that you can easily identify commonality in functionality. Don't worry if you are not able to identify commonality, just go ahead and as you move ahead with framework designing you will be able to know it.

Now, the divided code is bundled under functions with a name which could make sense, for example NavigateTo(strURL), Login(strUserName, strPassword), NavigateToPageMenu(strMenuName), LogOut()

In an attempt to make execution faster and in terms of maintenance we load the functions runtime by leveraging power of "ExecuteFile" method. See, when you associate the ".qfl" file with script, so when you want to move complete framework folder, you will have to re-associate the library files. Of-course while script development you would require to associate library file for debugging purpose. Later on after your code is fully developed you can use "ExecuteFile" method to make all functions available in QTP run session during runtime.

I will update some more ideas in future, ofcourse many more ideas related to Library files.

Now Talking about our Framework development, presuming I have functional knowledge of AUT. I decide to place functions in appropriate library file. When I say appropriate library file . . . I meant only those library files containing specific functions which are relevant to a particular module or Test Case should be loaded. It doesn't make sense if you have numerous function written in a library file and in runtime load, these function are available which are of no use.

I have seen people writing function in an unorganized fashion and a single library files are flooded with many functions which are sometimes create problem during maintenance. Ofcourse no harm with that, but I believe this as to be the best practices.

See below image for a gist I am trying to convey . . .













 In above framework folder structure you can see some library files example placed. I guess no need to explain library files other than "GlobalFunctions.qfl"

GlobalFunctions.qfl :- This is one its kind, you know as the name suggest I place all those functions which 
  • are repetitively used
  • needs to have global scope
  • are very generalized
For example functions like
FrameworkInitializer, LoadModuleBasedTestData, LoadGlobalDataVariablesFromGlobalDataxls, CreateOutputDataFile, InitializeLogs, WriteCurrentLogInLogFile, ReportPassFail . . .

I have purposefully named these functions to be more meaningful to you ;)

GlobalFunctions.qfl file is associated with all QTP TestScript. The decision to put functions in which library files solely depends on you, you have to design the architecture, you have to design the workflow of you framework, you have to decide when to load which library files.

-Pankaj Dhapola 
Think on it

Thursday, 12 July 2012

Some QTP DOM Codes

On one of my friend's Request

Set totalUL = Browser("Jobs - Jobs in Gulf -").Page("Jobs - Jobs in Gulf -").Object.getElementsByTagName("UL")
For each ul in totalUL
    Print "UL list--------------------->" & ul.getAttribute("classname")
    If ul.getAttribute("classname") = "lc" then
        Set lis = ul.document.getElementsByTagName("LI")
        i = 0
        on error resume next
        Do
            Print lis(i).getAttribute("innertext")
            'once you have got the attribute you want, use instr function and then grab the complete text.
            if err.Description <> "" then
                on error goto 0
                exit do
            end if
            i = i+1
        loop while true
    End If
Next


-Pankaj Dhapola
Let's Think on it

Tuesday, 26 June 2012

An Example of DotNetFactory in QTP

An Example of DotNetFactory in QTP

Function DotnetUIDPWDForm(strDetails)
 'Creating instances of DotNetfactory objects
Set frmProd = DotNetFactory.CreateInstance("System.Windows.Forms.Form", "System.Windows.Forms")
Set lblDBDetails  = DotNetFactory.CreateInstance("System.Windows.Forms.Label", "System.Windows.Forms")
Set lblUID = DotNetFactory.CreateInstance("System.Windows.Forms.Label", "System.Windows.Forms")
Set txtUID = DotNetFactory.CreateInstance("System.Windows.Forms.TextBox", "System.Windows.Forms")
Set lblPWD = DotNetFactory.CreateInstance("System.Windows.Forms.Label", "System.Windows.Forms")
Set txtPWD = DotNetFactory.CreateInstance("System.Windows.Forms.TextBox", "System.Windows.Forms")
Set btnSubmit = DotNetFactory.CreateInstance("System.Windows.Forms.Button", "System.Windows.Forms")

Set oPoint = DotNetFactory.CreateInstance("System.Drawing.Point", "System.Drawing", x, y)

oPoint.x = 10
oPoint.y = 10
lblDBDetails.Location = oPoint
lblDBDetails.Width = 350
lblDBDetails.Height = 70
lblDBDetails.Text = strDetails

oPoint.x = 10
oPoint.y = 80
lblUID.Location = oPoint
lblUID.Text = "PROD User ID"

oPoint.x = 10
oPoint.y = 110
lblPWD.Location = oPoint
lblPWD.Text = "PROD Password."

oPoint.x = 150
oPoint.y = 80
txtUID.Location = oPoint
txtUID.Width = 100

oPoint.x = 150
oPoint.y = 110
txtPWD.Location = oPoint
txtPWD.Width = 100
txtPWD.UseSystemPasswordChar=true

oPoint.x = 150
oPoint.y = 150
btnSubmit.Location = oPoint
btnSubmit.Width = 100
btnSubmit.Text = "Submit"
     
'Add Controls
frmProd.Controls.Add lblDBDetails
frmProd.Controls.Add lblUID
frmProd.Controls.Add txtUID
frmProd.Controls.Add lblPWD
frmProd.Controls.Add txtPWD
frmProd.Controls.Add btnSubmit
frmProd.CancelButton=btnSubmit
frmProd.Text = "This is a PROD RUN"

frmProd.Height = 250
frmProd.Width = 350
frmProd.ShowDialog
DotnetUIDPWDForm = txtUID.Text & ":" & txtPWD.Text

Set frmProd=Nothing
Set lblDBDetails=Nothing
Set lblUID=Nothing
Set txtUID=Nothing
Set lblPWD=Nothing
Set txtPWD=Nothing
Set btnSubmit=Nothing
Set oPoint=Nothing
End Function


-Pankaj Dhapola 
Let's Think on it

Tuesday, 24 April 2012

Bring your Test Data in QTP environment

This is continuation . . .

Okay,
Hear it goes

Well my Aim is to Bring an excel stored data into QTP Environment.

I hope you remember this figure . . .











Well this is the Screenshot of "GlobalData.xls", I have explained why did I named this excel as GlobalData.xls

Let's give this excel file an importance because whenever you script is going to start with execution, this file will play major role in term of Initializing your per-requisite of your Test.

Notice the column names "Key" and "Value", what I gonna tell you now, I think I gotcha!!!

I shall extract this data from excel using ADODB, then store that data into Dictionary Object and then make that Dictionary object as Environment Variable.


Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= & getGlobalDataxlsPath() & ";Extended Properties=""Excel 8.0;HDR=Yes;"";"
objRecordset.Open "Select * FROM [SheetName$]", objConnection


Now Since you've got the RecordSet, now it's time for Dictionary Object to come into picture

Set objDict = CreateObject("Scripting.Dictionary")
Do Until objRecordset.EOF
   objDict.Add objRecordset.Fields.Item("Key"),  objRecordset.Fields.Item("Value")
   objRecordset.MoveNext
Loop

Now let's make this Dictionary Object an Environment Variable.

Environment.Value("GlobalData") = objDict


From now on where ever you want you can use the Dictionary object stored in Environment, your reference code will be

strBasePath = Environment("GlobalData")("BasePath")

For more insight on referencing on Environment Variables click here

So folks,
I have shown you the code just for understanding the concept behind it, for codes google it out!!!


*getGlobalDataxlsPath()shall return the complete path of "GlobalData.xls" file, Since we need to achieve portability, the path shouldn't be the static one, I shall post later on the logic behind it.

Till Then Take Care . . .

-Pankaj Dhapola
Let's Think on it

Monday, 23 April 2012

Automation Framework Architecture using QTP

Automation Framework Architecture using QTP

Every one knows about the different types of framework
I'm not going to explain you about these framework (Many Authors have done that), I would like to visualize you how you can start off with designing of your framework . . .
I'll try my best to share with clarity and understanding


Well first off all, you should make a mind map (or simply draw a DFD) of the structure of your framework, for example
1) The flow of input data from a storage into your application
2) How you will arrange the output of the application and display/store results?
3) How your execution of scripts would be arranged both locally and in QC?
4) How is your reporting and logger functionality will work?

All this questions definitely come after experience, but people with great Visualization would grasp it easily.

Now their are some aspects of any framework

1) Library files:- which is bundle of functions in .qfl, .vbs, and/or .txt files.
2) Test Data: - The required inputs in your application, which may be stored in excel(mostly), txt, CSV etc
3) Test Scripts: - A place where all Scripts are stored functional and sub functional wise.
4) Results:- A place where your application results/output will be generated. Note that this place can be different in QC and Local folder structure
5) Object Repository: - A place where Global OR is placed if any.
6) Recovery Scenario: - A place to store recovery scenario.
7) Re-Usable Actions: - A place to keep your re-usable actions, if any.

you may also have some other folder to include depending on project.

And now . . . Bundle these aspects under one roof, i.e your framework like below folder structure


Now the layout is ready, how do you let QTP know about these folder structure path, how will you keep this folder called "MyFramework" independent of a place, where-ever you put, it should run seamlessly, either in Company Shared Drive or your desktop, etc.

In short how will you make it Portable or keep integrity of relevant aspects intact.

I have a solution ("GlobalData.xls"), write down the path name of all this structure in an excel file.

See below screenshots.











The Cell formula for "BasePath" is
"=LEFT(CELL("filename",A1),FIND("[",CELL("filename",A1),1)-1)"

Now you might have question why did I Named this excel file as "GlobalData.xls"
I think I gotcha!!!

Put all your data which will be used across your script execution, the data which you would need persistent throughout your script execution like AUT URL, User-ID, Password, all function library file path, etc

See what is the advantage . . .
Put this folder wherever you want, your excel file keep the integrity of the Framework Structure path. I have seen some framework which have many configuration issues if it is migrated to another PC for execution, and time is lost while debugging.

I came up with this intact solution.

Up to me A framework should leverage Re-Usability and should be good in maintenance.

I will tell you how you will bring these data in your QTP "Environment" ;)

Taking about next thing . . . . .
LibraryFiles

What do you think about Managing Object Repository

What kind of Results/Logs do you Generate?

-Pankaj Dhapola

Monday, 19 December 2011

QTP object identification process

How does QTP identify an object?

Well being a technical guy this question has been wondering me a lot before knowing it.

When I learned that QTP identify objects on the basis of properties and I was knowing that each and every object in DOM or Web Page has been assigned with properties (attributes) and its values. So I went into flashback when I used to create HTML pages . . .
For each web element frame, form, button, text box etc we assigned properties/attributes and value inside tags, u remember?
something like below figure . . .

Notice the tags and the attributes that html dveloper have assigned to each object in the html page.

These are the properties that QTP leverage to Identify a particular object.













This would be very interesting afterwards.


Let's go into some theory,
To be very specific QTP has grouped properties under 3 categories
1) Mandatory(or base) Properties:- These are most important properties which are required to identify
objects.
Example:- In a WebPage, how come a particular object is identified as button or textbox? its because of its mandatory property like object type of Class Name, whether it is WebButton or WebEdit. 

Note that:- sometimes it is possible to identify object without this property.

2) Assistive Properties: - Sometimes Mandatory property is not enough to identify an object uniquely, so
this property is used. Hence the name is given Assistive. example:- name, text, value etc

3) Ordinal identifiers:-    If above both fails then ordinal identifier are used to identify object. These are
like  Location and index (or order) of object.


"Now don't ask me how QTP extract the properties from application. That shall be another blog."


QTP identification process works exactly same as human like filtration process. Now to understand this you will have to think like a machine or AI. 


Example:- You might have seen Rajnikant's Robot movie right? 
Now suppose you have a family photo of Aishwarya Rai and you ask Chitti (the Robot) to Identify Sana (Aishwarya) from this photo. Now what does Chitti do?

He opens up his informational database regarding Sana and list out all properties or features.
Now he scan the photo and in first step process he figure it out the their are 2 males and 2 females. Now according to his informational database Sana is Female, so he filter out 2 males from photo and concentrate on 2 female. Here the property "female" is Mandatory or base filter property.  ok?

In the next step process he identifies that skin color which turn out to be same for both female, here the assistive property "skincolor" is not enough but again look for next property like Age.
This time he figure out that his informational database age and the visible age in photo and filter out the other women and uniquely identify Sana from the photo using assistive property "Age".

In this way objects are filtered out on the basis of Object properties.

Sometimes it may happen that due to lack of above two types of unique property Chitti fails to identify Sana. Now this time he uses the ordinal identifier property like location. for example, he scan his whole image database and finds that Sana Always stand on left hand side of photo in a group of 4. So he assumes that in this photo also she might have been standing in extreme left and says "Person in extreme right is Sana".

Now you might ask me so why QTP uses Mandatory and Assistive property then, why not use Ordinal directly? Suppose in other photo Aishwarya stands in the middle instead or extreme left, now chitti fail to identify Sana. That's why I mentioned the word "Assumes" and Chitti said  "Person in extreme right is Sana", he did not even said female on extreme left. Ordinal Identifier are not the reliable properties to Identify Objects many a times.

Their is Concept call Smart Identification feature- Sometimes what happens is while identifying objects QTP lacks exact property of object, so in this case QTP assumes that which object is very much near to the exact property provided. Not much to talk on this.

Their an inbuilt tool called Object Spy which is available in QTP menu with this Icon.
Object spy look like a window having properties and values column with a button having image of hand point to left.








Coming back to my flashback's HTML page and its code, I went home and searched out that HTML page and place the Object spy hand in it. I was surprised to see the properties in Object Spy of the WebEdit that I had created.

Below is the screenshot with marking.


Isn't this amazing? Are you actually able to relate things properly? Give a close look at the red and blue boxes.


Try it now!!! 
-Pankaj Dhapola