Functions and Subroutines - Modularizing code in QTP


When you see job requirements, one of the most common thing that I see as a condition nowadays when recruiters look for QTP Automation Engineers is that the candidate must not be doing just playback and record in QTP. Well, the fact is that people who have just started working on QTP would most likely just have used the playback and record feature but once you get experienced, they would have started writing more code and when you start writing more code, you would definitely have started to write functions and subroutines as well. This technique of using functions and subroutines is actually what we call code modularization. This is not specific to QTP, its more of a general programming concept where we divide our program into repeatable and logical units so that our test becomes more organizedunderstandable, readable and maintanable (is there such a word...h-m-m...you got what I meant anyway !!).
Too much of theory, right ? So, as usual, lets get into an example. But before that lets talk about the one difference between functions and subroutines. Functions can return a value but a subroutine cannot. I am sure that this is what you have read everywhere but I will show you what this really means. Lets first write a simple function to add two numbers..

















Line 1 : This makes sure that we dont mistype any variable names
Lines 4 - 8 : Function Definition
Line 12 : Function is called and its return value is stored

Couple of things to note over here is that

  • A function returns a value by assigning the value to the function name. So Line 6 is where the function is storing the return value.


  • Another thing is that this assignment of (function name)=(value) need not be the last line in the function. Aha.....never thought of that , eh ? Yes, its possible. Let me show you another piece of code.





























OK... what did we just do above ? Lets say that I never expect the function AddNumbers to return -1 and I have so many lines of code before the final addition. For some reason, for any reason, for whatever reason, lets say the function just terminated in between, the Line 23 would actually get the value -1 if at least the first line of the function had been executed. So all that I wanted to show was that (function name)=(value) need not be the last line in the function. The code I showed above is just a technique I use, not that its the best technique but it definitely is a good one !!! But ideally we would not have any statements after this because we would generally assume that the function did its job once the value is returned.

  • Third thing to note is that we need not declare the variables or the function arguments intA and intB in the function. So our Option Explicit will not complain.


  • Another point to note is that it is not necessary that a function has to return a value. Which means even the below is possible





















But then if you dont want your function to return anything, then why even use a function !!!! Thats where we can make use of subroutines. However, in the beginning, I mentioned that functions can return a value whereas a subroutine cannot. What this means and what this only means is that if AddNumbers was a subroutine, you could never write Line 14 as above. However, you can write a subroutine also to obtain the sum, and in this case, the only thing is that you would have to pass an additional argument.


















OK, so we did the trick with a subroutine as well. I intentionally passed intSum to the subroutine and had the function argument as intFnSum just to show that we do not need to pass the same argument name. It could be just anything.
Notice the call to the subroutine here. We did not use any parantheses here as this is the VB script syntax to call a subroutine. However if you want to use it , there is still a way. Replace Line 12 above with

Call AddNumbers (208, 392, intSum)

Beginners to VB script would be thinking that a function can only return one value. By definition, even though this is true, dont restrict your mind to think that its possible only to return one value. You can make use of multiple arguments as shown above to get multiple values. Yes, just a question of logical programming. I guess I can keep on writing about functions and their interesting facts but I guess this should be sufficient as far as this topic is concerned. You know what... when you play with it more, you learn more and more interesting facts !!!!
As you would have noticed, I wrote the function definition in my action itself. This makes the function available only within the action. What if I want to make this function available publicly i.e. to anyone !! Thats where we would make use of Function Libraries which I will cover in another topic.

I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (0)

QTP 10.00 Release Update

HP has released an update for QTP 10.0 (Patch QTP_00626) which is a cumulative patch that updates your QuickTest installation with the latest files from a set of patches and hotfixes.
Release Date: Oct 15, 2009


Refer the patch information page here.


The detailed release notes of this patch can be viewed in the Release Notes Page.


Core Patches and Hotfixes

