Relevant Codes (by Anshoo Arora)

A Test Development Resource for HP QuickTest Professional.

GUI Objects VBScript & Try Catch Finally

by Anshoo Arora on August 30, 2010

VBScript’s error handling techniques have been quite limited to On Error statements, and even though they satisfy our needs to some extent, the lack of incorporating dynamic behavior with them has been a much bigger issue. Lee Harvey here shows how Classes can be extended to create simple Try-Catch-Finally statements with just a bit more work. I like this technique, and have been using it for the past few days with success. We know that this is not the best solution that is possible with a scripting language (JS does a lot better!), but its a start and a terrific workaround (thanks Lee!).

Creating Try-Catch-Finally Statements in VBScript

If you have already read Lee’s article, you can skip this part. Otherwise, a simple implementation is shown below:

  1. As soon as the class executes, it enters Class_Initialize – Try statement
  2. It encounters an error – Err.Raise 1002
  3. As soon as it encounters an error, the Try statement (Class_Initialize) immediately ends execution
  4. Because we’re releasing the Class reference using Set NewTryCatchFinally = Nothing right after initializing it, the Class enters Class_Terminate
  5. Class_Terminate calls the Catch subroutine
  6. When Catch runs in its entirety, Class_Terminate executes
On Error Resume Next
 
Class TryCatchFinally
 
    Private Sub Class_Initialize 'Try
        Print "Entering Try.." & vbNewLine
 
        Err.Raise 1002 'Raise a Syntax Error
        MsgBox "This line will not execute"
    End Sub
 
    Private Sub Catch 'Catch
        If Err.Number = 0 Then Exit Sub
 
        Print "Entering Catch.."
        Print "Error caught: " & Err.Description  & vbNewLine
 
        Err.Clear
    End Sub
 
    Private Sub Class_Terminate : Catch 'Finally
        Print "Exiting.." 
    End Sub
 
End Class
 
Set NewTryCatchFinally = New TryCatchFinally : Set NewTryCatchFinally = Nothing

The output of executing the above code should be the following:

Try Catch Finally Implementation in VBScript

We can see from the result that as soon as the Class executes, it enters Class_Initialize. When it encounters an error, it enters into Class_Terminate which contains (and executes) the Catch method. A simple yet such an elegant solution!

Utility Class & Error Handler

In this article, I will try to implement the technique with QTP’s GUI objects. To begin, let’s create a simple Login class with the following methods:

  1. CheckPage
  2. CheckImage
  3. Login

The Login Class outputs the result through the Result property:

A simple Login Class
On Error Resume Next
 
Class Login
 
    Public Property Get Result
        Result = CheckPage And CheckImage And Login
    End Property
 
    Private Function CheckPage
        MsgBox "CheckPage" : CheckPage = True
    End Function
 
    Private Function CheckImage
        CheckImage = False
 
        Browser("title:=Welcome.*").WebElement("text:=Relevant Codes").Click 'Error here!

        MsgBox "Error!" 'This will not execute
    End Function
 
    'This will not execute
    Private Function Login
        MsgBox "Login"
    End Function
 
End Class
 
Dim NewLogin : Set NewLogin = New Login

Above, the Result property of the Login Class is called, which first executes CheckPage, then CheckImage and finally Login. Note that Login will only execute if CheckImage runs without any errors.

Let’s create another class that calls the methods of the original Login class, but with the error handling capabilities of a Try-Catch-Finally statement. This is also the Class that will always execute the original Login class because that’s where the actual error handling using Try-Catch-Finally exists.

Try..Catch..Finally with Class_Initialize & Class_Terminate
Class LoginHandler 'LoginHandler start

    Public bResult
 
    Private Sub Class_Initialize
         Print "Entering Try.." & vbNewLine
         bResult = NewLogin.Result
    End Sub
 
    Private Sub CatchErr
        If Err.Number = 0 Then Exit Sub
 
        Print "Entering Catch.."
        Print "Error: " & Err.Description & vbNewLine
 
        Err.Clear
    End Sub
 
    Private Sub Class_Terminate : CatchErr
        Print "Exiting.."
    End Sub
 
