Monday, 3 September 2012

QTP Clean Up Script Perfection II

Following on from the last time I posted something like this I have largely overhauled my clean up procedure.  

I suppose this isn't really limited to QTP as it's mostly VBS code, and objects are identified through Windows/desktop calls.

So, it starts with a driving function. I think it's self explanatory thus far.


I don't want to go overboard explaining all the calls and stuff, I have pasted below what I believe to be a near-complete working copy of the code. You'll need to remove any custom functions which point to other things (e.g. fDone, shown in the above picture).

For each fCleanUpDialogs(intIterations) and fCleanUpBrowsers(intIterations) objects are gathered, and then I try to close each of these. Seems simple enough.

An example of fCleanUpDialogs(...)

Again, this makes subsequent calls to other functions. This is largely for tidiness, and allows for easy modification of this function without needing to think too much.

And here's my code (formatting and commenting has proven to be a bit mind-numbing, forgive the messiness):



Function fCleanUp(intIterations)
fDone "fCleanUp() [CALLING]", "Function called. Paramater intIterations: " & intIterations
Dim i
i = 0
Do while i < intIterations
If (fCleanUpDialogs(1) = 0) AND (fCleanUpBrowsers(1) = 0) Then
Exit Do
End If
i = i + 1
Loop
fDone "fCleanUp() [EXITING]", "Function exiting after " & i & " iterations."
fCleanUp = i
End Function


'********************************************************************************************
'    Function    fCleanUpDialogs
'    Automater: Matt S
' Purpose: A function with will close all dialogs currently present
' Returns: The number of dialogs that the clean up proc performed
' 0 means that there were no dialogs cleaned up
'********************************************************************************************
Function fCleanUpDialogs(intIterations)
   Reporter.ReportEvent micDone, "fCleanUpDialogs() [CALLING]", "Function called. Parameter intIterations: " & intIterations
   Dim oDialog
Do While intLoopCount < intIterations
'bDialogDetected = false
oDialog = null
On Error resume next
set oDialog = fGetADialog()
On Error goto 0
If isNull(oDialog) = False Then
If fCleanUpDialogs_tryClickButtonWithName(oDialog, "Cancel") = False Then
If fCleanUpDialogs_tryClickButtonWithName(oDialog, "OK") = False Then
If  fCleanUpDialogs_tryClickButtonWithName(oDialog, "Close")= False Then
fDone "fCleanUpDialogs() [WARNING]", "Dialog detected, but unable to recognise which button closes the thing"
End If
End If
End If
Else
Exit do
End If
intLoopCount = intLoopCount + 1
Loop
fDone "fCleanUpDialogs() [EXITING]", "Function exiting after " & intLoopCount & " iterations."
fCleanUpDialogs = intLoopCount
End Function


'Supports function fCleanUpDialogs
'********************************************************************************************
'    Function    fCleanUpDialogs
'    Automater: Matt S
' Purpose: A function with will attempt to click on a dialog's button, by button name
' Returns: True if click was successful, else false
'********************************************************************************************
Function fCleanUpDialogs_tryClickButtonWithName(oDialog, btnName)
If Dialog("hwnd:="&oDialog.getRoProperty("hwnd")&"").WinButton("text:="&btnName&"").Exist(1) Then
Dialog("hwnd:="&oDialog.getRoProperty("hwnd")&"").WinButton("text:="&btnName&"").Click
Reporter.ReportEvent micDone, "fCleanUpDialogs()", "Attempted to close a dialog by (successfully) clicking on button: " & btnName
fCleanUpDialogs_tryClickButtonWithName = true
Else
Reporter.ReportEvent micDone, "fCleanUpDialogs()", "Attempted to close a dialog but could not locate any button of name: " & btnName
fCleanUpDialogs_tryClickButtonWithName = false
End If
End Function


Function fGetADialog()
fDone "fGetADialog()", "Calling function fGetADialog()"
fGetADialog  = null 
If Browser("index:=0").Dialog("index:=0").Exist(1) Then
fDone "fGetADialog() [RETURNING]", "Successfully identified a dialog by searching for Browser(""index:=0"").Dialog(""index:=0"").Exist(1)"
set fGetADialog = Browser("index:=0").Dialog("index:=0")
Else
Dim oDialogDesc, oDialogs, oTemp
Set oDialogDesc = Description.Create
oDialogDesc("Class Name").value = "Dialog"
Set oDialogs = Desktop.ChildObjects(oDialogDesc)
If oDialogs.count > 0 Then
fDone "fGetADialog() [RETURNING]", "Successfully identified a dialog by searching for objects with Class Name = Dialog"
set fGetADialog = oDialogs(0)
End If
End If
End Function


Function fCleanUpBrowsers(intIterations)
fDone "fCleanUpBrowsers() [CALLING]", "Function called. Parameter intIterations: " & intIterations
Dim i
i = 0
Do While i
Dim oBrowser
oBrowser = Null
On Error Resume Next
set oBrowser = fGetABrowser()
On Error Goto 0
If IsNull(oBrowser) = True Then
Exit Do
Else
oBrowser.close
End If
i = i + 1
Loop
fDone "fCleanUpBrowsers() [EXITING]", "Function exiting after " & i & " iterations."
fCleanUpBrowsers = i
End Function


Function fGetABrowser()
fDone "fGetABrowser() [CALLING]", "Calling function"
fGetABrowser = null
If Browser("index:=0").Exist(1) Then
fDone "fGetABrowser() [RETURNING]", "Successfully identified a browser by searching for Browser(index:=0)"
set fGetABrowser = Browser("index:=0")
Else
Dim oBrowserDesc, oBrowsers, oTemp
Set oBrowserDesc = Description.CreateCreate
oBrowserDesc("Class Name").value = "Browser"
Set oBrowsers = Desktop.ChildObjects(oBrowserDesc)
If oBrowsers.count > 0 Then
fDone "fGetABrowser() [RETURNING]", "Successfully identified a browser when searching by Class Name = Browser"
set fGetABrowser = oBrowsers(0)
End If
End If
End Function

QTP Troubleshooting – Objects not recognized


In ALM11 I’ve had an issue with QTP. When running a test no objects were being recognised in the application. They should be, they have been before, the components work in other tests, but not one test, for no reason. Using the Object Spy I can see QTP clearly doesn’t know what to make of the Browser, thinking it’s just a Windows object.


This is a problem I’ve been dealing with on and off for the last couple of months, and I am pleased to announce that the culprit was a certain Component making an appearance at the start of my BPT Test. Sadly I haven’t worked out what exactly is the reason why this component has sent everything in to a spin, but I am happy enough that I know generally where the failure is, and that it is not with my entire test.

It was a scripted component which did a very simple check on an input parameter.

I have since moved the function from the first to the second step in my test and now everything works again.

If anyone knows about this issue feel free to leave a note in the comments.

Robot Framework, Basic Setup

Plug: Robot Framework is quick to setup, easy to write tests for, and super fast to triage failures in. The last point really sets it apart...