The following patches and hotfixes apply to the QuickTest core application:
  • QTP_00579 - Add Recovery Scenario-Function Library Dependency
  • QTP_00584 - Improve Performance of Loading Multiple Function Libraries Using QuickTest
  • QTP_00588 - Enable Running WinMenu.Select Steps on Context Menus in Windows with an Invisible Parent
  • QTP_00589 - Ensure DataTable.ImportSheet Returns Correct Error Code
  • QTP_00594 - Prevent Loss of Environment Variables that were Loaded in an Automation Script
  • QTP_00596 - Prevent Unexpected Icons from Appearing in Expert View of Large Tests with Breakpoints
  • QTP_00599 - Improve Performance of Running Function Library Functions
  • QTP_00600 - Performance and Stability Fixes for the QuickTest Debug Viewer
  • QTP_00602 - Support the Quality Center Resources Folder for the Application.Folder.Add Automation Method
  • QTP_00603 - Do Not Filter Invisible Windows
  • QTP_00604 - Prevent QuickTest Crash Due to Corruption of Internal Configuration File
  • QTP_00606 - Support Relative Paths for the ObjectRepositories.Find Automation Method
  • QTP_00607 - Improve Performance of Browsing Network Folders using QuickTest Dialog Boxes
  • QTP_00608 - Save the Correct Version of Resources When Using the 'Save Test With Resources' Feature
  • QTP_00610 - Prevent Incorrect Deletion of Folder Paths when Running an Application.Folder.Add Automation Method
  • QTP_00611 - Prevent QuickTest Crash/Freeze After Rapidly Performed User Operations
  • QTP_00613 - Ensure that Steps can Run on Returned Child Objects after an Exist Step Runs on that Object
  • QTP_00616 - Languages supplement for text recognition
  • QTP_00617 - Prevent QuickTest from Crashing When an ExecuteFile Statement calls Function Library with Syntax or Logical Errors
  • QTP_00621 - Enable Relative Paths for Function Calls in Recovery Operations
  • QTP_00625 - Increase Value Length Limitation When Storing Function Libraries in QuickTest
  • QTP_00629 - Ensure that QuickTest Tests Run from Quality Center Do Not Fail When a Single Step Takes a Long Time
Java Hotfix
  • QTPJV_00008 - Java Add-in Memory Leak and Support Next-Generation Browser Plug-in for Windows XP

.NET Patches and Hotfixes

The following patches and hotfixes apply to the QuickTest .NET Add-in:

  • QTPNET_00014 - Prevent Internet Explorer Crash On GridView with Text-Only Cells
  • QTPNET_00024 - Prevent Application or QuickTest Crash when .NET Add-in Extensibility is Used

 Oracle Hotfix
  • QTPORACLE_00005 - Enable Neutralizing Menu Listeners To Improve Performance Opening E-Business Suite Forms

 PowerBuilder Patches and Hotfixes

The following patches and hotfixes apply to the QuickTest PowerBuilder Add-in:
  • QTPPB_00006 - QuickTest Testing Support for PowerBuilder 11.5
  • QTPPB_00007 - Enable PBDataWindow.GetCellData While Object is Disabled
  • QTPPB_00008 - Increase String Length Maximum in DataWindow.GetCelldata() Method
  • QTPPB_00009 - Remove Obsolete DataWindow.ButtonClick Method

Siebel Patch
  • QTPSBL_00002 - Improve Performance on Siebel Apps

 Terminal Emulator Hotfix
  • QTPTE_00008 - Ensure TeTextScreen.GetText Method Captures All Text For Emulators in Text Mode
Visual Basic Hotfix


  • QTPVB_00002 - Prevent QuickTest from Crashing when Working with Windows Containing Many VbLabel Objects

Web Patches and Hotfixes


The following patches and hotfixes apply to the QuickTest Web Add-in:  
  • QTPWEB_00020 - Performance Improvement for Running Initial Steps on Modal Dialog Boxes 
  • QTPWEB_00026 - Resolve Conflict between QuickTest and McAfee Host Intrusion Prevention
  • QTPWEB_00028 - Cumulative Hotfix For Web Extensibility Performance
  • QTPWEB_00030 - Solve Problem with Active Screen Capture for Some Web Pages
  • QTPWEB_00031 - Prevent Internet Explorer from Crashing When Secondary Browser Windows Close
  • QTPWEB_00037 - Support for Internet Explorer 8
Registry Settings and Other Manual Changes


