Have you ever encountered virtual memory issues when running long QuickTest Professional or Unified Functional testing scripts? They tend to occur while running either long overnight tests, or tests that have a ton of iterations. (If you're a sadist, your scripts might do both.)
Here are three things that might be causing your virtual memory issue:
- Not defining all your functions in a global function library
- Your application is not releasing memory
- QTP/UFT is not releasing memory
Place all your functions in a global function library
A leading cause of virtual memory issues is when local variables and functions are used within Actions. When this approach is used, QuickTest does not release its memory until it closes.
For example, if you have an action that iterates 1,000 times and you've defined 10 local variables, after 1,000 iterations enough memory will have been allocated for 10,000 variables! Things get even crazier if you're using an action-based framework that involves multiple actions calling each other.
The medication to relieve some of these memory allocation symptoms is to move all your variables and functions into a QTP VBScript library. Creating a function library won't solve all your memory usage issues, but it will help drastically minimize your memory usage.
Under QTP's File>settings>Resources section, you can point to your function library using the add button to associate your function library with the test script.
Once your script has a reference to the function library, you'll be able to call all the functions by typing them directly into your script. By creating a library file, you make your functions accessible to all your UFT scripts. Not only will this alleviate virtual memory issues, but it also will help:
- Simplify code for easier readability and maintenance
- Allow you to override an existing object method
- Abstracts your code for use and reuse in scripts, business components and recovery scenarios
If you don't know how to create a function library, take a look at the following example.
Creating a Library File
To create a function library you can either select File>New>Function Library in QuickTest Professional, or create a new file in a text editor like Notepad. For example:
- Create a new file in Notepad.
- Enter the following:
Function testMsg(firstName, lastName) msg = "Hello " & lastName &"," & firstName msgbox msg End Function
- Save as myFunction.txt to your C drive.
- In UFT/QTP, select File>New test.
- In the new test, click on File>Settings>Resources click on the add (+) button.
- If you get a “Relative Path” dialog, click No.
- The myFunction.txt library should now show up under the Resources section. Click on the “Test Settings” apply button.
- In your test, under the expert view, begin typing in the function name testMsg. Notice how the parameters for the function are shown.
- Enter the name:
testMsg “Colantonio”,”Joe”
- Click Run.
Your application is not releasing memory
There's no real solution for this if you're testing an application that's a memory hog. But in general, you might be able to free up some memory by minimizing the application. If minimizing doesn't help you should try starting and stopping your application for each test, or create a script that stops and restarts your application after a few tests have run. This is an issue I've commonly encountered when testing against IE, and I've found that minimizing the browser tends to solve things much of the time.
QTP/UFT is not releasing memory
Let's be honest. QTP/UFT itself can be a huge memory drain on your tests. If you're running tests that take hours and have lots of iterations you're inevitable going to encounter some issues. My advice is to restart QTP/Unified Functional Testing during replay, which will help to free up any memory that QuickTest Pro is holding onto. To do this you can use QTP's Automation Object Model. HP's knowledge base has a pretty cool code example on how to use AOM, as well as environment variables to help determine when to restart QTP after number of iterations:
(Source: The rest of this post is taken directly from HP's KB Site) The following set of instructions is a proposal with a on to generic approach to handle scenarios where QTP needs to be restarted:
1. Create a .vbs file (using AOM statements) that can be called from within QuickTest Professional. The .vbs file should check:
If QuickTest Professional is running, modify a couple environment variables (these will control the iterations) and shut down QuickTest Professional.
If QuickTest Professional is not running, launch it. Set some run-time settings, and start the script execution.
Example contents of the .vbs file:
' Wait 2 seconds to allow QuickTest Professional to complete replay overhead. wscript.sleep 2000 'Create a QuickTest Professional AOM object Set qtApp = CreateObject("QuickTest.Application") ' Check to see if QuickTest Professional is open (not necessarily running a script) if qtApp.GetStatus <> "Not launched" then set qtTest = qtApp.Test ' Get access to the test ' Get the current value of the "it_start" environment variable. This is the iteration start index. itstart = qtTest.Environment.Value("it_start") ' Get the current value of the "it_stop" environment variable. This is the iteration stop index. itstop = qtTest.Environment.Value("it_stop") ' Set the new values of the it_start and it_stop variables qtTest.Environment.Value("it_start") = CInt(itstop) + 1 drows = qtTest.DataTable.GetRowCount if drows > CInt(itstop) + 4 then stp = CInt(itstop) + 4 else stp = drows end if qtTest.Environment.Value("it_stop") = stp ' Close QuickTest Professional qtApp.Quit end if ' Wait 2 seconds to allow QuickTest Professional processes to end wscript.sleep 2000 ' Launch QuickTest Professional and make it visible qtApp.Launch qtApp.Visible = True ' Open the test script. Update to have full path to your test script qtApp.Open ' Get the current value of the "it_start" environment variable itstart = qtApp.Test.Environment.Value("it_start") ' Get the current value of the "it_stop" environment variable itstop = qtApp.Test.Environment.Value("it_stop") ' Set the Test Iterations for the script qtApp.Test.Settings.Run.IterationMode = "rngIterations" qtApp.Test.Settings.Run.StartIteration = itstart qtApp.Test.Settings.Run.EndIteration = itstop ' Run the test qtApp.Test.Run ' Release the QuickTest Professional object Set qtApp = Nothing
Note: Update the .vbs file to specify the full path to the test you wish to restart.
2. Open your test script, and go to Test -> Settings.
3. In the Environment tab, select “User-defined” in the Variable type field.
4. Enter two new variables, it_start and it_stop. (You can use other names, if you wish, but you will need to change the vbs file also.)
5. Set the it_start value to 1. Set the it_stop value to the number of iterations you want to complete before restarting QuickTest Professional (for example, 1000).
6. At the end of the script (or in the last action), add code that will call the .vbs file when appropriate.
Example:
If Environment("TestIteration") = 1000 Then ' 1000 iterations complete. Restart QuickTest Professional SystemUtil.Run "closeQTP.vbs" End If
In the above example code, the Test Iteration Environment variable is retrieved and checked to see if it has reached the limit set in step 5 (1000 iterations in the example). If the iteration limit has been reached, the .vbs file is launched. The start and stop iterations will be captured and stored and QuickTest Professional is restarted (if needed).
Make sure you update the .vbs file reflect the iteration limit you set in your script.
You should be able to start your script now and it will shut down and restart QuickTest Professional after x iterations.
Notes:
Each time QuickTest Professional re-launches and starts to replay the script, a new test results folder will be created. Using AOM you can have some control over the test results folders, but you should not use the same folder for each launch of the script if you need to save the test results (QuickTest Professional will overwrite the previous results, not append to them).
Some QuickTest Professional test environments, such as Web, require the application to be started after QuickTest Professional. Keep this in mind and structure your test as needed to allow you to restart the application if required.
You should use the VBS file to launch the test script.
What worked for me when I had perfomance issues (ulcers) was changing CloseToolAfterRuns=1 in the mic file in the
QTP bin directory. Since then, I can run hundreds of tests without issues.
Greg Encke » Awesome – thanks for the tip!
Hi Joe
My method is a little like yours but instead of iteration number being the trigger to exit each action I use QTP’s memory usage as the trigger point. This allows for tests where action iterations branch depending on the data under test, ie more branches using more memory resulting in less iterations, so fixed iteration restarts could still result in QTP memory failure. This of course be extended to any other application or system monitor variable or a combination.
If the memory limit gets reached each action is exited to allow for a clean exit of the application under test. An output Test parameter is then parsed to the calling vbs that started the test which has the loop below which simply restart the entire test (because my tests are data driven and the test writes back to the database which rows have been tested it will auto load only the untested rows into the datatable, if testing by iterations just pass the iteration to start from as a Test parameter output):
Do
Set oAppQTP = CreateObject”QuickTest.Application”)
…setup qtp options settings etc
oAppQTP.open sTestPath
Dim oTestParams
Set oTestParams = oAppQTP.Test.ParameterDefinitions.GetParameters()
‘run test
oAppQTP.test.run oTestResultOpt,true,oTestParams
‘get output from test – could also parse iteration number to restart at etc
sFlgQTPMemoryLimitReached = oTestParams.Item(“sFlgQTPMemoryLimitReached”).value
oAppQTP.test.close
oAppQTP.quit
set oAppQTP=nothing
…
Loop until sFlgQTPMemoryLimitReached=”FALSE”
In QTP 11 use local system montior to create a memory monitor on QTP.EXE or if your only running QTP9 then code some windows system memory querys.
eg. the code inside each action:
If SystemMonitor.GetValue(“QTPro”,”Memory Usage (in MB)”)>=iQTPMemoryLimitMB
TestArgs(“sFlgQTPMemoryLimitReached”) = “TRUE”
ExitAction
else
TestArgs(“sFlgQTPMemoryLimitReached”) = “FALSE”
End If