November 19, 2010

QTP 10 first impressions: Meh

This week, QTP 10 was installed at our workspace. We upgraded from 9.1 to 10, so we could also experience all new features of 9.5.
First of all, this is written from my own perspective. I don't use the object repository, the default report, multiple actions or the native QTP connection. I know, these things are improved, but I cannot write about them.

The good things
OK, the function viewer is great. Unfortunately, it does not display classes and properties, while functions and subs inside classes are displayed as Publics. What was the problem with displaying classes as expandable trees and with properties and methods underneath you would think.
Also functions starting with a square bracket [ are not rendered in the function viewer.

The Todo list could become quite handy, but after years working without it, I can... do without it.

The bad things
200 Megs. That is the amount of RAM QTP consumes if I start it, even without any scripts loaded. Just to be fair, I think it is more a problem with the installation and that only 2 of the 30(!!) patches are loaded by default, but I cannot change it and it bothers me. So I categorized it as a bad thing.
This brings me to the next point: Hangs. It hangs a lot and it makes my PC slow, especially Internet Explorer and Windows Explorer. Again, I think it is a problem with the installation and I have to look it up and/or ask support to our godlike and always kind administrators (without them I cannot do anything, so playing nice is important. Maybe they read this.). I think that is a bad thing.

The "Public Default Property Let Foobar()
End Property
End Property
End Property
End Property" syndrom.
WHY???

Variable typing is messed up:
Print "123" + "321" results in "123321". Are we switching to Javascript or what? I thought VBScript was proud of their dynamic var typing (as if that is a good thing). Don't mess with my brain by changing the working of the + sign. Make variables dynamic or make operators dynamic, not both!

Variable conversion is different:
I noticed a classical rounding error: subtracting two numbers can end up with a very small decimal part. Like (not a real example):
4.32 + -0.32 results in 4.00000000000014
Annoying when you want to compare two numbers during automated testing.

The bad things that remain
No autocomplete inside libraries.
No jump-to-function from libraries to other libraries.
The find is still buggy, with annoying "forward or backward" radiobutton.
'Sometimes a duplicate code line overwrites other code' bug.
No declaration check on variables other than during runtime.
Set myCompositeClass = [new componentA](new componentB) results in a syntax error while it is theoretical correct.

Conclusion
I think my installation is not correct, so I had a bad week and am a bit prejudiced about my new QTP. The function viewer certainly speeds up my work, unfortunately it is implemented poorly. The problems I have with my memory and performance is probably due to the installation, on my run PCs I do not have these problems, only on my development machine (but why couldn't it be correct the first time?). The changed variable conversion and operator functionality is really not a good thing. Besides that it influences our existing tests, it is not an improvement. The remaining annoyances stays, and from a user perspective this is merely a QTP 9.6 release and not a 10 major version. I think it is time HP/Mercury will get a real competitor and we get a real choice what automated test software we can use. They are now functioning like our dutch railway system: "Use our system or don't; we don't bother".

November 18, 2010

QTP and how to create an autodestruct class

Somewhere in our application under test, we have a webpage that only continues loading if the mouse is slightly moved. The page is loading while QTP is syncing the page. During the syncing, I cannot send mouse move commands from QTP to the application.

I don’t know why the application has this feature and “they” don’t want to fix it, so… work around time.


I created a low profile mousemove application in C that only does one thing: After 5 seconds it moves the mouse cursor one pixel to the right. And after 5 seconds it moves the cursor one pixel to the left. Repeat.


Actually it is an cut down version of out nolock.exe application, this application sniffs the mouse cursor movements. If it detects inactivity for 10 minutes, it moves the mouse cursor slightly in the same manner as discussed above. This program has a shortcut in the Windows Startup folder and prevent the screen from locking when automated tests are running.


But back to the autodestruct class. We want to have a “single line of code” to implement this in any function where we expect the screen to hang. This class starts the mouse moving as soon as it is created and stops the mouse moving when it is destroyed.


Private Const MOUSE_MOVE_APPL_NAME = “mouseMover.exe”

Private Const BINARIES_FOLDER = “C:\QTP_Framework\tooling\bin\”


Class cls_AutoDestructMouseMover

Private Sub class_initialize()

‘ Put the cursor somewhere to prevent it is on the extreme right position

call extern.SetCursorPos(100, 150)

‘ Run the external mouse move application

systemutil.Run BINARIES_FOLDER & _

MOUSE_MOVE_APPL_NAME, "", BINARIES_FOLDER

End Sub


Private sub class_terminate()

‘ Kill the mouse move application

systemUtil.CloseProcessByName MOUSE_MOVE_APPL_NAME

End Sub

End Class


And make a public accessor for the class:


Public function [new AutoDestructMouseMover]

Set [new AutoDestructMouseMover] = new cls_AutoDestructMouseMover

End Function


Now, we can implement the class whenever it is needed:


Public Function Example

‘ Create the object, make it move!

Dim autoDestructMouseMover : Set autoDestructMouseMover = [new AutoDestructMouseMover]

Call TimeConsumingFunction


‘ Destroy the object, let it stop!

Set autoDestructMouseMover = Nothing

End Function


But wait, we called it an “autodestruct” class, what about the autodestruct? Well, The last line of code is not necessary. When the Example function ends, it automatically destroys all variables and objectpointers with local scope. We can simply reduce the implementation of the autodestructor to one line of code (I know, I am cheating with the semicolon):


Public Function Example

‘ Create the object, make it move!

Dim autoDestructMouseMover : Set autoDestructMouseMover = [new AutoDestructMouseMover]

Call TimeConsumingFunction

End Function


And the autoDestructMouseMover object is automatically destroyed with the function clean up.


Nice. But are there more appliances for an autodestruct object? Oh, yes.

What do you think an autoDestructStackTracer?

Class cls_AutoDestructStackTracer

Private procedureName_

Public Sub Init(pName)

procedureName_ = pName

Print now & “ ADST Start “ & procedureName_

End Sub


Private sub class_terminate()

Print now & “ ADST Exit “ & procedureName_

End Sub

End Class


And make a public accessor for the class:


Public function [new AutoDestructStackTracer](pName)

Set [new AutoDestructStackTracer] = new cls_AutoDestructStackTracer

[new AutoDestructStackTracer].Init pName

End Function


And let’s test it:


Public Function ExampleParent

Dim autoDestructStackTracer : Set autoDestructStackTracer = [new AutoDestructStackTracer](“ExampleParent”)

Print “I’m with ExampleParent now!”

Call ExampleChild

End Function


Public Function ExampleChild

Dim autoDestructStackTracer : Set autoDestructStackTracer = [new AutoDestructStackTracer](“ExampleChild”)

Print “I’m with ExampleChild now!”

End Function


Call ExampleParent

Output:

18-11-2010 9:06:06 ADST Start ExampleParent

I’m with ExampleParent now!

18-11-2010 9:06:06 ADST Start ExampleChild

I’m with ExampleChild now!

18-11-2010 9:06:06 ADST Exit ExampleChild

18-11-2010 9:06:06 ADST Exit ExampleParent


And consider uses of an [new AutoDestructFunctionTimer](pName) to measure the performance of your different functions. Or a [new ScreenShotOnFunctionExit] (and more generalized: [new ExecuteOnFunctionExit](“call PerformScreenshot”)) when you have lots of functions with multiple exit points.