After installing this release update, you may also need to add or modify a registry setting or make other manual fixes to enable or modify the functionality provided in the following patches and hotfixes:

  • QTP_00599 - Improve Performance of Running Function Library Functions
  • QTP_00600 - Performance and Stability Fixes for the QuickTest Debug Viewer
  • QTP_00603 - Do Not Filter Invisible Windows
  • QTP_00629 - Ensure that QuickTest Tests Run from Quality Center Do Not Fail When a Single Step Takes a Long Time
  • QTPJV_00008 - Java Add-in Memory Leak and Support Next-Generation Browser Plug-in for Windows XP
  • QTPORACLE_00005 - Enable Neutralizing Menu Listeners To Improve Performance Opening E-Business Suite Forms
I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (0)

Descriptive Programming OR Regular Expression ? - Part 2

This is the second part to the post "Descriptive Programming OR Regular Expression ?". I recommend you to read the first part before you proceed, so please click here.
In the earlier part, we discussed how to use descriptive programming to make QTP to skip looking at an object in the object repository. Instead, we understood that descriptive programming helps QTP to identify an object in the application dynamically without searching in the object repository. In this part we will see another technique to look at objects when we are not sure of a particular behaviour of an object which would keep changing for every iteration or every time you work on the application. Some examples are new order numbers which are created newly every time or checking for the current date and time which would always change. Lets look at the example we saw in Part 1, where we want QTP to continue with the testing even when the order number changes. Here is where regular expressions are of great help. One of the sites which I often refer to for regular expressions is the regular-expressions.info site.
The way we are going to accomplish our task can be done through two ways.
1. Use regular expressions in our descriptive programming OR
2. Set a particular property value to a regular expression so that it would match the patterns that the particular property can have.

Lets try the first option. Now, we know that the only property which changes in our case is the "text" property of the Dialog object. So lets change the property to a regular expression. We know that the value "Fax Order No." is always constant but its the order number that keeps on changing. So we need to set a pattern such that the property text value should accept anything like Fax Order No.1, Fax Order No.2 or even Fax Order No.100. In a regular expression, to match any number, the pattern would look like [0-9]+. This means that any occurrences of any digits would match this pattern. So lets see how our script is going to look like...
The script in Part 1 would only have worked for Order no. 9 with the modified script but now, we have modified such that lines 7 and 8 of this script would work on any order number. However this script is very small but if we had a very large script, can you anticipate what the problem could be ? Yes, we would have to sit and modify each of the child objects that come after Dialog because we have to use descriptive programming for all the child objects as well. So here is where we are going to use one of the mostly used and effective techniques in QTP. We are going to make the regular expression change in the object repository itself and our program is going to look much neater.
We made the regular expression modification in the object repository and notice that I made one more change. Since this object is now going to be a more generic object, I modified the logical name of this object from Fax Order No. 10 to just Fax Order No. Now lets see how our code is going to look like
Now we dont need to take care of the child objects here because we are no longer using descriptive programming here. This has made our code also look very neat and this is one of the best ways to implement dynamic handling of objects in this particular case. I know this is quite overwhelming in the beginning but descriptive programming and regular expressions are some of the very important features that we make use of in QTP.

Hope this example helped you in understanding this concept. Suggestions are always welcome.

I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (2)

Descriptive Programming OR Regular Expression ? - Part 1


Hey, wondering what the title of this thread means ? Whats the relation between Descriptive Programming and Regular Expressions ? OK...we will come into all that. Of course, we are going to have an example, as always, to explain any concept. The example we are going to take here is an application that comes shipped with Quick Test. Its a windows based Flight Resevation application. I thought of taking this example as I could neatly explain descriptive programming and regular expression at the same time.
For those who do not have this application, dont worry, the screen shots below would be sufficient to understand the concept. Alright, so lets get into it. I opened the flight application and logged in. I have started recording only from this point forward.


First I go to File -> Open Order and selected Order 10 and clicked OK.


I then enter a FAX number and click the Send button.


OK..lets stop recording as we just need this much. Lets look at how our script looks like.

So everything looks good. If we try running this script its all fine. Now, lets perform this test on order 9 instead of order 10 so we need to modify line 4, and modify the value of 10 to 9 and then run the test. What just happened !!


