Sunday 21 October 2012

Architect Object Respository in your own way in Automation Framework

Object repository has been one of the most important aspects of framework development.


I am not going to show how you gonna add objects in QTP Object repository or use the object repository manager of QTP. Well you could find all those stuff very well over Internet.

I have seen some people Manipulating Object repository usage in QTP.

At a very basic level how do you understand Object repository existence, why their is a need of OR?

 To explain it in a simple manner, every Automation tool has its own architectural aspect to store Object properties or Object identifying criteria at a common place for usage while automation script run session.

 For example,
  • Object Repository in QTP
  • Object Map in RFT
  • Object Browser in Test Complete
I have seen people using QTP based Object repository, some building their own object repository! Of-course as I always say usage of every scenario has its own pros and cons.

Do you understand building their own object repository and not using QTP based Object repository?

I guess your next question is how is that so?

Just give more attention to above paragraph in bold letters.

When I say a place where object properties are stored, you can use an XML file, and excel file, a text file etc., Now the challenge is how you will use these files while in QTP run session.
You can place the description strings in these files and use some powerful Vb Script functions to build scripts


Just try to decode the below Image Illustration





Above illustration is very raw type of code, my aim behind showing this illustration is being an Automation Test Engineer cum developer you can tweak
the Object Repository usage in your script. Many ways can be developed to design architectural aspects. Of-course to master on you architectural skills you need experience.

Please note that I have purposely use the name of objects as such for better understanding.

Other Variation I see is below, I learned this technique from one my mentor, whom I regard as one the best minds I ever met.












So in Above illustration, you can observe how you can mimic an OR in QTP. Of-course many other ways have been developed.
Note that don't bother about the Hierarchy column as of now.
 

My main intention of displaying above different technique is to make you understand how you can design your OR. People of great minds have done this in many ways.

-Pankaj Dhapola
Let's Think on it

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

Saturday 18 August 2012

Object Repository & Descriptive Programming

What is an Object Repository?
As the name Suggest Object Repository (OR in Short) is place where QTP Test Objects properties and its values are stored.

Conceptually if we want to perform a task on any Objects like WebButton, WebEdit, WinEdit etc. what we look for? Naturally the Object's available methods/functions/sub on which we need to perform the task!

Now, how do you know or how do you identify whether you are clicking the right button or entering string in right TextBox (WinEdit/WebEdit)? So, what do you look for the right Button or TextBox?

Your answer maybe like
-The look and feel of Object should be like button
-It should contain text on button
-And if their are two button with same name then in which context the button is present, I shall click that one. Example button name is "Submit" context may be
  1. Click Submit to update record 
  2. Click Submit to Add the record

So ultimately what were you doing? Identifying Objects by their properties, right? This is how QTP does the same to identify Objects.

For in depth understanding with illustrations on how QTP Identify Objects, click here.

Also have a look at Object Repository GUI in QTP and Descriptive Programming in QTP

Now, lets look at below screenshot of OR & DP Code, try to catch the difference

Look at the highlighted part. You will understand the commonality or what is the basic thing QTP works with, i.e. Properties.

I was just wondering how could OR based Code is associated with Object Repository, I just opened the Script.mts file in notepad and then. . .






See the highlighted part, now you can imagine how QTP IDE has been designed and how could QTP OR and DP based code works. ;-)
Hope you are able to understand OR and DP!

I don't know what these highlighted part are, otherwise I could have been in Mercury inc. ;-)



-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

Some Utility Codes

Some Utility Codes

While working with Oracle DB's,  you require TNS entry file (tnsnames.ora) in your system whenever you fire a query to a particular DB.
So when you fire query using ADODB objects to oracle DB's , you may require to have the TNS entry in that file else you would find error stating "TNS entry missing".

I struggled this kind of scenario, to have someone from Admin team to replace file, due to lack of administrative privileges. Some organizations don't allow that. I thought to eliminate this, so Googled for TNS entrly less Connection String.

I saw that a TNS file have below type of information
................................................................
SomeRefrenceName=
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP) (HOST = theDBHostServer.Companyname.com) (PORT = 1530))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = SomeServiceName)
    )
  )
................................................................

So I thought can we enter this TNS Entry into our connection string? I found below solution.

Below provider is from MicroSoft for Oracle DB, This seemed to be reliable for me.

ConStr =  "provider=msdaora;" _ 
          & "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)" _ 
          & "HOST=" & strHOST & ")" _
          & "(PORT="& strPORT & "))" _
          & "(CONNECT_DATA=(SERVICE_NAME="& strSERVICE & ")))" _
          & ";User Id=" & strUID & ";Password=" strPWD & ";"

You can use other providers as well like
Provider=MSDAORA.1 
provider=OraOLEDB.Oracle.1


-Pankaj Dhapola 
Let's Think on it

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

Friday 15 June 2012

Entry point in your Automation Framework

*getGlobalDataxlsPath()shall return the complete path of "GlobalData.xls" file

This is a small part to understand  getGlobalDataxlsPath()


Now the logic behind having an entry point for your Automation framework is whenever you execute any script, your framework structure should be available in Execution QTP environment. Since "GlobalData.xls" itself contain the structure, how you gonna access this excel sheet seamlessly.

One Idea, let's leverage QTP's Enviroment("TestDir") variable.

So your function called getGlobalDataxlsPath() Should return a path like for example 
"C:\\whereveryouhaveplaced\GlobalData.xls"
Colored path is what we need to extract.

Look at below code

Function  getGlobalDataxlsPath()
                 getGlobalDataxlsPath = Mid(Environment("TestDir"), 1, instr(1,Environment("TestDir"), "Framework")+10)
End Function

I hope you got dat!!!

Notice the dependency, your Framework Base folder should contain the word "Framework".

-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

Sunday 22 January 2012

Descriptive Programming in QTP

What do you mean by Descriptive Programming (DP in Short)?

In QTP, An Automation script developer can write script codes using Object Repository or Descriptive Programming. Descriptive Programming is nothing but working with Object's property name and property value. As we all know QTP identify objects on the basis of object properties which is ultimately known as Descriptions.

Now in QTP, How do we write scripts in DP to perform an action like entering string in text field, clicking button etc. . .?

Ummm . . .

To Identify object uniquely we need to find descriptions or properties of an Object. How do we find properties? It's Object Spy. Descriptive code can be written in two ways

  • Mention your Descriptions using QTP inbuilt programmed Description Object. (Note here Description object is different than the GUI objects like WebButton, WinButton etc, Description Object is programming concept.)
  • Another way is to mention your description in string format.

Let's take an example . . .

I have adjacent html WebPage that I developed during my college days when I first learned HTML ;)

I have to write a script to enter firstname, lastname and then click on Submit button.

Now, to write script using Description Object you would require to create a description object and use its add method to add "propertyname -propertyvalue" pair, for that write below code

Set objDesc = Description.Create
objDesc.add "propertyname1", "propertyvalue1"
objDesc.add "propertyname2", "propertyvalue2"


Use this code to write script for object
QTPObject(objDesc )



Wait this is not the end, I want to uniquely identify the TextBox besides "First Name" Label. so for this I need the properties of the "First Name" TextBox and for that naturally I will use QTP object spy.

Let's see what Object spy has to say. . .
Look at the 3 property and value pair for First Name WebEdit (or Text Box)
class = fntxtclass
html tag = INPUT
name = fntxt 

According to hierarchy of "First Name TextBox" Object, with little knowledge of DOM I realized that to reach this textbox I need to identify Browser(MyFirsthtmlcode) first and then Page(MyFirsthtmlcode) and then WebEdit(fntxt)

okay let me go with First Name Textbox or WebEdit(fntxt)


Can you relate things in browser, HTML source page and object spy? Try to understand how are WebObjects being interpreted in QTP environment.

Now I decide to use these 3 properties for identifying the "First Name" TextBox (or WebEdit) in our description object.
Let's see how do i do that . . .

Set objFirstNameTextBoxDescription = Description.Create
objFirstNameTextBoxDescription.add "class","fntxtclass"
objFirstNameTextBoxDescription.add "html tag","INPUT"
objFirstNameTextBoxDescription.add "name","fntxt"

now this object is mentioned in WebEdit object as

WebEdit(objFirstNameTextBoxDescription)


