Using Tester

[Previous] [Next]

Using Tester is relatively simple. You just create a couple Tester objects, either start or find your application's main window, play some keystrokes to your application, check the results, and end. Listing 13-1 shows a sample VBScript test that starts NOTEPAD.EXE, enters a few lines of text, and closes Notepad.

Listing 13-1 Using common Tester objects

' A minimal VBScript Tester example. It just starts Notepad, enters a ' few lines of text, and closes Notepad. ' Get the system and input objects. Dim tSystem Dim tInput Dim tWin Set tSystem = WScript.CreateObject ( "Tester.TSystem" ) Set tInput = WScript.CreateObject ( "Tester.TInput" ) ' Start Notepad. tSystem.Execute "NOTEPAD.EXE" ' Wait 200 milliseconds. tSystem.Pause 200 ' Try to find Notepad's main window. Set tWin = tSystem.FindTopWindowByTitle ( "Untitled - Notepad" ) If ( tWin Is Nothing ) Then MsgBox "Unable to find Notepad!" WScript.Quit End If ' Ensure that Notepad is in the foreground. tWin.SetForegroundTWindow ' Type something. tInput.PlayKeys "Be all you can be!~~~" ' Play it again, Sam. tInput.PlayKeys "Put on your boots and parachutes....~~~" ' Third time's the charm. tInput.PlayKeys "Silver wings upon their chests.....~~~" ' Wait 1 second. tSystem.Pause 1000 ' End Notepad. tInput.PlayKeys "%FX" tSystem.Pause 50 tInput.PlayKeys "{TAB}~" ' Script is done! 

Listing 13-1 shows the three objects Tester uses most often. The TSystem object allows you to find top-level windows, start applications, and pause the testing. The TWindow object, which is returned by FindTopWindowByTitle in Listing 13-1, is the main workhorse. It is a wrapper around an HWND and has all sorts of properties that tell you everything about the window. Additionally, TWindow allows you to enumerate all the child windows that belong to a particular parent. The last object in Listing 13-1 is the TInput object, which supports the single method PlayKeys to funnel keystrokes to the window that has the focus.

Listing 13-2 shows the TNotify object used in a VBScript test. When developing automation scripts, one of the most difficult cases you'll need to handle is when an unexpected window, such as an ASSERT message box, pops up. The TNotify object makes it a snap to provide an emergency handler for such events. The simple script in Listing 13-2 just watches for any windows with "Notepad" in their captions. Although you might not use the TNotify class much, when you do need it, you really need it.

Listing 13-2 Using TNotify in VBScript

' A VBScript test to show the window notification handlers ' Constants for the TNotify.AddNotification routine. If I were ' using Visual Basic 6, I'd define these constants with Enums. Const antDestroyWindow = 1 Const antCreateWindow = 2 Const antCreateAndDestroy = 3 Const ansExactMatch = 0 Const ansBeginMatch = 1 Const ansAnyLocMatch = 2 ' Get the system and input objects. Dim tSystem Dim tInput Set tSystem = WScript.CreateObject ( "Tester.TSystem" ) Set tInput = WScript.CreateObject ( "Tester.TInput" ) ' The TNotify object variable Dim Notifier ' Create the TNotify object. Set Notifier = _ WScript.CreateObject ( "Tester.TNotify" , _ "NotepadNotification_" ) ' Add the notifications that I want. For this demonstration, I want both ' window destroy and window create notifications. See the TNotify source ' code for all the possible notification combinations. Notifier.AddNotification antCreateAndDestroy , _ ansAnyLocMatch , _ "Notepad" ' Start Notepad. tSystem.Execute "NOTEPAD.EXE" ' Pause for half a second. tSystem.Pause 500 ' Because Visual Basic isn't thread-safe, I set up the notification ' scheme to use a timer. However, the message can get blocked because ' all the processing is forced to a single thread. This function lets ' you manually check the window create and window destroy conditions. Notifier.CheckNotification ' The message box in the NotepadNotification_CreateWindow event ' procedure blocks, so the code to end Notepad won't execute until the ' message box is cleared. tInput.PlayKeys "%FX" tSystem.Pause 50 tInput.PlayKeys "{TAB}~" ' Again, check notifications. Notifier.CheckNotification ' Give TNotify a chance to intercept the window destroy message. tSystem.Pause 100 ' Disconnect the notifications. If you don't do this in WSH, the class ' terminate never gets called so the notification is still active in the ' notification table. WScript.DisconnectObject Notifier Set Notifier = Nothing Sub NotepadNotificationCreateWindow ( tWin ) MsgBox ( "Notepad was created!" ) End Sub Sub NotepadNotificationDestroyWindow ( ) MsgBox ( "Notepad has gone away...." ) End Sub 

