Mr. Cluey : Library : Except


Exception Handling

What went wrong

It's very easy to miss the trap in this code fragment, especially when writing it for the first time...

do
   SomethingThatFails () ;
except
   DoItTheOtherWay () ;

Clearly, you are anticipating that the application may fail. The problem is that, should the application fail in some unexpected way, your exception handler is at the very least going to throw away the real information about the new problem.

It is important, when deliberately trapping a particular exception, to first check that the exception is the one you expected.

The safer implementation of the code above looks like this:

do
   SomethingThatFails () ;
except
{
   ConfirmException( 123 ) ;
   DoItTheOtherWay () ;
}

ConfirmException is defined in except.inc. This function monitors the exception that got raised. If it is the one that we expected, the exception handler continues normally. However, if the exception is not the one we expected, it reraises the original problem. In other words, the exception handler now catches only the problems we anticipate.

ConfirmException is implemented to be able to handle trapping multiple exceptions. Only once have I actually needed this functionality; to be quite honest, I probably could have written my routine more carefully to eliminate the need. When trapping multiple exceptions, the rule is that you will want to handle each exception differently; thus, the syntax of the call changes.

do
   SomethingThatFails () ;
except
{
   switch ConfirmException( 123, 456 )
   {
      case 123: WorkAround123() ;
      case 456: WorkAround456() ;
   }
}

Applications

In general, there are two occassions where ConfirmException() is used.

The primary function is to trap known or anticipated problems in the application being tested, so that the test script can continue to execute, and produce meaningful results, even if there is a minor flaw in the application. This is explored in more detail in kbreport.

The secondary function is to use partner's exception handling to gather information which cannot be obtained any other way. One example, determining if a particular function has been defined, is discussed in Function.

Implementation

The implementation of ConfirmException is not terribly complex. A few details are worth mentioning.

The user defined type, EXCEPTION_TYPE, is used because script authors are not limited to the exceptions enumerated in 4test.inc. Predefined exceptions can, of course, be used when calling ConfirmException:

do
   Foo()
except
{
   ConfirmException( E_BITMAPS_DIFF_SIZE ) ;
   // etc.
}

The arguments are declared as varargs because that syntax makes more sense to this author than trying to implement the function to accept a list or an integer.

ConfirmException, when it catches an anticipated exception, returns the number of that exception. When only one exception is trapped, this is not terribly useful, but does no harm - in 4test, such returned arguments are harmlessly discarded. It isn't necessary to return the value - ExceptNum() will still allow the script access to the exception that was raised. I find the syntax of the call more elegant as written.

The original implementation of this library used two different functions; one for handling individual exceptions, and one for handling a list of exceptions. Having two different function calls makes it easier to search the source files to inspect where each aspect of the functionality is being used.


Mr. Cluey : Library : Except

Return to ATS Automated Testing Resources Page