Part 2: QTP/UFT beginner tutorial-creating a dynamic click link function from scratch!

 

In part one of the tutorial, we created a basic click link function that only works for specific pages. Today, we will capitalize on that and add a way for our function to click a link on any page. Just like the first tutorial, we will use the three links below for practice.

Link1

Link2

Link3

We will start by identifying which browser window is currently open. We can do this with the code hwindow = Browser("creationTime:=0").GetROProperty("hwnd") The hwindow is a unique property used to identify the Browser window. Using the code above, we are setting the hwindow variable to print us back a unique number which we can use to identify the browser. The creation time refers to the order in which the browser windows were opened. It is used like the standard index property. If you open 1 window in the browser, the creation time is 0. If you have two windows open, the first window creation time is 0, and the second window creation time is 1. And lastly, we are using the GetROProperty to return the run time value of the property hwnd. This is the hwindow unique number that I was referring to. Set a message box for our hwindow variable, and it should return a unique number. My number is 658734.

hwindow = Browser("creationTime:=0").GetROProperty("hwnd")

MsgBox hwindow 

Now that we identified the browser, we can use this to identify the page. I am setting a new variable to return the value of the page title. I used my unique hwnd property for the browser. For the page, since we don't want to use a static page, we want to use a regular expression that helps us identify the page_title of any page. I use .* regular expression to pull the run time property title value. Set the message box for the page title and you will now have a unique page title.