You need to call the TNotify CheckNotification method every once in a while. (I'll explain the reasons you need to call this method in the section "Implementing Tester" later in the chapter.) Periodically calling the CheckNotification method ensures that the notification messages can get through given that you might not have a message loop in your language of choice. The code in Listing 13-2 shows how to use a message box in the notification event procedures, though you probably don't want to use message boxes in your real scripts because they can cause problems by unexpectedly changing the window with the focus.

Also keep in mind that I allow you to set only a limited number of notifications—five—so you shouldn't use TNotify for general scripting tasks such as waiting for the File Save dialog box to appear. TNotify should be used only for unexpected windows. Depending on how you set up your notification handlers and how they search for the specified text in the window caption, you can easily receive notifications for windows that you might not be interested in. You're most likely to receive unwanted notifications when you use a generic string such as "Notepad" and you specify that the string can appear anywhere in the window caption. To avoid notifications you don't want, you should be as specific as possible with your notifications when calling the TNotify AddNotification method. Your CreateWindow event procedures should also look at the TWindow passed in so that you can verify that it's the window you're interested in. For DestroyWindow event procedures that handle generic notifications, you should search the open windows to ensure that the window you're interested in no longer exists.

Included with the source code on the companion CD are two other samples that you might want to look at to see how you can use Tester. The first sample, NPAD_TEST.VBS, is a more complete VBScript test and has some reusable routines. The other sample, TT (or Tester Tester), is the main unit test for Tester, and you can access it with the TESTER.VBG project group file. TT is a Visual Basic_based application, and it should give you an idea of how to use Tester with Visual Basic. Additionally, these two samples show the TWindows object, which is a collection that contains TWindow objects.

Although I'm partial to using VBScript for my unit tests, I realize that getting it to work correctly can be a challenge. VBScript variables are untyped and there's no magic VBScript editor, such as the editor in Visual Basic, so you're back to the old run-and-crash style of debugging. The main reason I like using VBScript is that I don't need to rely on compiling my tests. If you have a flexible build environment—one in which you can easily build other binaries in addition to your main application—you might want to consider using Visual Basic so that you can build your tests as you build your application. Of course, Tester doesn't limit you to the easiest-to-use testing languages—if you're more comfortable in C or the Microsoft Macro Assembler (MASM), you're welcome to use those languages instead.

Although using the objects in Tester is fairly simple, the real work is planning your tests. You should keep your tests as focused and simple as possible. When I first started automating my unit tests in my early development days, I tried to force my tests to do too much. Now I write each script to test just a single operation. A good example of a single-operation test is to limit the script just to sending the keystrokes to open a file. You can chain the scripts together in various ways to maximize script reuse. Once you have the script to open a file, you can use it in three different tests: a test to see whether you can open a valid file, a test to open an invalid file, and a test to open a corrupt file. As in normal development, you should avoid any hard-coded strings if possible. Not only will this make internationalizing your script a piece of cake, but it will also help when you change your menu system and accelerators for the hundredth time.

Another detail to consider when you're designing your Tester scripts is how you'll be able to verify that the script actually worked. If you're bored and have the time, I guess you could just sit there and watch the scripts run to see whether you get the same results on each run. Probably a better idea is to log states and key points in your script so that you can compare the output to previous runs automatically. If you use the CSCRIPT.EXE WSH executable, you can use WScript.Echo and redirect the output to a file. After the script finishes, you can run a difference utility (such as WinDiff) on the output; if the utility turns up any differences, you can check to see that the script executed correctly. Keep in mind that you'll want to normalize the information you log and keep the information free of run-specific details. For example, if you're writing an application that downloads stock quotes, you won't want to include the last price-update time in the logging output.

What about debugging your Tester scripts? Because Tester doesn't have its own integrated debugger, as Visual Basic does, you need to be careful that you don't stop your debugger on a TInput PlayKeys method call. If the debugger does stop there, the keystrokes will obviously go to the wrong window. To work around this potential problem, I generally force the window to which I'm sending keystrokes to the top of the z-order by calling the TWindow SetForegroundTWindow method before each PlayKeys call. This way, I can break on the SetForegroundTWindow call, check the state of the application, and still get the keystrokes to the correct window.



Debugging Applications
Debugging Applications for MicrosoftВ® .NET and Microsoft WindowsВ® (Pro-Developer)
ISBN: 0735615365
EAN: 2147483647
Year: 2000
Pages: 122
Authors: John Robbins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net