Handling exceptions from a different unit

The engine of the Jscript language, used in TestComplete, does not support working with several units. Such a possibility is provided by the TestComplete itself. One of the side effects consists in the following situation: if we are in one unit inside the try...catch block calling the function from another unit, and this second function raises an exception, it will not be caught by the try block. In the result, TestComplete will stop script execution.

The simplest way to solve this challenge is creation of the try...catch block in the called function and using the returned value of the function for analysis in the function-call. This solution, however, may misfire in several situations, this is why in the given recipe we will consider one of the methods to intercept exceptions in the functions of another unit.

Getting ready

Before we start, we need to perform the following preparation steps:

  1. Create two new units UnitA and UnitB (right-click on the Script element, and go to Add | New Item).
  2. Place the following function into UnitA:
    function calledFunction()
    {
      Log.Message("Called function from UnitA");
      throw "exception from UnitA";
    }

    We will call this function from another unit.

  3. Into the UnitB unit, place the following code:
    function callerFunction()
    {
      Log.Message("Message from caller function");
      try
      {
        UnitA.calledFunction();
      }
      catch(ex)
      {
        Log.Message("Exception caught!", ex);
      }
    }

    In this function we are calling the calledFunction function from the UnitA, meanwhile trying to intercept all the arisen exceptions. If this function is launched, we would see that the exception is not intercepted, rather the following error message is displayed on the screen: Exception thrown and not caught.

    Namely this problem we are supposed to resolve right now.

How to do it...

In order to catch the exception from a different unit, we need to perform the following steps:

  1. Create a new call function and place it into any of the two existing units:
    function call(functionName)
    {
      var fnArray = functionName.toString().split("
    ");
      fnArray[0] = fnArray[1] = fnArray[fnArray.length-1] = "";
      return fnArray.join("
    ");
    }
  2. In the callerFunction function replace the direct call of the function (UnitA.calledFunction()) with the following programming construct:
    var str = call(UnitA.calledFunction);
    eval(str);
  3. Launch the callerFunction function. In the result, the error message will not appear, and in the log, we will have the following message written down: Exception caught!. If you select this message in the log, on the Additional information panel, we will see the text of the caught exception that is generated by the calledFunction function: exception from UnitA.

How it works...

Since exceptions from other units are not intercepted, our task consists of launching the code we are interested in from the current unit via the instrumental function call of the additional call function. In JScript language everything is an object, including a function. This is why we can pass the function as a parameter. Then, with the help of the toString method, we obtain the code of the very function as an ordinary text string. With the help of the split method, we transform this string into an array so that in the future we could remove all the unnecessary strings from it (the first two lines are the declaration of the function and the opening curved bracket, as well as the closing curved bracket). These lines are, for the sake of simplicity, to be replaced with empty lines.

In the result, in the array, we have only the body of the function left. The array will be transformed back into the string with help of the join method, and it will return the resulting string of code back to the callerFunction function). Further, with the help of the built-in eval function, we execute the code that was returned as a string with the call function. Since, this code is in fact executed in a single unit UnitB, we have a possibility to intercept the exception.

There's more...

Despite the fact that examined approach allows resolving a fairly complex problem, it is easy to see its shortcomings:

  • The given example allows launching only a function without parameters. Writing of the same function with parameters would significantly complicate the code of the call function.
  • The function implies that the code conforms to a specific style (the first line is the heading of the function, and the next line is the opening bracket). To better transform the function into the executable code, one would have to write up a smarter function.
  • In the result of adding the new function, we have in fact two lines of code instead of one line. Although, this could be simply resolved by joining the two lines of code into a single one:
    eval(call(UnitA.calledFunction));
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.195.225