End Class 'LoginHandler end

Set NewLoginHandler = New LoginHandler
Set NewLoginHandler = Nothing
Set NewLogin = Nothing

The Class_Initialize method of the class calls the Result property of the Login class. Once Result is called, it executes all the methods called by the Result property. If any error occurs, CatchErr is immediately called by Class_Terminate and later, all code inside the Class_Terminate method is executed.

Output of executing Login Class & LoginHandler:

QTP Print Log

Method Containing the Error?

By including the name of each method in the very first line, we can also find out where exactly the error occurred. This, however, I agree is quite time consuming and repetitive work. The only alternative to this has been shown by PowerDebug Beta. However, if you would like to extend the above approach in VBScript, this *may be* the only possible approach. I’ve been wrong before, and would love to see a technique which simplifies the method naming approach used below.

Login Class with Method Names
On Error Resume Next
 
Class Login 'Login start

    Public sMethod
 
    Public Property Get Result
        Result = CheckPage And CheckImage And Login
    End Property
 
    Private Function CheckPage
        Me.sMethod = "CheckPage"
 
        MsgBox "CheckPage" : CheckPage = True
    End Function
 
    Private Function CheckImage
        Me.sMethod = "CheckImage"
 
        CheckImage = False
        Browser("title:=Welcome.*").WebElement("text:=Relevant Codes").Click 'Error here!
        
        MsgBox "Error!" 'This will not execute
    End Function
 
    Private Function Login 'This will not execute
        Me.sMethod = "Login"
 
        Msgbox "Login"
    End Function
 
End Class 'Login end
Dim NewLogin : Set NewLogin = New Login
LoginHandler (Outputs Method Names)
Class LoginHandler 'LoginHandler start

    Public bResult
 
    Private Sub Class_Initialize
         Print "Entering Try.." & vbNewLine
         bResult = NewLogin.Result
    End Sub
 
    Private Sub CatchErr
        If Err.Number = 0 Then Exit Sub
 
        Print "Entering Catch.."
        Print "Error occured in: " & NewLogin.sMethod
        Print "Error: " & Err.Description & vbNewLine
 
        Err.Clear
    End Sub
 
    Private Sub Class_Terminate : CatchErr
        Print "Exiting.."
    End Sub
 
End Class 'LoginHandler end

Set NewLoginHandler = New LoginHandler
Set NewLoginHandler = Nothing
Set NewLogin = Nothing

View code.

Output of executing Login Class & LoginHandler:

QTP Print Log

Notes

After using this technique for several days and manipulating it a bit from the original work, I have found some success. However, implementing Handler classes when the scope of the utility class increases can be quite challenging, and time consuming. I still believe its a start to something that we haven’t witnessed in QTP (yet). To be honest, I still prefer the old way of doing things where I can branch out most of my GUI code in conditional statements – which has enabled me to always create more comprehensive reporting.

My recommendation would be to use this approach with VBScript code instead of using it for QTP’s GUI objects, ofcourse, until absolutely necessary. Most of my usage for the above technique has been with pure VBScript code which has enabled me to create better error handling. In an upcoming article, I will show how this technique will be used to handle Excel errors and recover from them in the CatchErr method using a Select Case block. Including Try-Catch-Finally statements within Try-Catch-Finally statements is quite easily done in .NET, but its very complex to perform the same operation with VBScript. I’m still happy to have a start though.

If you have any questions, please ask them in the comments section.

{ 3 comments… read them below or add one }

1 Varun September 22, 2010 at 8:00 am

We have been using Call Chain Mechamism and Error Handler combined since long… and it is working fine….
you can give your comparison comments

Reply

2 Anshoo Arora September 29, 2010 at 3:11 pm

Varun,

I’m not sure I understand. Can you please show how you’ve used a Call Chain Mechanism to implement a Try-Catch-Finally??

3 Jenny July 28, 2011 at 2:21 am

Even I would also love to know how to implement this call chain mechanism.

Reply

Leave a Comment

Previous post:

Next post: