Having problems with your account or logging in?
A lot of changes are happening in the community right now. Some may affect you. READ MORE HERE

How can SilkTest use enumerated types to handle multiple Invoke/Dismiss methods?

How can SilkTest use enumerated types to handle multiple Invoke/Dismiss methods?

In Microsoft Windows and other GUI environments, there are typically multiple ways to invoke and dismiss windows. Let"s consider the WordPad application, a word processor included with Windows and accessible in the Accessories program group on the Start menu. To invoke the Open dialog in WordPad, you can:

  1. choose the File | Open menu item,
  2. type Alt-F-O,
  3. press Ctrl+O, or,
  4. click the Open icon in the toolbar.

To dismiss the Open dialog, you can:

  1. click Cancel,
  2. press Alt+F4,
  3. press the Esc key,
  4. right-click the window"s title bar and click the Close menu item, or,
  5. click the X in the upper right-hand corner of the window.

The "standard" Invoke and Dismiss method for the Open dialog are coded as follows:

[-] window DialogBox Open
  [ ] tag "Open"
  [ ] parent WordPad
  [ ]
  [ ] //most objects omitted to save space
  [ ] PushButton Cancel
  [ ]
  [-] void Invoke ()
       [ ] WordPad.File.Open.Pick ()
  [-] void Dismiss ()
       [ ] Cancel.Click ()

Now the Invoke and Dismiss methods can be modified to handle the multiple ways to invoke and dismiss the Open dialog noted above.

A first pass at this might be the following, where the individual invoke and dismiss methods are coded for the individual ways to invoke and dismiss the Open dialog. (Note: only a subset of the possible ways to invoke and dismiss the dialog are coded below.)

[-] window DialogBox Open
   [ ] // everything but methods omitted to save space
   [-] void InvokeViaMenu ()
      [ ] WordPad.File.Open.Pick ()
   [-] void InvokeViaAltKeys ()
      [ ] WordPad.TypeKeys ("fo")
   [-] void InvokeViaCtrlKeys ()
      [ ] WordPad.TypeKeys ("")
   [-] void DismissViaButton ()
      [ ] Cancel.Click ()
   [-] void DismissViaAltF4 ()
      [ ] TypeKeys ("")
   [-] void DismissViaEsc ()
      [ ] TypeKeys ("")

This solution certainly works, but seems to be causing a "method explosion." Remembering the name of the method corresponding to a particular way of invoking or dismissing the dialog might prove to be a problem. Also, if there are tens or hundreds of dialogs in the application, enforcing a naming convention (using the same method names in all of the dialogs) is difficult as well.

A second try at handling the multiple invoke and dismiss paths involves encapsulating all of the possible invoke paths in a single Invoke method and all possible dismiss paths in a single Dismiss method. The method takes an argument that specifies the particular path to take. The Open dialog"s Invoke method is coded as follows:

[-] void Invoke (integer iHow)
  [-] switch (iHow)
    [-] case 1 // via menu
      [ ] WordPad.File.Open.Pick ()
    [-] case 2 // via alt keys
      [ ] WordPad.TypeKeys ("fo")
    [-] case 3 // via ctrl keys
      [ ] WordPad.TypeKeys ("")
    [-] default
      [ ] raise 1, "*** Error: no case for {iHow}"

To invoke the Open dialog using a menu pick, a script would call Open.Invoke (1). To invoke Open via the Alt keys sequence, a script would call Open.Invoke (2). Invoking the Open dialog via the Ctrl keys sequence is coded as Open.Invoke (3).

A call such as Open.Invoke (99) causes an exception to be raised when the call is executed at script runtime, since there is no case in the switch statement corresponding to 99. We would ideally like such a problem to be caught at compile time, instead of while the script is executing. Another annoyance is that the method calls are rather cryptic. To figure out the meaning of Open.Invoke (1), you would most likely have to dig through the test frame, find the Open::Invoke method, and scan its code to find out what the argument of 1 does. It is not at all obvious from the method call that Open.Invoke (1) invokes the Open dialog using a menu pick.

