FAQ

How can you prevent cascading errors?
(getting back to the base state

Detail

The recovery system is one of Silk Test’s best kept secrets. And that’s by design, because the recovery system is invisible to the user … or nearly so. Built into the product since its inception in 1992, the recovery system attempts to get the Application Under Test (AUT) back to a known base state after a testcase has been executed. This feature protects a suite of tests from the “domino effect” where a failure in one testcase causes the entire run to fail. Without it, the user would be required to add recovery code to each testcase and then hope for the best. In short, the recovery system was designed to support unattended testing.

What does the Recovery System do?

By default the recovery system carries out four tasks for client-server applications:

  • Ensures that the application or browser is running
  • Restores the application if it is minimized
  • Sets the application active
  • Closes any application child windows or dialog boxes

In addition to these tasks, the recovery system does the following for browser-based applications:

  • Waits for the browser to become ready
  • Ensures that browser toolbars, location textfield and status bar are displayed

How does the Recovery System Work?

The recovery system is stored in a file called defaults.inc in the directory where SilkTest is installed. Most of the action happens in an appstate function called DefaultBaseState (). This is the appstate that testcases are based upon by default.

The recovery system gets invoked automatically when a script or testcase is run. The flow of control differs slightly if tests are run from a testplan vs. from a main function in a .t file. When running testcase through SilkOrganizer (via a testplan), control first passes to the testcase that is being run. Before the testcase executes, the DefaultTestCaseEnter function is called. It calls SetAppState which by default calls DefaultBaseState. Then the testcase begins to run. If the testcase runs to completion or if an error is encountered that is not trapped with a do .. except, control passes to DefaultTestCaseExit. It logs any exceptions raised in the testcase and calls SetBaseState which by default calls DefaultBaseState.

When running tests through a main function in a .t file, there are two other recovery system functions that are invoked in a similar fashion. DefaultScriptEnter is called before the first testcase is run. It is NULL by default. DefaultScriptExit is called after the last testcase completes. It logs any errors that may occur outside of a testcase.

How can the Recovery System be configured?

As noted above, the recovery system functions are defined in defaults.inc. But there are times when the default functions are not sufficient to return the application to its base state. In some cases there are windows that need to be closed that are not children of the AUT’s main window. In other cases, it may be necessary to leave child windows open as in the case of a floating tool palette. Rest assured, SilkTest provides an array of ways in which the user can configure the recovery system. Here is a summary of the primary options:

  • wStartup is a member constant WINDOW of the AUT’s MainWin declaration. It can be assigned the 4Test identifier of the first window to be displayed when the application is invoked. This configures the recovery system to expect that window instead of the AUT’s MainWin.
     
  • wLeaveOpen is a member constant LIST OF WINDOW of the AUT’s MainWin declaration that can be assigned a list of 4Test identifiers of the windows that should not be closed by the recovery system.
     
  • Close Methods can be added to the declaration of any window that requires custom steps to successfully close the window. Keep in mind that the signature for your Close methods must always match that of the default: VOID Close (BOOLEAN bConfirm optional, BOOLEAN bSetActive optional). If you do not include the optional BOOLEAN arguments, the recovery system will encounter an error when calling your methods because the argument list will not match. Unfortunately the error is trapped within a do .. except statement in DefaultBaseState and is not reported. If a Close method has not been defined for a window to be closed, the recovery system will call a default Close method that can be configured via the Close TAB in the Agent Options dialog.
     
  • BaseState is an optional method that you can include in the window declaration of the AUT’s MainWin. Application specific steps to be carried out by the recovery system beyond the default tasks should be included in this method. If a BaseState method is defined it will be called by DefaultBaseState after the default tasks are executed.
     
  • AppStates are not intended to recover the AUT to a base state but rather transform it from one state to another. They provide a convenient way to store application tasks needed to get the application from the base state to a test state so that the code can be easily reused by many testcases. Appstates are invoked simple by appending the keyword appstate to a testcase and providing the name of the appstate function, e.g.

testcase MyTestCase appstate MyAppState

To declare an application state function use the keyword appstate. It is also possible to base an appstate upon another appstate creating chains of setup steps. The following is an example:

appstate MyAppState () basedon MyBaseState

  • Overriding default recovery functions – Sometimes there are application specific steps that need to be carried out before or in lieu of the default recovery tasks. By defining functions named TestCaseEnter, TestCaseExit, ScriptEnter and/or ScriptExit, the user is able to override the associated default recovery system functions. When these functions are defined, they are called instead of their default counterparts. If the default functionality is still desired, the built-in functions can be called from within the user defined overrides. For example to call DefaultTestCaseExit from within your custom TestCaseExit, the code will look something like this:

[-]TestCaseExit (BOOLEAN bException)
      [-] if (bException)
             [ ] ExceptLog ()
             bException = FALSE //Set the switch back to false
                                             //since the error has been reported.
                                             //If you forget to do this, the error
                                             //will get reported again when
                                             //you call DefaultTestCaseExit

       //perform some steps that the default recovery system
       //is not able to do successfully

       //now call the default function to complete the recovery tasks
       DefaultTextCaseExit (bException)

Gotchas and Other Tips

  • The recovery system helps to enforce good testcase design by discouraging test engineers from beginning one test where the previous test left off. It is always important to make each testcase independent by starting each from a known base state.
     
  • A testcase is really a function with special behavior. A function prefixed with the keyword testcase will automatically invoke the recovery system.
     
  • If you write your own TestCaseExit function be sure that the first step reports any errors that may have been raised in a testcase. If you forget to do this, all of your testcase will pass because the errors will have been silenced. The following is an example:

[-]TestCaseExit (BOOLEAN bException)
       [-] if (bException)
               [ ] ExceptLog ()
//your application specific code starts here

  • There are several ways to turn off the recovery system. To disable it entirely, remove the const wMainWin from your window declarations file. Often, it is convenient to turn off the recovery system while you are experimenting so that the application does not get returned to the base state before the code you are testing is run. An easy way to do this is to append the keywords “appstate none” to your testcase.
     
  • Unfortunately once you’ve defined a BaseState function or written your own TestCaseExit function, attempting to turn off the recovery system with the keywords “appstate none” will not work. You have to comment the functions out to disable them. Make sure you uncomment them when you’re done experimenting or your team mates will grumble.