Handling Errors in Script Extensions

Applies to TestComplete 15.0, last modified on October 21, 2021
About

During execution of the script extension’s services, different errors may occur. For example, the user may specify an incorrect value for a runtime object’s property or a keyword test operation’s parameter, an action may fail to create the checkpoint due to a certain reason, and so on. Script extensions must properly handle such situations.

To handle exceptions that may occur in script extensions, you can use “native” means of the scripting languages that are used to develop extensions -- VBScript and JScript.

In VBScript, you can handle errors using the On Error Resume Next statement in conjunction with the Err object. The On Error Resume Next statement turns error handling on and commands the VBScript engine to continue script execution even if an error occurs. After executing problematic statements, you can check the Err object to see if any of them raised an error:

VBScript

Sub DoSomething
  ' Enable exception handling
  On Error Resume Next

  ' Do something
  ...

  ' Check if there was an error
  If Err.Number <> 0 Then
    ' Handle the error
    ' For example, display it to the user:
    aqDlg.ShowError Err.Description

    ' Clear the error indicator
    Err.Clear
  End If

  ' Proceed
  ...

End Sub

In JScript, you can handle exceptions using the try...catch...finally statement. The try block contains code that may raise an error, the catch block -- code that handles the error, the finally block -- code that is executed regardless of whether or not an exception occurs in the try block:

JScript

function DoSomething()
{
  try
  {
    // Do something
    ...
  }
  catch (e)
  {
    // Handle the error
    // For example, display it to the user:
    aqDlg.ShowError(e.description);
  }
  finally
  {
    ...
  }

  // Proceed
  ...
}

For more information about exception handling in VBScript and JScript, refer to the MSDN Library. For example, you can see the description of the On Error statement and Err object to learn more about exception handling in VBScript, and the description of the try...catch...finally statement and Error object to learn more about exception handling in JScript.

Notifying User About Errors

Besides handling exceptional situations, script extensions should include means to notify a user about occurred errors. The way in which the script extension’s services can do this depends on the service type -- action, object, or keyword test operation.

Record-time and design-time actions can notify a user about errors using the aqDlg.ShowError or aqDlg.MessageDlg methods. For example:

JScript

var Result;  // Holds the result of the checkpoint creation (success/failure)

...

if (! Result)
  aqDlg.ShowError("Failed to create the checkpoint.");

VBScript

Dim Result  ' Holds the result of the checkpoint creation (success/failure)

...

If Not Result Then
  aqDlg.ShowError "Failed to create the checkpoint."
End If

As for runtime objects, since they are supposed to be used during execution of automated tests, error notifications must be done programmatically, not visually. To illustrate possible solutions, suppose that the script extension provides the SampleObject runtime object and this object has the Number property that can hold integer values:

JScript

var number;  // An internal variable that holds the Number property value

// The get method of the Number property
function GetNumber()
{
  return number;
}

// The set method of the Number property
function SetNumber(Value)
{
  number = aqConvert.VarToInt(Value);
}

VBScript

Dim number  ' An internal variable that holds the Number property value

' The get method of the Number property
Function GetNumber
  GetNumber = number
End Function

' The set method of the Number property
Sub SetNumber(Value)
  number = aqConvert.VarToInt(Value)
End Sub