OK...so whats the deal. Here is what happened. When we recorded this script, we recorded on order 10, as a result the properties of the Dialog window for Order 10 is what got stored in our object repository. Understand that its not the value "Fax Order No. 10" in Dialog("Fax Order No. 10") that is the problem. Its the properties of the Dialog window which caused the problem for which we need to see the object repository.

"Fax Order No. 10" (the value you see against Name: on the top) in Dialog("Fax Order No. 10") is just a logical name to the object and we could give any value to the logical name. Hope that is clear. If yes, then lets proceed. The object recognition problem happened because the "text" property of the dialog in the object repository did not match the application because now our text property has changed to "Fax Order No. 9". If you use the object spy on the new dialog, you would notice this. So much for the theory, now how do we resolve this issue !! We obvously want to run our tests as we may want to test this on multiple orders.
There are two ways to do this. Descriptive programming and using Regular Expressions or I would also call it "Property parametrization".
First lets look into Descriptive Programming and what it means. Below is a snippet from the Quick Test Help documentation.
"Descriptive Programming instructs QuickTest to perform operations on objects without referring to the object repository or to the object's name. To do this, you provide QuickTest with a list of properties and values that QuickTest can use to identify the object or objects on which you want to perform an operation."
In the case above, the object Dialog("Fax Order No. 10") is the object which changed which we want to work dynamically i.e. on any order. To make our code work on order 9, this is what we will do. We know that its the "text" property of the dialog which changed. So lets modify line 7 above to
Window("Flight Reservation").Dialog("text:=Fax Order No. 9").WinObject("Fax Number:").Click

Now lets rerun the modified test and see what happened. We got an error again.

And this is because
"When using programmatic descriptions from a specific point within a test object hierarchy, you must continue to use programmatic descriptions from that point onward within the same statement. If you specify a test object by its object repository name after other objects in the hierarchy have been specified using programmatic descriptions, QuickTest cannot identify the object." ( as taken from QTP Help documentation)
What this means is that, we used descriptive programming to help identify the Dialog object but we have to continue using descriptive programming from that point onwards i.e. from the Dialog object and all the child objects from that point within that statement. In short, we have to use the same technique to identify the object WinObject and even for the WinButton in Line 10. Before that lets see what properties QTP used to identify the WinObject.

and the WinButton
So we will make use of the "regexpwndclass" property for WinObject and we will use just the "text" property for the WinButton. Our modified code would look like this.

So here, you must understand that from Line 7 onwards, QTP will refer to the object repository only to look for the Window("Flight Reservation") object but from Dialog onwards, it will just search dynamically within the application (without referring to the object repository) to see the objects with the matching properties as specified by us.

Run the test and everything is going to be perfect !!
The second part of regular expressions is covered in Part 2.
Hope this example helped you in understanding this concept. Suggestions are always welcome.



I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (2)

Smart Identification - Pretty Smart !!!


Hey, today lets get into this concept of Smart Identification with an example. The QTP help documentation gives a pretty neat explanation of this concept, but you know what ... you will understand it better when you first see what it is and then read the help !!! A picture says a 1000 words .. so lets see what this smart identification really is !! You need an example, right ? Ok.. so here we go.

Lets first get prepared. Make sure that your browser has tabbed browsing. In IE8 you go to Tools->Internet Options->General->Tabs->Settings and make sure that you have the check box for "Enable Tabbed Browsing" checked. Next, lets make the home page set to blank. Again .. go to Tools->Internet Options->General->Home Page->Use blank. Lets close Internet Explorer. OK.. we are ready !!

Open QTP and load the Web Add-in. Go to Automation->Record and Run Settings. In the Web tab, make sure that "Record and run test on any open browser" radio button is selected. Now open IE. IE should now be opened and you should be seeing the page about:blank. Go to www.google.com. Now lets start recording and hit the Record button in QTP. Now enter site:learnqtponline.blogspot.com at the search box and click the button "Google Search". Hope you are with me until now. Stop the recording. If everything went well, this is what you should see in your script..



Lets go to IE and click on the back button. This should take you back to the Google page. Lets run this script now and look at the results.