Lets use the same process to identify Browser and page, I figured out below code for both Browser and Page Object


Set objMyBrowserDescription = Description.Create
objMyBrowserDescription.add "name","MyFirsthtmlcode"

As

Browser(objMyBrowserDescription


Set objMyPageDescription = Description.Create
objMyPageDescription .add "class","fntxtclass"

As 

Page(objMyPageDescription)



Now lets see whether we have uniquely identify or not, for that I used highlight method for each objects.
Notice hierarchy in the code as well.

Browser(objMyBrowserDescription).highlight
Browser(objMyBrowserDescription).Page(objMyPageDescription).highlight
Browser(objMyBrowserDescription).
Page(objMyPageDescription).
 WebEdit(objFirstNameTextBoxDescription).highlight

guess what!!! "First Name" TextBox was highlighted

And then I used the most common method of WebEdit object i.e. set() method to enter value in our text box.

Browser(objMyBrowserDescription).Page(objMyPageDescription).
 WebEdit(objFirstNameTextBoxDescription).Set "Pankaj Dhapola"

Now Another way without using Description Object is to enter Description properties in String format like this
QTPObject("PropertyName1:=PropertyValue1","PropertyName2:=PropertyValue2", . . . .)

Above equivalent code in String format is



Browser("name:=MyFirsthtmlcode").Page("name:=MyFirsthtmlcode").
WebEdit("class:=fntxtclass","html tag:=INPUT","name:=fntxt").Set "Pankaj Dhapola"



Try it yourself friends.
But notice the case sensitivity inside the String and Description object where you provide the Descriptions or "PropertyName:=Value" pair.
-Pankaj Dhapola

Sunday 8 January 2012

Object Repository in QTP

Wooah!!! Let get into deep understanding of Object Repository (OR in Short)

As the name suggest "A place where Object is stored", but don't get confused. Object in QTP world is basically "PropertyName-PropertyValue" pair. QTP Object Repository is a Graphical representation Various Test Objects and their properties along with hierarchical relationship with other objects as well.

Their are some more functionality available in Object Repository window like . . .
 Add Objects to Repository
 Object Spy
 Associate Other Repository from file
 Highlight Selected Test Object in Application

These are very few enlisted above with Icon Image.

Now lets see how does an Object Repository GUI window looks like.

Left Pane shows the total Test Objects what is going be used by QTP during Test Run. Now these object can be added manually or by QTP itself while recording a script rather I should say a workflow.
Two thing keep in mind to get familiarize with OR.
1) Notice the hierarchical relationships among objects. People who can understand HTML DOM (Document Object Model) can easily figure out why these objects are placed in such order.
2) Notice the Icon and Name of each Object.

Right Pane shows an Object properties and its values.

Lets take an example of our Test Object having Name "Google Search"
Notice the Icon, its a WebButton and the name "Google Search" 
Look at the Right Pane now 3 Description properties are displayed like type, name and html tag.
QTP have itself added these 3 properties to uniquely identify a particular object in application.

Now you will ask me what do you mean "QTP has itself added these properties"? (Note that I am talking about object properties and not Object because I have manually added all those objects in OR, but QTP have itself added all the required properties of each object.)

When I click on Icon         QTP vanishes and Object Spy Hand  appears and placed on the object (Google Search Button) then QTP fetch all the available object properties from the application and using Object Identification Mechanism it filters out that it require above 3 properties to uniquely identify Google Search Button in Google landing page. 

QTP self assign a name ("Google Search") to Google Search button object so that automation tester can use this name as reference in his code.
Now let's around with this object, 
1. Click on highlight button  and then Google Search Button gets highlight
2. Delete  some property and see that whether you can identify (or highlight) object, I deleted property "html tag" and guess what I was able to highlight Google Search Button. And I again deleted property "type" and I was able to highlight Google Search Button. And I again deleted property "name" and guess what QTP showed me 

What did I concluded here.
QTP sometimes take extra precaution to uniquely identify object hence add some more properties without which it can still identify object uniquely.
I have learned that the more number of properties you add, QTP will take more time to analyze object. Hence I started deleting properties.

Okay pals try yourself . . .
Happy Learning . . . :)

-Pankaj Dhapola