In the set method of the Number property, we would like to report an error if the specified value cannot be converted into an integer. We can do this in one of the following ways:

  • Use the Log.Error or Log.Warning method to post an error or warning message to the test log. For example:

    JScript

    function SetNumber(Value)
    {
      try
      {
        number = aqConvert.VarToInt(Value);
      }
      catch (e)
      {
        Log.Error("Unable to set the Number property value.", e.description);
      }
    }

    VBScript

    Sub SetNumber(Value)
      On Error Resume Next

      number = aqConvert.VarToInt(Value)

      If Err.Number <> 0 Then
        Log.Error "Unable to set the Number property value.", Err.Description
      End If
    End Sub

  • Add a special property or method that will return the status of the last method execution. The object’s members should set the status value before returning the control flow to the caller routine. The value 0 can correspond to successful execution, any other value - to error.

    The example below illustrates this approach. It extends our sample object with the LastStatus property that returns the status code of the last operation performed over the object:

    JScript

    var number;
    var last_status;  // An internal variable that holds the LastStatus property value

    // The set method of the Number property
    function SetNumber(Value)
    {
      try
      {
        number = aqConvert.VarToInt(Value);
        last_status = 0;  // The property value has been successfully modified
      }
      catch (e)
      {
        last_status = e.number;  // An error indicating that Value could not be converted to an integer
      }
    }

    // The Get method of the LastStatus property
    function GetLastStatus()
    {
      return last_status;
    }

    VBScript

    Dim last_status  ' An internal variable that holds the LastStatus property value

    Sub SetNumber(Value)
      On Error Resume Next

      number = aqConvert.VarToInt(Value)
      last_status = Err.Number
      ' last_status is 0 if Value was successfully converted to an integer.
      ' Otherwise, last_status contains the error code.
    End Sub

    ' The get method of the LastStatus property
    Function GetLastStatus
      GetLastStatus = last_status
    End Function

    Here is how you can check the object’s LastStatus property from test scripts:

    JavaScript, JScript

    function UsingLastStatus()
    {
      // This line causes an internal error in SampleObject
      SampleObject.Number = "not a number";

      if (SampleObject.LastStatus != 0)
        Log.Error("Unable to set the Number property value");
    }

    Python

    def UsingLastStatus():
      # This line causes an internal error in SampleObject
      SampleObject.Number = "not a number"
    
      if (SampleObject.LastStatus != 0):
        Log.Error("Unable to set the Number property value")

    VBScript

    Sub UsingLastStatus
      ' This line causes an internal error in SampleObject
      SampleObject.Number = "not a number"

      If SampleObject.LastStatus <> 0 Then
        Log.Error "Unable to set the Number property value"
      End If
    End Sub

    DelphiScript

    procedure UsingLastStatus;
    begin
      // This line causes an internal error in SampleObject
      SampleObject.Number := 'not a number';

      if SampleObject.LastStatus <> 0 then
        Log.Error('Unable to set the Number property value');
    end;

    C++Script, C#Script

    function UsingLastStatus()
    {
      // This line causes an internal error in SampleObject
      SampleObject["Number"] = "not a number";

      if (SampleObject["LastStatus"] != 0)
        Log["Error"]("Unable to set the Number property value");
    }

  • Return the status of the object’s method execution via the method’s return value. This approach can only be used by the object’s methods that are not supposed to return other values. It cannot be used in the get and set methods of properties.

    To illustrate this approach, suppose that our sample object has the IncNumber method that increases the stored number by the specified value. To prevent exceptional situations, this method verifies the type of the passed parameter and returns an error code if the parameter type is invalid (that is, any but integer):

    JScript

    var number;

    function IncNumber(Value)
    {
      var result = 0;

      if (aqObject.GetVarType(Value) == varInteger)
        number += Value
      else
        result = 1;

      return result;
    }

    VBScript

    Dim number

    Function IncNumber(Value)
      Dim result
      result = 0

      If (aqObject.GetVarType(Value) = varInteger) Or (aqObject.GetVarType(Value) = varSmallInt) Then
        number = number + Value
      Else
        result = 1
      End If

      IncNumber = result
    End Function

    The example below demonstrates how you can check the method’s return status in the test code:

    JavaScript, JScript

    function UsingReturn()
    {
      SampleObject.Number = 42;

      var res = SampleObject.IncNumber(5);   // OK, ...
      if (res != 0)
        Log.Error("Unable to increment the Number property");    // so this line will not be executed

      res = SampleObject.IncNumber(true);    // The parameter type is incorrect, ...
      if (res != 0)
        Log.Error("Unable to increment the Number property");    // ... so we'll have this error posted to the log
    }

    Python

    def UsingReturn():
      SampleObject.Number = 42
    
      res = SampleObject.IncNumber(5)   # OK, ...
      if (res != 0):
        Log.Error("Unable to increment the Number property")    # so this line will not be executed
    
      res = SampleObject.IncNumber(True)    # The parameter type is incorrect, ...
      if (res != 0):
        Log.Error("Unable to increment the Number property")    # ... so we'll have this error posted to the log

    VBScript

    Sub UsingReturn
      Dim res

      SampleObject.Number = 42

      res = SampleObject.IncNumber(5)     ' OK, ...
      If res <> 0 Then
        Log.Error "Unable to increment the Number property"    ' ... so this line will not be executed
      End If

      res = SampleObject.IncNumber(True)  ' The parameter type is incorrect, ...
      If res <> 0 Then
        Log.Error "Unable to increment the Number property"    ' ... so we'll have this error posted to the log
      End If
    End Sub

    DelphiScript

    procedure UsingReturn;
    var res;
    begin
      SampleObject.Number := 42;

      res := SampleObject.IncNumber(5);      // OK, ...
      if res <> 0 then
        Log.Error('Unable to increment the Number property');    // so this line will not be executed

      res := SampleObject.IncNumber(true);    // The parameter type is incorrect, ...
      if res <> 0 then
        Log.Error('Unable to increment the Number property');    // ... so we'll have this error posted to the log
    end;

    C++Script, C#Script

    function UsingReturn()
    {
      SampleObject["Number"] = 42;

      var res = SampleObject["IncNumber"](5);    // OK, ...
      if (res != 0)
        Log["Error"]("Unable to increment the Number property");    // so this line will not be executed

      res = SampleObject["IncNumber"](true);     // The parameter type is incorrect, ...
      if (res != 0)
        Log["Error"]("Unable to increment the Number property");    // ... so we'll have this error posted to the log
    }

Keyword test operations can use a combination of the described approaches. For instance, at design-time they can display errors using the aqDlg.ShowError or aqDlg.MessageDlg methods, at run time -- post error messages to the test log using the Log.Error or Log.Warning method.

See Also

Script Extensions
Creating Script Extensions
Creating Custom Actions
Creating Runtime Objects
Creating Keyword Test Operations
Debugging Script Extensions

Highlight search results