So far, so good. Now what we will do is close IE and open it once again. Nothing special, just want to get into the reset mode :) So now you have the about:blank page opened again. Go to www.google.com again and this time we will open one more tab (not another browser..remember we enabled tab browsing earlier !!) and in this tab also we will go to www.google.com. Note that you have your second tab focussed and lets leave it like that. Shall we run our script now ? Ok..lets do it !! Lets run our two line test.
What happened ? Did it just go to the first tab and execute the test ? What is our results showing ?


Ok...so now we got an example and let me explain from here.
First let us look at a couple of windows
Below is the local object repository


Below is the window you see when you go to Tools->Object Identification

And below is the window you see when you click on the "Configure" button next to the "Enable Smart Identification" checkbox.

In the object identification window, we see that for the browser object, we do not have any mandatory or assistive properties to identify the Browser object. As a result, if you look at the local object repository, you see just the same. So what happened when we created a new tab and went to www.google.com and reran the test. QTP saw two browser objects but was unable to decide which browser object it was supposed to go to. Note that the Browser object had the Enable Smart Identification mechanism set to True and so the Smart Identification mechanism kicked in when a conflict aroused.
Now we are going to see what this mechanism actually is. For that we will analyze two windows, the results window of the second test and the window "Smart Identification properties - Browser" as you see on the top. The first part of this mechanism is that QTP will see if there are any Base Filter Properties. Since we dont have any in this case, Smart Identification mechanism  moves on to look at the Optional Filter Properties. It will take the first property which is "name" and filter the objects. QTP sees that both the browser objects (both tabs) still had the same value for the name property which is "Google". Smart Identification mechanism next includes the "title" property as well. QTP still sees that both objects have the same title property value "Google". Next the Smart Identification mechanism includes the openurl property and tries to filter and now QTP sees that the first tab had the openurl value of "about:blank". If you noticed, the openurl or the value you see at the address bar when you clicked on the new tab was "about:Tabs". Since we have now got a unique object, QTP is able to perform the operation and the Smart Identification Mechanism will ignore all the other Optional Filter Properties. Observe above that I have mentioned that "Smart Identification mechanism includes the .... property" . So the previous properties would also be present along with the newly included property for the filtering.
But we didnt see any name, title or openurl property in the local object repository, right ? Then how did QTP know this ? Try clicking on the + sign in the object repository.

So why was this not shown ? Thats because QTP didnt need it earlier but now it needed it when it kicked in the Smart Identification AND SO this is one of the main reason that Smart Identification may not be something that you would want to enable !! Oh my God...did I just say that ? Well yes, its because when you enable Smart Identification, you never know which property QTP is going to use to "smartly" detect the object. Your test script could end up entering values in the wrong field or testing the wrong object just because QTP "smartly" identified your object. So though this technique may be considered a good feature in some cases, I have never enabled this to True as it gives me more control on my test because if an object was unable to be identified I would like to know why it was not identified. If I enabled this, I would just ignore the results and assume everything went well. Believe me, I have gone through this a couple of times. However as I have mentioned earlier also, a feature is always good to have. You never know when you will need it.

Hope this example helped you in understanding this concept. Suggestions are always welcome.

I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (0)

Start and Stop Windows Services

Today we will be dealing with something not a QTP specific feature but its more to do with VB script. Lets say we need to start or stop a windows service like DHCP Client, Netlogon etc. This can be automated using VB script and in QTP without the need to open the Services window. Lets see how to do this.
Certain tests might need to be developed by starting or stopping certain services and then validate certain conditions. So this should be very helpful while developing certain tests. The basic code has been taken from MSDN where a very good example has been given.
There are a few things that we would be doing here
Get the WMI (Windows Management Instrumentation or Windows Management Interface) object
Execute a query to get the list of services
Start/Stop the service
Below you can see how we can get the list of all services. Click on the image to see the code.



To start or stop a service all that we need to do is to use the StartService() or StopService() method.  However, for that we would need to modify our query slightly. This is what we would need to do.Click on the image to see the code.





Notice the extra "quotes" used for the service name and that is because in the query we would need to have the filter in quotes.
Hope this helped.

I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (0)

Visitors

Website Counter