page_title = Browser("hwnd:=658734).Page("title:=.*").GetROproperty("title")

MsgBox page_title

Awesome! You're almost there. In my situation, my page_title contains special characters. I have to set my title in a specific way to help QTP/UFT read those special characters as a string. I have a separate tutorial for that you can check out below.

Special Characters Tutorial

I have created a function to replace all the special characters in my function.

Function fnReplaceRegExp(StrLabel)
    StrLabel = replace(StrLabel, "|", "\|")
    fnReplaceRegExp = StrLabel
End Function

This function takes the | character which appears in my title, and replaces it with \|. All we have to do is call this function with the code below. Set this code up after retrieving the Browser hwindow, and the title and you should see that the special characters have been replaced.

page_title = fnReplaceRegExp(page_title)

MsgBox page

Now we can take these three parts and convert them into a function.

Function fnIdentifyBrowserPage()
    hwindow = Browser("creationTime:=0").GetROProperty("hwnd")
    page_title = Browser("hwnd:=" & hwindow).Page("title:=.*").GetROproperty("title")
    page_title = fnReplaceRegExp(page_title)
End Function

Lastly, let's convert our original fnCLickAnyLink function to include the newly found Browser and page title values.

Function fnClickAnyLink(pStrName, pIntIndex)
    Browser("hwnd:="& hwindow).Page("title:="& page_title).Link("name:=pStrName).Click
End Function

Now if we call the fnIdentifyBrowserPage function before, we can then click on any link. But wait, some of us may not be using a name property uniquely identify a link. That's ok, we can create a dynamic way of uniquely identifying a link by any property.

Function fnClickAnyLink(pStrPropertyName, pStrName, pIntIndex)
    Browser("hwnd:="& hwindow).Page("title:="& page_title).Link(""& pStrPropertyName &":="& pStrName).Click
End Function

I added another parameter pStrPropertyName and placed it instead of the name property for the link. Now, we can set the link property to html id, innertext, innerhtml, and so on... I will now call the function and dynamically click on the first link.  First, I call the identify browser and page function, then I click on the link.

fnIdentifyBrowserPage
fnClickAnyLink "innerhtml","Link1", 0

Awesome right? Your full code should look like this:

fnIdentifyBrowserPage
fnClickAnyLink "innerhtml","Link1", 0

Function fnClickAnyLink(pStrPropertyName, pStrName, pIntIndex)
    Browser("hwnd:="& hwindow).Page("title:="& page_title).Link(""& pStrPropertyName &":="& pStrName).Click
End Function

Function fnReplaceRegExp(StrLabel)
    StrLabel = replace(StrLabel, "|", "\|")
    fnReplaceRegExp = StrLabel
End Function

Function fnIdentifyBrowserPage()
    hwindow = Browser("creationTime:=0").GetROProperty("hwnd")
    page_title = Browser("hwnd:=" & hwindow).Page("title:=.*").GetROproperty("title")
    page_title = fnReplaceRegExp(page_title)
End Function

Congratulations, you have a very dynamic link function. In later tutorials, I will show you how to dynamically select the window that the link is on when you have multiple open windows! Please post your questions and comments below!

  • TestEngineerX

    This is definitely better since it is more dynamic. But again it brings us back to the same problems. First, what if you have multiple properties that you need to use? Second, what if I dont want to use index? I dont think there is a point in wrapping that line of code in a function because it’s easier to do:

    Browser(“hwnd:=”& hwindow).Page(“title:=”& page_title).Link(“”& pStrPropertyName &”:=”& pStrName).Click

    I can store my properties in an xml file and they will only live in 1 place. If I need to use more properties, i can do

    objBrowserPage.Link(“prop1:=val1,prop2:=val2”).Click

    While you would need to create another function. And what would you call it, “fnClickAnyLinkWith2Properties”?. And without index, I would need another function “fnClickAnyLinkWithoutIndex”. So now I will have 3 functions to do 1 same action. Very confusing, don’t you think? I think it would be good to jsut have a function that clicks a link and takes an array of properties or a dictionary. Then I can pass in as many as I want and have only 1 function to do 1 action.

    • QTPtutorialnet

      With a function, you can’t adjust for every single scenario. A function is supposed to make your life easier, create less work for you, and lessen the maintenance in your script. In most cases, you will not need more than one unique property to identify an object. And if there are objects that have the same properties, this is where the index comes in. Also, it takes .001 seconds to add an index when calling a function. This isn’t going to affect anything. It comes into play when you have two or more link objects with the same values. Personally what you’re saying saying about functions applies to the extreme outliers where not all elements align. But in this case, I can use this same function for 99% of the click link scenarios. But if you have an application where each objects need 2 or 3 properties to be identified, I can update the first function to do that as well. It really depends on your application. Between applications, there is usually some kind of consistency in the way the developers coded it. You can adjust the function to fit your type of application. Your way of creating an object for the browser and page is also a good way of creating less code while making your life easier. I actually have a tutorial about it as well 🙂 But if you’re talking about the quantity of code, look at my example vs your example below.

      Your example:
      objBrowserPage.Link(“prop1:=val1,prop2:=val1”).Click
      objBrowserPage.Link(“prop1:=val2,prop2:=val2”).Click
      objBrowserPage.Link(“prop1:=val3,prop2:=val3”).Click

      My example:

      fnClickAnyLink PropName1, prop1, Index1
      fnClickAnyLink PropName2, prop2, Index1
      fnClickAnyLink PropName3, prop3, Index1

      And yes again, I agree with setting variable values instead of hardcoding them. But this is great for repetitive items. It is much too tedious for every single link you will every click on.

      • TestEngineerX

        I complete disagree with this statement, “With a function, you can’t adjust for every single scenario.”. That is the purpose of a function. It is supposed to repeat one action and make it easy to do so. In our case, we are discussing links. Therefore, there should be ONE funClickLink, ever. Why would you need more than 1? Look at the Descriptive programming, you can do

        objBrowserPage.Link(“p1:=v1”).click

        objBrowserPage.Link(“p1:=v1″,”p2:=v2”).click

        objBrowserPage.Link(“p1:=v1″,”p2:=v2”, “p3:=v3”).click

        One function can handle multiple parameters, no matter what they are. If we are designing a function to click any link, then it should do just that.

        Which brings me to my 2nd point of “In most cases, you will not need more than one unique property to identify an object”. This is also false. Maybe you are lucky to not have a complex application. However, I deal with 3 different applications on a daily basis and all of them require different properties to be recognized because they are developed on different technologies. Please help me with a click link function to satisfy the following scenarios:

        1. need 2 properties

        2. need 3 properties,

        3. some need an index,

        4. others with only 1 property

        5. asynchronous calls where I need to use coordinates to figure out if they exist on a page

        6. sometimes I even have to use xpath

        Then, I can use that function to create all of my other functions like setWebEdit, clickButton, clickImage, findImage…

        Also, it doesn’t take .001 second to add an index. First, you have to type it. We are humans and we always make mistakes. I can’t remember how many late evenings i mistyped something and spent 30 minutes trying to debug. Have you ever made a mistake while coding? Second, you have to identify the index. Sometimes there may be multiple objects on a page and so you have to make sure that you click on the right one, otherwise your identifier will fail. Third, what happens when another object is added or removed from the page, now you have to maintain those indices. Finally, even if you dont have any of those issues, why would you do extra work for no reason?

        In regards to this, “But in this case, I can use this same function for 99% of the click link scenarios.” this only applies to you then. For me this function would be useless and I would need to redesign it for my purpose, right? So would anyone else in my situation. And so would you if you went to a different company. That’s why I feel like having 1 dynamic click link function will solve everyone’s need. Design one time and be done with it, forever.

  • Pingback: Part 3: QTP/UFT beginner tutorial-creating a dynamic click link function from scratch! |()

  • Pingback: QTP/UFT Identifying objects using Xpath the easy way! |()

Pin It on Pinterest

Clef two-factor authentication