Our third and final pass at handling multiple invoke and dismiss paths uses enumerated types to address and solve these problems. The SilkTest help file defines an enumerated type as follows.

"An enumerated data type groups together a set of values and orders them sequentially from 1 to n. You declare an enumerated type when you want a variable to hold only a limited number of distinct values. Use the type ... is enum declaration to declare enumerated data types."

The enumerated type declaration that enumerates the ways a dialog can be invoked appears below. Note that this definition must be placed at the same level as the dialog itself; the definition cannot appear within the Invoke method or within the Open object.

[-] type INVOKEMETHOD is enum

[ ] INVOKE_VIA_MENU
[ ] INVOKE_VIA_ALTKEYS
[ ] INVOKE_VIA_CTRLKEYS

After modifying the Invoke method to use the enumerated type, we have:

[-] void Invoke (INVOKEMETHOD eHow optional)
  [-] if (IsNull (eHow))
[ ] eHow = INVOKE_VIA_MENU
  [-] switch (eHow)
[-] case INVOKE_VIA_MENU // via menu
  [ ] WordPad.File.Open.Pick ()
[-] case INVOKE_VIA_ALTKEYS // via alt keys
  [ ] WordPad.TypeKeys("fo")
[-] case INVOKE_VIA_CTRLKEYS // via ctrl keys
  [ ] WordPad.TypeKeys("")
[-] default
  [ ] raise 1, "*** Error: no case for {eHow}"

Note that the Invoke method"s single argument is optional. If the Invoke method is called without any arguments, it assumes that the caller wants to invoke the dialog using the ubiquitous menu pick.

The script call to invoke the Open dialog via a menu pick is now Open.Invoke (INVOKE_VIA_MENU) instead of the Open.Invoke (1) call required by our previous solution. Using the enumerated type makes the script more readable, since the enumerated value INVOKE_VIA_MENU clearly indicates what path the Invoke method will use. Another benefit of the enumerated type is that passing an unhandled (undefined) value to the method will cause a compile time error - you don"t have to watch the script execute for 10 or 15 minutes and then see it abort just prior to completion because of a logical error in the script. For example, attempting to execute a script with the statement Open.Invoke (INVOKE_VIA_WHATEVER) yields the error Variable INVOKE_VIA_WHATEVER is not defined at compile time.

The enumerated type for specifying the dismiss path to use and the actual Dismiss method for the Open dialog are coded in a similar fashion, as follows. Again, remember that the enumerated type definition must appear at the same level as the declaration of the Open dialog.

[-] type DISMISSMETHOD is enum
  [ ] DISMISS_VIA_BUTTON
  [ ] DISMISS_VIA_ALTF4
  [ ] DISMISS_VIA_ESC
[-] void Dismiss (DISMISSMETHOD eHow optional)
  [-] if (IsNull (eHow))
    [ ] eHow = DISMISS_VIA_BUTTON
  [-] switch (eHow)
   [-] case DISMISS_VIA_BUTTON // via button
    [ ] Cancel.Click ()
[-] case DISMISS_VIA_ALTF4 // via Alt-F4 keypress
   [ ] TypeKeys ("")
[-] case DISMISS_VIA_ESC // via ESC keypress
   [ ] TypeKeys ("")
[-] default
   [ ] raise 1, "*** Error: no case for {eHow}"

What"s really happening "behind the scenes" here? As the help file indicated, the compiler internally assigns an integer value of "1" to the first enumerated value; "2" to the second enumerated value; etc. Proof positive can be found by executing the statement Print ([integer] INVOKE_VIA_MENU). To you and me, however, the enumerated type allows using pseudo-English "phrases" as method arguments and also provides compile time error checking. It is much easier to decipher what the enumerated value INVOKE_VIA_MENU does when it is passed as an argument to the Invoke method vs. deciphering the meaning of the integer value 1 passed as an argument.

Old KB# 21808

DISCLAIMER:

Some content on Community Tips & Information pages is not officially supported by Micro Focus. Please refer to our Terms of Use for more detail.
Top Contributors
Version history
Revision #:
1 of 1
Last update:
‎2013-02-15 19:24
Updated by:
 
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.