Sie sind auf Seite 1von 179

TestPartner Advanced

Training Guide

Release 5.2.0

Please direct questions about Testpartner or comments on this document to: TestPartner Technical Support Compuware Corporation One Camp Martius Detroit, MI 48226-5000 1-800-538-7822 Outside the USA and Canada, please contact your local Compuware office or agent.

Copyright 1999 Compuware Corporation. All rights reserved. Unpublished rights reserved under the Copyright Laws of the United States. U.S. GOVERNMENT RIGHTS: Use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in Compuware Corporation license agreement and as provided in DFARS 227.7202-1(a) and 227.7202-3(a) (1995), DFARS 252.227-7013(c)(1)(ii)(OCT 1988), FAR 12.212(a) (1995), FAR 52.227-19, or FAR 52.227-14 (ALT III), as applicable. Compuware Corporation. THIS MATERIAL CONTAINS CONFIDENTIAL INFORMATION AND TRADE SECRETS OF COMPUWARE CORPORATION. USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF COMPUWARE CORPORATION. Compuware, Reconcile, QARun, TestPartner, QADirector, TrackRecord, QAHiperstation+ and QAHiperstation are trademarks or registered trademarks of Compuware Corporation.

All other company or product names are trademarks of their respective owners. Doc. CWQAD2.0A October 22, 1999.3

CHAPTER 1 -- OBJECT MAPPING ............................................................................. 8 INTRODUCTION TO OBJECTS .............................................................................................. 8 DETERMINING WHICH OBJECTS TO MAP.......................................................................... 9 MODIFY RECORD OPTIONS ............................................................................................. 10 To modify the Record options.................................................................................... 10 MODIFYING ATTACH NAME OPTIONS............................................................................. 12 MANAGE ATTACH NAME PROFILES ................................................................................ 14 Create an Attach Name Profile................................................................................... 14 Activating an Available Attach Name Profile............................................................ 23 Change the Order of an Attach Name Profile ............................................................ 23 Deactivating an Attach Name Profile......................................................................... 24 TIPS FOR NAMING ATTACH NAME PROFILES.................................................................. 26 COMPARING ATTACH DATA ENTRIES ............................................................................. 28 Selecting Attach Data from the Object Browser........................................................ 28 Selecting Attach Data in the Attach Data Compare dialog box................................. 30 MODIFY THE COMPARE ATTACH DATA COLORS ............................................................ 31 To modify the compare attach data colors ................................................................. 31 EXERCISE 1 OBJECT MAPPING ........................................................................... 34 CHAPTER 2 SCRIPT MODULARITY ....................................................................... 40 RUN() ............................................................................................................................. 41 EXERCISE 2 SCRIPT MODULARITY ................................................................... 42 CHAPTER 3 SCRIPT LOGIC ...................................................................................... 46 PROCEDURES .................................................................................................................. 46 Subroutines................................................................................................................. 46 Functions .................................................................................................................... 47 ARGUMENTS ................................................................................................................... 47 Passing Arguments by Reference............................................................................... 47 Passing Arguments by Value ..................................................................................... 48 CONTROL FLOW STATEMENTS........................................................................................ 49 If.Then .................................................................................................................... 49 If.Then.Else ........................................................................................................ 50 Select Case ................................................................................................................. 51 LOOP STATEMENTS......................................................................................................... 52 DoLoop................................................................................................................... 52 ForNext................................................................................................................... 53 WhileWend............................................................................................................. 54 THE EXIT STATEMENT .................................................................................................... 54 EXERCISE 3 SCRIPT LOGIC .................................................................................. 55 CHAPTER 4 VARIABLES, ARRAYS & COLLECTIONS ...................................... 57

VARIABLES ..................................................................................................................... 57 Naming Conventions.................................................................................................. 57 Types of variables ...................................................................................................... 57 ARRAYS .......................................................................................................................... 59 Declaring Arrays ........................................................................................................ 59 Specifying Limits ....................................................................................................... 59 COLLECTIONS ................................................................................................................. 60 Adding to a Collection ............................................................................................... 60 Removing an item from a collection .......................................................................... 60 Returning Items in a collection .................................................................................. 61 Counting a collection ................................................................................................. 61 OPTION EXPLICIT............................................................................................................ 61 VARIABLE SCOPE ........................................................................................................... 62 CHAPTER 5 MODULES AND CLASS MODULES .................................................. 66 MODULES ....................................................................................................................... 66 Adding a Module........................................................................................................ 66 Using A module ......................................................................................................... 67 SHARED MODULES ......................................................................................................... 68 Adding a Shared Module............................................................................................ 68 Using a Shared Module .............................................................................................. 68 CLASS MODULES ............................................................................................................ 69 Adding a Class Module .............................................................................................. 69 Using a Class Module ................................................................................................ 69 EXERCISE 5 MODULES AND CLASS MODULES ................................................. 71 CHAPTER 6 ALIAS MAPPING................................................................................... 73 USING ALIAS MAPPING .................................................................................................. 74 ADDING ALIAS MAP ENTRIES ......................................................................................... 75 MODIFYING ALIAS MAP ENTRIES ................................................................................... 77 DELETING ALIAS MAP ENTRIES ..................................................................................... 78 EXERCISE 6 ALIAS MAPPING.................................................................................. 79 CHAPTER 7 IMAGE MAPPING AND TEXT SELECTS ........................................ 83 IMAGE MAPPING ............................................................................................................. 83 TEXTSELECTS ................................................................................................................. 89 EXERCISE 7 IMAGE MAPPING AND TEXT SELECTS ....................................... 91 CHAPTER 8 TEST DATA HANDLING ..................................................................... 93 TESTDATA FILES ............................................................................................................ 93 ACCESSING A STANDARD CSV FILE ............................................................................... 94 ACCESSING AN EXCEL SPREADSHEET ............................................................................. 96 ACCESSING A CSV FILE WITH COLUMN HEADINGS ........................................................ 98 EXERCISE 8 TEST DATA HANDLING .................................................................. 103 4

CHAPTER 9 MULTIPLE EVENTS........................................................................... 110 WAIT EVENTS ............................................................................................................... 110 WHENEVER EVENTS ..................................................................................................... 111 EXERCISE 9 MULTIPLE EVENTS.......................................................................... 115 CHAPTER 10 CAPTURING DATA .......................................................................... 119 IDENTIFY ICON .............................................................................................................. 119 USE OF THE STOP COMMAND........................................................................................ 121 OBJECT SELECTION SCREEN ......................................................................................... 122 CAPTURETEXT METHOD............................................................................................... 124 EXERCISE 10 CAPTURING DATA.......................................................................... 126 CHAPTER 11 ERROR HANDLING.......................................................................... 128 DEFINING AN ERROR HANDLING SUBROUTINE ............................................................. 129 ERROR PROPERTIES ...................................................................................................... 130 EXIT FROM AN ERROR FUNCTION ................................................................................. 130 THE ERROR HANDLER IN A SHARED MODULE .............................................................. 131 CHAPTER 12 USER DIALOGS AND SCRIPT DEBUGGING.............................. 136 MSGBOX ...................................................................................................................... 136 INPUTBOX .................................................................................................................... 138 DEBUGGING SCRIPTS .................................................................................................... 139 USER FORMS ................................................................................................................ 140 ACTIVATION OF A USERFORM ...................................................................................... 149 EXERCISE 12 USER DIALOGS AND SCRIPT DEBUGGING............................. 150 CHAPTER 13 USER ID/PASSWORD ENCRYPTION ........................................... 152 SWITCHING LOGGING OFF ............................................................................................ 152 ENCRYPTION AND DECRYPTION ROUTINES .................................................................. 152 STORING AND RETRIEVING FROM THE REGISTRY ......................................................... 154 EXERCISE 13 USER ID/PASSWORD ENCRYPTION .......................................... 156 CHAPTER 14 FILE HANDLING............................................................................... 158 MICROSOFT SCRIPTING RUNTIME ................................................................................. 158 THE FILESYSTEMOBJECT ............................................................................................. 159 THE TEXTSTREAM OBJECT ........................................................................................... 160 EXERCISE 14 FILE HANDLING.............................................................................. 162 CHAPTER 15 USING SQL ......................................................................................... 165 MICROSOFT ACTIVEX DATA OBJECTS ......................................................................... 165 CONNECTION AND RECORD SET OBJECTS..................................................................... 165 EXERCISE 15 USING SQL ........................................................................................ 167 5

CHAPTER 16 SCREENSHOTS ................................................................................. 169 PRINTSCRN ................................................................................................................... 169 STORING IN FILES ......................................................................................................... 169 EXERCISE 16 SCREENSHOTS ................................................................................ 171 APPENDIX A - SOME EXTRA NOTES ................................................................... 174 WORKING WITH LISTS AND COMBO BOXES .................................................................. 174 SCROLLBARS ................................................................................................................ 174 CHECKBOXES................................................................................................................ 175 LOADING AN APPLICATION ........................................................................................... 176 THE CURRENTLY ACTIVE WINDOW .............................................................................. 176 SEARCH FUNCTIONS ..................................................................................................... 177

(Page left blank intentionally)

Chapter 1 -- Object Mapping


Introduction to objects
TestPartner uses a technique called object mapping to provide simplified, easily understood aliases for the names of Windows objects. Once a window is registered in the Object Map, all references to it in scripts, check definitions, and event definitions are made by its alias, rather than by its actual attach name. The attach name is an important concept when testing applications using TestPartner. When you control a Windows application manually, you select the window by clicking on it. TestPartner uses a slightly different method, called attaching. TestPartners method of attaching to a window is analogous to you clicking on it to bring it into focus. A typical Windows application displays many different dialog boxes, each containing its own menus, edit boxes, lists, buttons, and other controls. Each dialog box and control has a name that uniquely identifies it, and TestPartner uses that name to locate the window and attach to it. The full name of any Windows object (called its attach name) is constructed from the name and the object's properties of interest, as shown in the examples below: Window("Application=IEXPLORE.EXE Caption='http://intranet/ - Microsoft Internet Explorer'").Attach HTMLBrowser("Caption='Employee Lookup' ExtendedStyle=0").Attach HTMLButton("Name=btnclose").Click TestPartner uses a technique called object mapping to allow a logical name (an alias) to be associated with a physical window. Once a window is registered in the Object Map, all references to it in scripts, check definitions, and event definitions are made by its alias, rather than by its actual attach name. The Object Map maintains a 1:1 relationship between logical and physical window names. Object Map aliases look like the examples below: httpintranet Microsoft Internet Explorer provided by Compuware Corporation Window httpintranet HTMLBrowser Close HTMLButton Object mapping has the following major benefits: It enables descriptive names to be substituted for complex attach names. It eliminates a scripts dependence on attach names which may change if the target is modified. Logical names created by object mapping are shorter than attach names, making scripts easier to read.

Determining Which Objects To Map


Before you begin learning scripts, you should determine the types of objects that you want to map in addition to windows. TestPartner allows you to include all the objects from your target application in the Object Map, but this isnt usually necessary because many of the controls that are encountered already have text associated with them that adequately describes the control. So, you may decide that mapping these controls is unnecessary. For example, without object mapping when you Learn a click on the Open button in Notepads File Open dialog box, the following code is learned: Button("Caption=&Open").Click However, with object mapping and the Auto-Create PushButton option selected, the following code is learned: Button("&Open Button").Click Using this method, the "&Open" button is assigned an alias of "&Open button" and as the buttons caption is now stored in the database it does not appear in the code. In this example, object mapping has not helped to improve the readability of the script. In contrast, a button without associated text (for example, a picture button) might be learned as the following code without object mapping: Button("Caption='' Index=20").Click But, when using object mapping, the same action could be learned as the following example: Button("Calculator_No_4").Click The above makes it much clearer which button is being dealt with. There is no rule about when you should use object mapping and when you should use attach names. The decision will depend on the type of target application you are working with.

Modify Record Options


You can use the Record options to control TestPartner's behavior while recording scripts. This category contains sub-categories forTiming, Attach Name specification, Hotkey options, and Code Generation options, in this section we are interested in the Attach Name specification.

To modify the Record options


1. Select the Tools menu Options item.

2. In the outline view, click Record and then Attach Name.

10

3. The attach name details may be modified as described in the following section Modifying Attach Name Options. 4. Optionally, click Save As to save your settings as a group name

5. Click OK to close the Record Settings dialog box 6. Click OK on the options dialog box to apply your changes and close the dialog box. Click Cancel to close the dialog box without applying your changes.

11

Modifying Attach Name Options


You can modify the Record Attach Name options to control how TestPartner attaches to different types of objects while recording a script. Use the Attach Name options to control how TestPartner identifies and records objects while recording scripts. You can use the Record Settings at the bottom of the panel to save a group of Attach name options for later use. You can also use this dialog box to return to TestPartner's system defaults. You can set the following options: 1. Object Map Recording Determines if and how object map entries are used when recording.

Set to Create new, Use existing, TestPartner will automatically create and record an Object Map entry when attaching to any object during recording, as long as the

12

object does not already have an entry in the Object Map. If an object already has an Object Map entry, a map entry will not be created for the object, but the original map entry in the database will be recorded. Set to Use existing, TestPartner will use an existing Object Map entry if one exists for the object being recorded. If a Map entry does not exist for the object, the raw attach name will be recorded. Set to Raw Attach Name to disable Object Map recording and only record raw attach names when attaching to objects during recording.

2. Manage Attach Name Profiles Click the Ellipsis button in the value field to display the Manage Attach Names Profiles dialog box, where you can create and manage how objects are recorded, and set properties of interest for each object type. This is detailed in the next section, Manage Attach Name Profiles. 3. Disable Attach Name Profiling Set to Yes to prevent TestPartner from using any currently active Attach Name profiles. This setting lets you turn profiling on and off without having to go to the Manage Attach Name Profiles and move profiles to and from the Active and Available Profiles lists. 4. Flash Rate Per Second Type a value to set the number of times per second the surrounded border flashes when TestPartner is locating an object. You locate an object by clicking the Locate button when viewing details for the object's map or attach name entry, or in the Identify or Locate Image Map dialog boxes. 5. Maximum Number of Flashes Type a value to set the maximum number of times the surrounded border flashes when TestPartner is locating an object. You locate an object by clicking the Locate button when viewing details for the object's map or attach name entry, or in the Identify or Locate Image Map dialog boxes. The maximum number of flashes setting and the Flash rate per second can be used to determine how long the surrounding border will flash when TestPartner locates an object. For example, a setting of five for the Flash Rate per Second with a Maximum Number of Flashes set to fifteen would allow the object map locator's flashing border to flash for a maximum of three seconds

13

Manage Attach Name Profiles


Raw Attach Names and Object Map entries can be modified in TestPartner after they have been created. However, TestPartner also lets you modify default information recorded for any object before the object is recorded. What's more, you can store modifications in logical groups and use the modifications stored in the groups whenever they are needed. These groupings are called Attach Name profiles. Attach Name profiles give you full control of how objects are recorded in scripts. For each group of objects, you can determine which object types you want to modify, whether the object will record as a Raw Attach Name or Object Map entry, what the object's properties of interest are, and when to enforce recording the properties of interest. You can also activate and deactivate any profiles you create, set a profile to operate only with certain applications, and change the hierarchical order in which active profiles operate.

Create an Attach Name Profile


To create an attach name profile, you perform the following: Access the Manage Attach Name Profile dialog box Create and Name the profile. Define attach data configuration criteria for the Attach Name profile.

To access the Manage Attach Name Profile dialog box 1. Select Tools | Options. 2. In the outline view, click Record. 3. The Record options display in the panel on the left and the Timing, Attach Name, and Hotkeys sub-categories display in the outline view below Record. 4. In the outline view, click Attach Name 5. In the options panel, select Manage Attach Name Profiles, then click the ellipsis button . The Manage Attach Name Profiles dialog box displays.

14

To create and name an Attach Name profile 1. In the Manage Attach Name Profiles dialog box, click New. The New Profile dialog box displays.

2. In the Name Field, type the name for the Attach Name profile you want to define. You can use any combination of characters and numbers when naming a profile. Spaces are also allowed. The profile should be given a name that gives its users an idea of the profile's use. See section "Tips for Naming Attach Name Profiles" for more information on tips for naming Attach Name profiles.

15

3. To base the new profile on an existing profile, selecting an existing profile name in the Copy From list box. Select <Default Profile> if you do not want to base the new profile on an existing profile. 4. Click OK. The Attach Name Profile dialog box displays.

To define attach data configuration criteria for the Attach Name profile 1. Select the Domain extensions that will apply to the Attach Name profile. In the Include column, select the check box of the extension(s) you want to set object type and properties of interest settings for. Extensions include: COM Objects - Includes the App and COMObject object types, which can be recorded when the recording domain is set to COM. HTML Includes HTML Object types derived from Standard Controls, such as HTMLButton, HTMLCheckbox, etc. Also includes non-standard controls for HTML, such as HTMLBrowser, HTMLTable, etc., and Netscape specific controls such as NSToolbar. HTML object types begin with the prefix HTML in TestPartner script. 16

Java Select this check box to customize how TestPartner records Java controls such as JavaEditBox, JavaListBox, etc. Java object types begin with the prefix Java in TestPartner script. Navision For users of Cronus' Navision Attain product, select this check box to customize how TestPartner records Navision controls, including NAVSubForm and NAVMatrixBox. Navision object types begin with the prefix NAV in TestPartner script. Standard Controls Select this check box to customize how TestPartner records base objects types such as Window, Button, ListBox, etc. VisualBasic Select this check box to customize how TestPartner records its set of objects types specific to VisualBasic. VisualBasic objects begin with the prefix VB.

2. Select the object types that will apply to the selected domain extensions. In the Attach Name Profile dialog box, click the Types tab. The Types tab displays a list of each object type that is a member of any selected domain extensions.

17

In the Include column, click the check box of each object type you want to be part of the profile. Each selected object type becomes part of the profile. Note: If editing the profile, you can also click selected check boxes to deselect them. Click the Record As column for each selected object type, then select from the list the preferred method to record that type. There are three choices: Raw Attach Name TestPartner will record this object as a raw attach name. Properties recorded for the object may include the properties of interest selected for the object type. Prompt For Value When selected, TestPartner will prompt you to enter an object map name for an object, unless the object already has an Object Map entry in the database. TestPartner supplies a default name which you can use. If an Object Map entry already exists, TestPartner will automatically use that entry. You can click Cancel when the prompt displays to use the raw attach name. Object Map Entry TestPartner will record this object as an object map entry based on Object Map recording guidelines. If an object map entry already exists for a recorded object, TestPartner will use the existing entry.

18

3. Select the applicable properties of interest for each object type selected. In the Attach Name Profile dialog box, click the Properties of Interest tab. The Properties of Interest tab displays two panes.

The left pane is the Properties pane. It shows all the properties for each object type selected. Each selected property has a check in the Include column. The right pane is the Types pane. It shows a list of the relevant object types for each selected property. These are the objects selected in the Types tab which have the selected property. In the Include column of the Properties pane, click the check box of the first property you want to be a property of interest for the selected object type. This selects the property for all types that include the property. You can also click a selected check box to deselect a property.

19

The Selected column changes to indicate how many of the object types the select property applies to as a property of interest. For example "1 of 2" means the property is a property of interest for 1 of the 2 selected object types. The word "All" means this property is a property of interest for all the object types in the Types pane. "None" means the property has not been selected as a property of interest for any of the objects in the profile. The Includes column of the Types panel selects properties on a type-by-type basis. Select the check box of object type you want the selected property to be a property of interest for. Note that the Selected column in the Properties pane changes if you select or deselect objects. To force a property as a property of interest for an object type, select the Always Use check box for the desired object type. Note that the Always Use check box only displays when the property is included. If the Always Use check box is not selected, the selected property of interest is recorded in script in accordance with TestPartner's properties of interest recording guidelines. Note: If editing the profile, you can also click selected check boxes to deselect them. Repeat the above for each property you want as a property of interest for the selected object types. Click OK to save your changes and return to the Manage Attach Name Profiles dialog box, or click Cancel to exit without saving your changes. You can also click Apply to record your changes immediately, or optionally click the Applications tab and continue defining the profile by specifying applications for an attach name profile.

4. You can also optionally specify applications on which the profile will operate. Each Attach Name Profile can be set to operate on specific applications. This feature allows you to record an object differently based on the application under test. The default is for a profile to work on all applications. 4.1 To access the Applications tab of the Attach Name Profile dialog box In the Manage Attach Name Profiles dialog box, select the profile you want to want to specify certain applications to operate on. You can select any profile from either the Active or Available column. Click the Edit button to access the Attach Name Profiles dialog box. 20

Click the Specify Applications tab.

4.2 To add an application to the list Start the application you want to add to the list, if it is not currently running. After starting the application, switch back to the TestPartner application. To add the application to the list, click Identify. TestPartner is minimized, and the target application becomes visible. Position the mouse over any window or control in the application and click the left mouse button.

21

TestPartner is restored and the name of the application displays in the Applications list.

As an alternative to using Identify, you can click Browse Tree to select an attach name from the Object Selection window or Object Map to select an attach name from the existing Object Map entries. You can also click Add and enter the file name of the application in the Add Application dialog box. However, the application name entered must exactly match the application name. Note: You can also select an application from the Applications list and click Remove to remove it. Click OK to save your changes and return to the Manage Attach Name Profiles dialog box, or click Cancel to close exit without saving your changes. You can also click Apply to record your changes immediately.

5. Click OK to save your changes and exit to the Manage Attach Name Profiles dialog box, or click Cancel to exit without making any changes. In the Manage Attach Names dialog box, the created profile is added to the list of available profiles. 22

Activating an Available Attach Name Profile


When an Attach Name profile is created, it resides in the Available list of the Manage Attach Name Profiles dialog box until you activate it. To activate an attach name profile Access the Manage Attach Name Profiles dialog box from TestPartner's options. In the Available list, select the profile you want to activate.

Click the Activate button . To activate all profiles from the Available list, click the Activate All button .

Repeat the above steps to activate other profiles from the Available list.

Change the Order of an Attach Name Profile


Attach Name profiles operate in a hierarchical order. In the list of active Attach Name profiles, configuration settings in higher ordered profiles take precedent over settings in lower ordered profiles. You can order profiles so those with settings you always want to operate are the higher ordered profiles. Only active profiles can be reordered. To change the order of an Attach Name Profile Access the Manage Attach Name Profiles dialog box from TestPartner's options.

23

In the Manage Attach Name Profiles dialog box, select the profile in the Active list whose order you want to change. If the profile you want is not in the Active list, you can activate it from the Active list.

Click Move Up or Move Down to change the order of the selected profile. Click OK to save your profile changes or Cancel to exit without saving your changes.

Deactivating an Attach Name Profile


When you activate an Attach Name profile, it remains active until it is removed from the Active list. Deactivate a profile when you don't want it to operate, but you may want to use it in the future. To deactivate an attach name profile Access the Manage Attach Name Profiles dialog box from TestPartner's options. In the Active list, select the profile you want to deactivate. Click the Deactivate button . To deactivate all profiles from the Active list, click the Deactivate All button . Repeat the above steps to deactivate other profiles from the Active list.

24

Click OK to save your profile changes or Cancel to close the Manage Attach Name Profiles dialog box without saving your changes. Click OK to save your profile changes or Cancel to close the Manage Attach Name Profiles dialog box without saving your changes.

25

Tips For Naming Attach Name Profiles


Because the content and configuration of an Attach Name profile is not readily apparent from the profile's name, it is important you name Attach Name profiles so content can be apparent from the name. In general, your naming strategy for Attach Name profiles should loosely follow how you want to customize attach names, and your organization's testing practices. Below are some general suggestions and strategies for Attach Name profile naming. If you plan to create profile information for just one type of domain extension, you may want to base profiles and their names on single object types within the extension. If for example, you are testing only Java applications, you may want one profile for each Java application. Each profile would only use the Java domain extension, but customize Java object recording in different ways depending on the application. In this case you may want to name each profile the name of the application for which it will be used. However, if you are customizing only a few Java object types and want to keep the Attach Name profiles relatively uncomplicated, you may want to just customize one object per profile. In this case, consider naming the profiles after the object type it customizes for recording, such as JavaEditBox, JavaButton, etc. If your profiles only modify how one or two object types are recorded, consider naming the profile after the object types they modify. That way the customization in the profile is easily known from the name of the profile. Examples Button, Window HTMLBrowser VBWindow and VBListBox This method is also useful if you plan to have several different ways of customizing the recording of a single object type. For example, if you want the Window object recorded one way for certain applications, and another way for other applications, you can have two separate profiles with the names Window1 and Window2. If you plan on customizing how most or all available objects are recorded, consider creating separate profiles based on domain extension groupings, and naming them according to the domain whose object types they customize.

26

Examples HTML Extensions VisualBasic Controls Navision If you know that you'll want to always record some object types as raw attach names and others as Object Map entries, you may want to create profiles based on these recording options. In that case, consider creating two profiles; one with all the object types that are to be recorded as Raw Attach Names, one with all the object types to be recorded as Object Map entries. These profiles could be named Raw Attach Names and Object Map Entries

27

Comparing Attach Data Entries


Occasionally, the differences between two objects is so slight that TestPartner is unable to Auto-Create different raw attach or Object Map names. This can happen if the objects are a non-standard class (when the Type is recorded simply as ChildWindow) and untitled. Applications with multiple tool bars often create these conditions. Many times, the only differences between two objects might be their attach names and screen coordinates. TestPartner provides an easy method to view and analyze attach data differences between two objects. The Compare Attach Data utility lets you compare the attach data of any two objects. Differences are highlighted to make comparison quick and easy. You can select Attach Data to compare using TestPartner's Object Browser, or using the Compare Attach Data dialog box.

Selecting Attach Data from the Object Browser


Select View | Asset Browser on the menu bar. Under Asset Types, select Object Map. Select the first object entry you want to compare. Hold down the CTRL key and select the entry with which you want to compare the first entry.

28

Perform one of the following: Right-click and select Compare Attach Data from the pop-up menu. Click the Compare Attach Data button on the toolbar. Select Tools | Compare Attach Data on the menu bar.

The Compare Attach Data dialog box displays.

When both attach data entries you want to compare display in the Compare Attach Data dialog box, you can compare their differences. Each property for the entries and their values are shown, and significant properties for each are marked by a check next to the property in the Significant column. Color codes indicate the type of difference. The colors used can be set in TestPartner options for Compare Attach Data Colors. See the section "Modilfy the Compare Attach data Colors" below for details about what each difference and color code signify

29

Selecting Attach Data in the Attach Data Compare dialog box


Apart from the above method of selecting two objects to compare from the object map you may also select objects for the two window panes in the Compare Attach Data dialog box using the Identify, Browse tree, and Object Map buttons above each pane.

1. Using the Identify Button In the desired pane of the Compare Attach Name dialog box, click Identify to select the object from the desktop. When you click Identify, a crosshair cursor displays, and window objects are highlighted as you move the mouse over them in the target application. When the control you want to add is highlighted, click the left mouse button. Click OK. Attach data and properties for the selected control are displayed in the selected pane of the Compare Attach Name dialog box.

2. Using the Browse Tree Button Click Browse Tree... to select the object whose attach name data you want to compare from a tree view of the current GUI or COM objects. The Object Selection window displays. In the Object Tree pane, choose the GUI or COM object you want to compare from the object tree. When you highlight an element in the object tree, its properties display in the Properties pane. If you don't see the Properties pane, click Properties on the toolbar. Click OK. Attach data and properties for the selected control are displayed in the selected pane of the Compare Attach Name dialog box.

3. Using the Object Map Button

30

Click Object Map... to select the object from the Object Map. When you choose Object Map..., the Browse for Object Map Entry window displays. Choose the object you want to check and click Insert. Attach data and properties for the selected control displays in the selected pane of the Compare Attach Name dialog box.

4. With an entry selected in each window pane the differences between the two entries may be viewed as described before.

Modify the Compare Attach Data Colors


You can modify the Compare Attach Data Colors to specify the different colors used by the Compare Attach Data Dialog to indicate differences between data captured for two objects.

To modify the compare attach data colors


From Tools | Options, double-click Advanced, and then Compare Attach Data Colors. Use the Compare Attach Data Colors options panel to set colors that represent different data in the Compare Attach Data utility. Each data type option in the options panel is numbered to correspond to a number in the Sample frame below the options panel.

31

In the option panel on the right, select the color option you want to change. You can set color combinations for the following: Different Values Text color used to indicate a value in the Values column that is different from the attach data being compared. Different Values Selected Text color used when a value that differs is selected in either Value column of the Compare Attach Data utility. Different Significance Background color used in the Significant column of the Compare Attach Data utility to indicate a difference in the significance state of a property between the attach data being compared. Different Significance Selected Background color used in the Significant column of the Compare Attach Data utility when an item in the Significant column is selected. Used to indicate a difference in the significance state of a property between the attach data being compared. Property is Missing Text color used to indicate that the property in the attach data being compared is missing. Property is Missing Selected Text color used to indicate that the property in the attach data being compared is missing, when the property entry that is not missing is selected. Property Doesn't Exist Color of the patterned lines that go through a row when a property only exists in the attached data being compared.

Click the ellipsis button ( . . . ) next to the selected color option. TestPartner displays the Windows Color dialog box.

32

Use the Windows Color dialog box to set the desired color. Click OK to set the color for the selected color option. The color value for the selected color option changes. Color values are represented by their hexadecimal value. Repeat the above for any other Compare Attach Data Color options you want to change. Note: If at any time you want to revert to the original system colors to indicate differences between compared attach data, click the Restore Defaults button. Click OK to apply your changes and close the dialog box. Click Cancel to close the dialog box without applying your changes.

33

Exercise 1 Object Mapping


Objective: Create an Attach Name Profile to make all Edit fields, Radio Buttons, and Push Buttons into objects for the QADemo Web application. Ignore the use of ID for recognition. Set Object Mapping Options to prompt for new Windows objects. Object map all the edit, radio button & push button controls in the Qademo Web application up to and including the Add Car Window.

Target Application: QADemo Web Instructions: STEP 1: STEP 2: STEP 3: Create an Attach Name Profile called QADemo Web . Select HTML and Standard Controls extensions Set the Types HTMLEditBox , HTMLRadioButton, HTMLButton to Object Map Entry. Set the Type Window to Prompt for Value. Activate the attach Profile. Record loading the QADemo Web application, signing in, select add cars, input an entry to every field in the add cars windows and then exit the application. Select the Object Map asset and examine the objects stored in the map. Rename the Edit Field entries to have meaningful names. Then record the add car option in QADemo again and compare the script with the earlier script.

STEP 4: STEP 5:

STEP 6: STEP 7:

34

Examples: STEP 1: Creating a new Attach Profile.

STEP 2: Set the required Extensions

35

STEP 3: Setting the Types.

STEP 4: Activate the Profile.

36

STEP 5: Record the input of car data within QADemo Web .

The web address for QADemo Web is: http://127.0.0.1/~qademo The user id and password are dtl and pass. From the File menu select Main Options From the list select Add Car Fill in all fields and checkboxes

37

Select Add and then Close the browser. Stop Recording STEP 6: Examine the object Map

STEP 7: Rename the fields to have more meaningful names.

38

Testpartner script recorded before Object Renames: ' Attach to Caption='QADemo - Add Car' HTMLBrowser("Caption='QADemo - Add Car'").Attach HTMLEditBox("HTMLEditBox_0002").SetText "Car1" HTMLEditBox("HTMLEditBox_0003").SetText "Ford" HTMLEditBox("HTMLEditBox_0004").SetText "3000" HTMLEditBox("HTMLEditBox_0005").SetText "1999" HTMLEditBox("HTMLEditBox_0006").SetText "3" HTMLEditBox("HTMLEditBox_0007").SetText "Blue" HTMLEditBox("HTMLEditBox_0008").SetText "3000" HTMLEditBox("HTMLEditBox_0009").SetText "15" HTMLEditBox("HTMLEditBox_0010").SetText "1" HTMLCheckBox("Name=chkRadio").Click Testpartner script recorded after Object Renames: ' Attach to Caption='QADemo - Add Car' HTMLBrowser("Caption='QADemo - Add Car'").Attach HTMLEditBox("Add Car Window Reference Edit").SetText "Car2" HTMLEditBox("Add Car Window Make Edit").SetText "Ford" HTMLEditBox("Add Car Window Engine Size Edit").SetText "3000" HTMLEditBox("Add Car Window Year Edit").SetText "1999" HTMLEditBox("Add Car Window Doors Edit").SetText "3" HTMLEditBox("Add Car Window Color Edit").SetText "Blue" HTMLEditBox("Add Car Window Cost Edit").SetText "3000" HTMLEditBox("Add Car Window DealerDiscount Edit").SetText "15" HTMLEditBox("Add Car Window Quantity Edit").SetText "1" HTMLCheckBox("Name=chkRadio").Click

39

Chapter 2 Script Modularity


A complete test case contains many individual scripts, executed at different points within the target application. A test case typically consists of a driver script, which drives the target application to the proper test point to begin a test script.

A driver script runs a setup script to run an application or open a Web page. The driver script then launches the first test script, which tests the functions or user interface for that test site and logs the results. When the first test script finishes running, the driver script advances the application to the next test point and launches the next test script, which again runs the appropriate tests for that site. Since one driver script can run any number of test scripts, you can add or modify test scripts as self-contained modules. A driver script uses the Run command to run compiled scripts. A well-designed test script returns the target application to the original test point before completion. This ensures that: Driver scripts can always pick up from where they left off. You can add or remove tests at a test site without modifying the driver path.

40

Run()
Runs another script from this script. This script is suspended until the other finishes. Syntax: Run( "scriptname" ) Operation: This command runs the script specified by "scriptname". The calling script is suspended until "scriptname" has finished processing. Then it resumes from the line following the Run command. Examples: Sub Main() Run ("AppLoad") Run ("AppClearDB") Run ("AppAddData") Run ("AppVerifyData") End Sub

41

Exercise 2 Script Modularity


Objective: Create a script for starting QADemo Web. Create a script for closing QADemo Web. Create a script for clearing the QADemo database Create a Driver script to run the above scripts

Instructions: STEP 1: Create a new script named EX02 Record the process of starting QADemo Web (http://127.0.0.1/~qademo), signing on to the application (dtl, pass), closing the New window, Selecting ResetDatabase from the menu, Selecting Logoff from the menu and closing the browser. Verify the script plays back. STEP 2: Cut the instructions from EX02 for starting and signing on to QADemo Web, and paste them into a new script called Signon. STEP 3: Cut the instructions from EX02 for closing QADemo, and paste them into a script called Shutdown. STEP 4: Cut the instructions from EX02 for clearing the database and paste them into a script called ClearDataBase. STEP 5: Insert Run commands into EX02 to run the new scripts Startup, Shutdown., and ClearDatabase. Verify the new script executes without error.

42

Examples: Example of Signon script.

43

Shutdown Script

Clear Database Script

44

Driver Script (EX02)

45

Chapter 3 Script Logic


Procedures
Procedures are useful for implementing repeated tasks such as frequently used calculations. The calculations could be embedded in your code wherever you use them, but then if a change is required every occurrence of this code must be altered. It is much more efficient to put the code in a single procedure and call that procedure from wherever it is required to do the calculation. This provides a much cleaner code that is easier to understand and maintain as there is only one copy to look after. There are two types of procedures, Subroutines and Functions.

Subroutines
A subroutine is a block of statements that carries out a well defined task. The block of statements is placed in a pair of Sub/End Sub statements and can be invoked by name. Sub ShowDate() MsgBox Date() End Sub A subroutine would normally be more complicated than the above. This subroutine can be invoked by calling it: Call Showdate() Or it can be invoked by just using the name: ShowDate() Subroutines may also accept parameters separated by commas: Call Subroutine (Param1, Param2,Param3,.) Altering the above ShowDate subroutine to accept a parameter of a number of days and to display the date of today plus that number of days we get: Sub ShowDate ( Count as Integer) MsgBox Date() + Count End Sub To call this we can now use:

46

ShowDate ( NumDays) Where NumDays is an Integer variable containng the number of days to add to today. While a Subroutine can accept parameters it can not return a value, in order to return a value we must use a Function.

Functions
A function is similar to a subroutine, but a function returns a result. Subroutines perform a task and don't return a value to the calling program; functions typically carry out calculations and report the result. A function is a block of code between Function/End Function statements. Also as a Function returns a value it must have a type. Changing our ShowDate subroutine above to be a function that returns a date we would have the following: Function NewDate (Count as Integer) As Date NewDate = Date() + Count End Function Note how the second line of the above function returns a value, this is achieved by assigning the return value to the function name. We would invoke this function as follows: NextDate = NewDate( NumDays)

Arguments
Arguments (parameters) can be passed to procedures in two ways, by reference (the default) where the address of the original variable is passed and the procedure could change the original variable. The other way is by value, where a copy of the argument is passed and the procedure can not alter the original value.

Passing Arguments by Reference


The default method of passing arguments is by reference. As shown in the following example that allows the called function to change the original variables. Function Add(Num1 As Integer, Num2 As Integer) As Integer Add = Num1 + Num2 Num1 = 0 Num2 = 0

47

End Function Dim A As Integer, B As Integer A= 10 B= 2 Sum = Add (A,B) Debug.Print A Debug Print B Debug.Print Sum The above code will give the results: 0 0 12 In general you only pass arguments by reference if the called procedure has a need to alter its value, this is not a safe method of passing parameters and should not be used unless necessary. When passing an argument by reference, the argument type must match the declared type (Both are Integer in the above example). If they do not match then an error message will be generated. If in the above example A was defined : Dim A As Single Then we need to convert this value to integer. This can be done as follows: Sum = Add (Cint(A),B) A second method is to let VB to automatically convert the value, this is achieved by enclosing the argument in parenthesis. Sum = Add ((A),B)

Passing Arguments by Value


When you pass an argument by value the procedure sees only a copy of the argument. The benefit of this is that the argument values are isolated from the procedure, and only the program in which they are declared can alter them. Passing arguments by value requires a little bit of extra typing, since this is not the default argument passing mechanism. Changing our example above to pass parameters by value we get the following: Function Add(Byval Num1 As Integer, ByVal Num2 As Integer) As Integer 48

Add = Num1 + Num2 Num1 = 0 Num2 = 0 End Function Dim A As Integer, B As Integer A= 10 B= 2 Sum = Add (A,B) Debug.Print A Debug.Print B Debug.Print Sum The above code will give the results: 10 2 12 The code in the function, which assigns zero to the arguments, has no effect on the original variables.

Control Flow Statements


VBA provides three test conditions to take a different course of action depending on the outcome of a test.

If.Then
The If structure can have a single line or multiple line syntax: If condition Then statement If condition Then statement End If Examples: If Month (date) = 1 Then Year = Year + 1 If Month (date) = 1 Then Year = Year + 1 End If

49

If.Then.Else
The IfThenElse statement executes one block of statements if the condition is True and another if False. If condition Then statement block 1 Else statement block 2 End If If the condition is true then statement block 1 is executed, if the condition is false then condition block 2 is executed. Another variation of the IfThenElse statement uses several conditions with the ElseIf keyword. If condition1 Then Statement block 1 ElseIf condition2 Then Statement block 2 ElseIf condition 3 Then Statement block 3 Else Statement block 4 End If You can have any number of ElseIf clauses. The conditions are evaluated from the top, if one of them is True then the corresponding block of statements is executed. The Else clause will be executed if none of the previous expressions are true. Example: Score = InputBox("Enter Score") If Score < 50 Then Result = "Failed" ElseIf Score < 75 Then Result = "Pass" ElseIf Score < 90 Then Result = "Very Good" Else Result = "Excellent" End If

50

Select Case
The Select Case structure compares one expression to different values. The advantage over multiple IfThenElse statements is that it makes the code easier to read and maintain. Select Case expression Case value 1 Statement block 1 Case value 2 Stratement block 2 . . . Case Else Statement block End Select Example: Select Case WeekDay(Date) Case 1 DayName = "Monday" Message = "Have a nice week" Case 6 DayName = "Saturday" Message = "Have a nice weekend" Case 7 DayName = "Sunday" Message = "Did you have a nice weekend" Case Else Message = "Welcome Back" End Select Some Case statements can be followed by multiple values, which are seperated by commas. The following demonstrates this: Select Case WeekDay(Date) Case 1 DayType = "Workday" Message = "Have a nice week" Case 2, 3, 4, 5 DayType = "Workday" Message = "Have a nice weekend" Case 6, 7 DayType = "Weekend"

51

Message = "Have a nice weekend" End Select The above structure does not contain a Case Else statement because all possible values are handled by the Case statements.

Loop Statements
Loop statements allow you to execute one or more lines of code repetitively. There are three loop statements: DoLoop ForNext WhileWend

DoLoop
The DoLoop executes a block of statements for as long as a condition is True. There are two variations using keywords While and Until to specify how long the statements are executed. To execute a block of statements while a condition is true use: Do While condition Statement block Loop To execute a block of statements until the condition becomes true use: Do Until condition Statement block Loop A DoLoop can execute any number of times as long as condition is True. The number of iterations need not be known before the loop starts. If condition is initially False the statements may never execute. Another variation of the Do loop always executes the statements first and evaluates the condition after each execution, this ensures the statements will be executed at least once. Do Statements Loop While condition

52

Do Statements Loop Until condition

ForNext
Unlike the Do loop the ForNext loop requires that you know how many times the statements in the loop will be executed. The ForNext loop uses a variable (called the loop counter) that increases or decreases in value during each repetition of the loop. The syntax is as follows: For counter = start To end [step increment] Statements Next [counter] The keywords in the square brackets are optional. The arguments counter, start, end, and increment are all numeric. The loop is executed as many times as required for the counter to reach (or exceed) the end value. Execution of the For loop follows the following steps: 1. Sets counter equal to start. 2. Tests to see if counter is greater than end. If so, it exits the loop. If increment is negative the test is to see if counter is less than end. If it is it exits the loop. 3. Execute the statement in the block. 4. Increments counter by the amount specified with the increment argument. If the increment argument isn't specified, counter is incremented by 1. 5. Go to step 2. The following example scans all the elements of the numeric array data and calculates their average. For I = 0 to Ubound(Data) Total = Total + Data(I) Next I Debug.Print Total/Ubound(Data) The single most important thing to remember when working with ForNext loops is that the loop's counter is set at the beginning of the loop. Changing the value of the end variable in the loops body won't have any effect. For example the following loop will be executed 10 times not 100 times. EndValue = 10 For I = 1 to EndValue EndValue = 100 More statements Next I 53

WhileWend
The WhileWend loop executes a block of statements while a condition is True. The WhileWend loop has the following syntax: While condition Statement block Wend If condition is True, all statements are executed and when the Wend statement is reached, control is returned to the While statement which evaluates condition again. If condition is False, the program resumes with the statement following the Wend statement. The following example loop prompts the user for numeric data. The user can type a negative value to indicate that all values are entered. Number = 0 While Number => 0 Total = Total + Number Number = InputBox("Please enter another value") Wend

The Exit Statement


The Exit statement allows you to exit prematurely from a block of statements in a loop, or from a procedure. To exit loops you use: Exit Do Exit For To exit functions and subroutines you use: Exit Function Exit Subroutine The following example calculates the square root of a series of numbers and exits if a number is negative: For I = 0 to Ubound(nArray()) If nArray(I) < 0 Then MsgBox "Negative Value found, terminating calculations" Exit Function End If NArray(I) = Sqr(Narray(I)) Next

54

Exercise 3 Script Logic


Objective: Create a script with functions within it. Create a function with parameters to do a calculation and a return value. Verify function parameters. Create a function to log a message parameter and terminate execution. Test functions.

Instructions: STEP 1: Create a new script named EX03 STEP 2: Create a function called PriceCalc which accepts 2 numeric parameters, SalePrice and Discount, and returns a numeric value. STEP 3: Check that neither parameter is zero, if either are zero then return zero. STEP 4: Perform the calculation SalePrice (SalePrice * (Discount/100)) and return the result. STEP 5: Create a second function called Timeout which accepts a string parameter, outputs a Failed usercheck command with the parameter as the message and exits the script.

55

Example

56

Chapter 4 Variables, Arrays & Collections


Variables
Naming Conventions
Variable names must begin with a letter, they can not contain a period or any typedeclaration characters. They must not exceed 255 characters and must be unique within their scope.

Types of variables
Numeric Variables. Integer Long Single Double Currency Examples: Stores integer values in the range -32,768 to 32,767 Long integers in the range -2,147,483,648 to 2,147,483,647 Single precision floating point numbers in the range -3.402823e38 to -1.401298e-45, 0 can not be represented precisely. Double precision floating point numbers. Negative numbers in the range -1.79769313486232e308 to -4.94065645841247e-324 and positive numbers 4.94065645841247e-324 to 1.79769313486232e308. Fixed point number with 4 decimal digits in the range -922,337,203,685,477.5808 to 922,337,203,685,477.5807. Dim Count as Integer Dim DaysInCentury as Long Dim Length as Single Dim Area as Double

String Variables. The string data type store only text and are all declared the same way: Dim SomeText as String A string variable can theoretically hold almost 2gb of text. Examples: SomeText = "" rem sets Sometext to blank SomeText = "There are approx 12,000 words in this chapter" SomeText = "15,000"

57

Fixed Length Strings Strings vary in size to according to the values assigned to them. You can force a string to be a fixed length with a statement like the following; Dim SomeText As String * 1000 An assignment of less than 1000 characters will be padded with spaces, more than 1000 characters will be truncated. Boolean variables These have the value of -1 (For True) and 0 (For False) although any non-zero value will be considered false. Boolean variables are initialized to False. Dim Failure As Boolean Example: If Failure Then MsgBox "Test Failed"

Date Variables A variable declared as date can hold both data and time values. The declaration is: Dim Expiration As Date Examples: Expiration = "01/01/2003" Expiration = "13:03:05 AM" Expiration = "02/23/2002 3:03:05 AM" Expiration = #02/23/2001 10:03:05 PM#

Constants Constants do not change value once they have been declared and are faster in execution than variables. They are declared as follows: Const ConstantName [As Type] = value Examples: Const Pi As Double = 3.141592653589979 Const ExpDate = #31/12/2001#

58

Arrays
Declaring Arrays
Arrays must be declared with the Dim statement followed by the name of the array and the maximum number of elements it can hold. Dim Salary(15) As Long Dim Names(15) As String Note the type of the array is optional. Examples: Names(0) = "John Doe" Salary(0) = 34000 Names(1) = "Dave Smith" Salary(1) = 62000

Specifying Limits
By default an array has index values from 0 to the Dim statements upper bound, ie. in the above example the index went from 0 to 15 (16 entries). However it is possible to define the lower bound of an array explicitly as follows: Dim Names (1 to 16) as String Dim MyNumbers (10 to 20) as Long. Multidimensional Arrays When data is related as in the above example it can be more convenient to declare a multidimensional array. Dim NameSalary (15,15) NameSalary(0,0) = "John Doe" NameSalary(0,1) = 34000 NameSalary(1,0) = "Dave Smith" NameSalary(1,1) = 62000 Dim Matrix (9,9,9) This is a 3 dimensional array consisting of 1000 elements (10x10x10)

59

Collections
Arrays can only be accessed by a numeric index, if you want to use an Alphanumeric index value then we have to use collections. Collections can be useful for storing captured data where we use an alphanumeric value such as an id or name as an index. The collection is declared as follows: Dim Salaries As New Collection A collection object provides three methods and one property Add Method Remove Method Item method Count Property Adds items to the collections Deletes an item from the collection by index or key Returns an Item by index or key Returns the number of items in a collection.

Adding to a Collection
The Add method adds new items to a collection and has the following syntax: Collection.Add value, key, before, after To add a new element to a collection assign its value to the value argument and its key to the key argument. To place the item in a specific location in the array, specify one of the arguments before or after (but not both). To add the salary for John Doe to the Salary collection use the following statement: Salary.Add 34000,"John Doe" To add the salary for Dave Smith after John Doe use the statement: Salary.Add 62000,"Dave Smith",,"John Doe"

Removing an item from a collection


The Remove method removes an item from a collection. This can be done by the key value or if known the position in the collection: Salary.Remove "Dave Smith" Or Salary.Remove 2

60

Returning Items in a collection


The Item method returns the value of an item in a collection. This can be done by the key value or if known the position in the collection. Amount = Salary.Item("John Doe") Amount = Salary.Item(1) The Item method is the default method for a collection object and may be omitted. Amount = Salary("John Doe")

Counting a collection
The Count property returns the number of items in the collection. Number = Salary.Count You can also use the Count property to scan all the elements in a collection: For I = 1 to Salary.Count [process] Next I

Option Explicit
Using the "Option Explicit" statement is good programming practice. When the Option Explicit statement is at the start of a script, VBA generates a compile time error if it encounters a variable that has not been declared Option Explicit Sub Main() Dim Example As Double

61

Variable Scope
Variables declared in a script outside of any procedure or subroutine can be accessed by all the procedures within that script. If the variable is defined within a procedure then it can only be referenced within that procedure. Option Explicit Dim Var1 As Integer Sub Main() Dim Var2 As Double End Sub Sub Temp End Sub In the above example the variable Var1 is available to procedures Main and Temp, however Var2 is only available within Main. If it is required to make a variable available to more than one script then it should be defined in a shared module and instead of using the Dim statement the Public statement is used instead. Public Var1 As Integer

62

Exercise 4 Variables, & Collections


Objective: Create a script using a collection. Add values to a collection Retrieve individual collection items by key value Retrieve all the items from the collection.

Instructions: STEP 1: Create a new script named EX04 STEP 2: Define a collection called "Temperatures". STEP 3: Write code to add the following 5 temperatures and cities with the cities as the key: 76 Atlanta 85 Los Angeles 97 Las Vegas 66 Seattle 70 New York STEP 4: Create a loop containing code that uses the "InputBox" function to request a city and "MsgBox" to display the temperature looked up by the city in the collection. Use the "On Error GoTo NotFound" command to go to a label (NotFound:) and exit the loop. STEP 6: Use MsgBox to display the count and average temperatue.

63

Examples Final script

64

Input Box

City Temperature Display

Average Temperature Display

65

Chapter 5 Modules and Class Modules


Modules store variables declarations and code (functions and subroutines), which are available to all other components of a testpartner project. If the function NewDate developed earlier is going to be called from several different scripts then you should implement it in a module. Procedures stored in a module can be called from any script in a project, the same is true for variables that must be accessed by multiple scripts. This is one method by which scripts can exchange information. You can think of procedures as the methods of the Module, only you don't have to prefix them with the name of the module when you call them. The public variables you store in a Module can also be though of as properties of the module. Therefore a Module is similar to a class, and Classes are implemented as special types of Modules called Class Modules. Testpartner actually has 3 module types, Modules, Shared Modules, and Class Modules. The only difference between Modules and Shared Modules is that to access a Module from a script it must be explicitly included in the script using a '$TPInclude "Module1" statement. Shared Modules are always available to scripts without needing an include statement. From this point forward we will only refer to Modules and Class modules. When do you use Modules and when do you use Class Modules? If you only have a few procedures and global variables for a single project then a Module will probably be acceptable. However there are problems which can occur with Modules, if 2 modules both contain the same function name they can not both be included. If a module has public variables which conflict with variables defined in scripts then you may get unpredictable errors in those scripts. Using Class modules overcomes the above problems, to access a Class Module you must use an object variable. When you enter the name of the object variable and a period a list of its members becomes available, this uniquely identifies them. More details on class modules are covered in the Class Modules section.

Modules
Adding a Module
A module is a set of declarations, followed by procedures, that is designed to accomplish a particular task. The TestPartner module is equivalent to a Standard module in Visual Basic. In TestPartner, module assets are stored in the project in which they are created and have to be explicitly included in any test script that requires them. Select the option View -> Asset Browser on the menu bar.

66

Under Asset Types, right-click Module. Select New from the context menu.

TestPartner displays an empty code window. You can select Insert -> Procedure to add the template for a Public or Private subroutine, function, or property. You can write the code using Visual Basic syntax and TestPartner objects as you would any Visual Basic module.

Using A module
The following code is a simple timing module: Public TotalInterval as Double Dim T1 As Double Sub StartCounting() T1 = Time End Sub Sub StopCounting() TotalInterval = TotalInterval + Time - T1 End Sub Sub ResetTimer() TotalInterval = 0 End Sub Startcounting() starts the timer and the subroutine StopCounting() pauses the timer. Each time the timer is stopped, the TotaInterval variable is updated. A script to use this module to time a test would look as follows: '$TPInclude "TimerMod" Sub Main() StartCounting Rem code here StopCounting TestLog.Comment ("Time Taken =" & Hour(TotalInterval) & " Hours " & _ Minute(TotalInterval) & " minutes " & _ Second(TotalInterval) & " seconds.") End Sub

67

Shared Modules
Adding a Shared Module
As in Visual Basic, a TestPartner Shared Module is a set of declarations, followed by procedures, that is designed to accomplish a particular task. In TestPartner, a shared Module is stored in a designated project and is automatically visible to all assets in that project. To use shared modules in other projects, you must explicitly include them in any test script that requires them. Select the option View -> Asset Browser on the menu bar. Under Asset Types, right-click Shared Module. Select New Shared Module from the context menu.

TestPartner displays an empty code window. You can select Insert | Procedure to add the template for a Public or Private subroutine, function, or property. You can write code using Visual Basic syntax and TestPartner objects as you would any Visual Basic module.

Using a Shared Module


If TimerMod was stored as a Shared Module then the only difference in the test script would be that an Include statement is not required. Sub Main() StartCounting TestLog.Comment ("Count started") Rem code here StopCounting TestLog.Comment ("Time Taken =" & Hour(TotalInterval) & " Hours " & _ Minute(TotalInterval) & " minutes " & _ Second(TotalInterval) & " seconds.") End Sub

68

Class Modules
Adding a Class Module
A class module is the definition of a class, including its properties and methods. You can use class modules when you need to explicitly control scope of visibility. The TestPartner class module is equivalent to class modules in Visual Basic. For more information, see "classes" and "Class Module" in the Visual Basic help. Class module assets are not automatically visible to other assets in a project. Select the option View -> Asset Browser on the menu bar. Under Asset Types, right-click Class Module. Select New Class Module from the context menu.

TestPartner displays an empty code window. You can select Insert | Procedure to add the template for a Public or Private subroutine, function, or property. You can write the module using Visual Basic syntax and TestPartner objects as you would any Visual Basic module.

Using a Class Module


Implementing the same timer code as a class module would have the following code: Dim TotalInterval As Double Dim T1 As Double Public Sub StartCounting() T1 = Time End Sub Public Sub StopCounting() TotalInterval = TotalInterval + Time - T1 End Sub Public Sub ResetTimer() TotalInterval = 0 End Sub Property Get ElapsedTime() As Double ElapsedTime = TotalInterval End Property The above code is similar to a standard module but has differences.

69

There is no longer a public variable, the variable TotaInterval can only be accessed through the ElapsedTime() procedure. This is a special type of procedure called Property Get. The value of the TotalInterval variable can only be accessed through the ElapsedTime procedure. Its code reads the value of the TotalInterval local variable and assigns it to the ElapsedTime() procedure. This is the value that is returned to the calling script. This example does not need to set a variable in the class module but if it was needed then you would have a Property Let procedure, the opposite of the Property Get. You can also have Private procedures which can be called from within the module but can not be accessed from outside the module. The methods of the Class Module are identical to the methods of the Module. Adding a method to a Class is as simple as declaring a Public function or subroutine in that class module. The script to use the class module is as follows: '$TPInclude "ClassTimerMod" Sub Main() Dim Etime As Double Dim TMR As New ClassTimerMod TMR.StartCounting TestLog.Comment ("Count started") Rem code here Pause 5 TMR.StopCounting Etime = TMR.ElapsedTime TestLog.Comment ("Time Taken =" & Hour(Etime) & " Hours " & _ Minute(Etime) & " minutes " & _ Second(Etime) & " seconds.") End Sub

70

Exercise 5 Modules and Class Modules


Objective: Create a Class module. Use multiple instances of that class module Time various aspects of QADemo Web.

Instructions: STEP 1: Create a Class Module using the timer code described in this chapter. STEP 2: Copy script EX02 and save it as EX05 STEP 3: Modify EX05 to make the Timer Class module available STEP 4: Use the timer class module to time how long EX05 takes to run and how long each of the child scripts take to run. STEP 5: Write all 4 timing values to the script log. Examples The Class Module ClassTimerMod

71

Script EX05 Option Explicit '$TPInclude "ClassTimerMod" Sub Main() Dim EX05Time, SignonTime, ClearDBTime, ShutdownTime As Double Dim TMR1 As New ClassTimerMod Dim TMR2 As New ClassTimerMod TMR1.ResetTimer TMR1.StartCounting TMR2.ResetTimer TMR2.StartCounting Run ("Signon") TMR2.StopCounting SignonTime = TMR2.ElapsedTime TMR2.ResetTimer TMR2.StartCounting Run ("ClearDataBase") TMR2.StopCounting ClearDBTime = TMR2.ElapsedTime TMR2.ResetTimer TMR2.StartCounting Run ("Shutdown") TMR2.StopCounting ShutdownTime = TMR2.ElapsedTime TMR1.StopCounting EX05Time = TMR1.ElapsedTime TestLog.Comment ("EX05 Time: " & Minute(EX05Time) & " minutes " _ & Second(EX05Time) & " seconds.") TestLog.Comment ("Signon Time: " & Minute(SignonTime) & " minutes " _ & Second(SignonTime) & " seconds.") TestLog.Comment ("Clear DB Time: " & Minute(ClearDBTime) & " minutes " _ & Second(ClearDBTime) & " seconds.") TestLog.Comment ("Shutdown Time: " & Minute(ShutdownTime) & " minutes"_ & Second(ShutdownTime) & " seconds.") End Sub Extract from Log of EX05

72

Chapter 6 Alias Mapping


Windows applications are popular because of their user-friendly interface. A number of control types have been introduced to provide simple, intuitive ways to use computer systems. There are toolbars (bars with buttons that give single-click access to the most commonly used features of a program), spin controls (which allow you to increase or decrease a value by pressing an up or down arrow), sliders, tabs, grids, etc., all of which help to make sophisticated applications easier to use. Many of the application development systems available today feature variations on these common control types and some even include third-party extension controls. When you record a script, TestPartner automatically recognizes standard control types (that is, controls with classes of button, edit, listbox, radio button, etc.) and generates a script entry that records them at object level without reference to their positions. But if you use an application that incorporates non-standard controls, it is possible that TestPartner will not be able to recognize them. When this happens, TestPartner abandons object-level recording and learns keystrokes, mouse-clicks, and screen coordinates. This ensures the script will replay correctly but it makes the script more difficult to understand and maintain. When a control cannot be learned at object level because of a non-standard class name, you can register it as a standard control within the Alias Map. The Alias Map crossreferences non-standard controls to standard control types. You must ensure that the non-standard control is comparable to a standard control for alias mapping to work properly. For example, you can register a non-standard button as a standard button but you cant register a spin-type control as a list box or a radio button type control as a toolbar! In the example below the listbox and buttons look standard but are actually not standard windows controls.

73

Recording clicking on the second item in the listbox and then clicking on the Open Dialog button results in the following code: Window("This Is A Delphi Program Window").Attach GUIObject("ClassName=TListBox Caption=''").Attach GUIObject.TextSelect "Item 2" GUIObject("ClassName=TButton Caption='Open Dialog'").Attach GUIObject.Click 17, 20

Because this is a Delphi program the listbox class is actually TlistBox rather than ListBox and the button has a class of TButton instead of Button. TestPartner has recorded the controls as GuiObjects and recorded an attach to the objects and then an action on each object, a textselect in the case of the list and a mouseclick in the case of the button. However as it is quite clear that these controls are a listbox and a button we can register them as that in the Alias Map. Having done this if we record the above script again the following script is generated: Window("This Is A Delphi Program Window").Attach ListBox("Parent.Caption=Panel1").Select "Item 2" Button("Caption='Open Dialog'").Click This generates a script that is much more sensible, easier to read and interpret, and faster to execute. TestPartner attaches to the Window (This is a Delphi Program) selects a listbox item and clicks the Open Dialog button . All the previous references to GUI objects are gone and textselects and mouseclicks have been replaced by commands which represent the object they are operating on.

Using Alias Mapping


It is better to assign Alias Map entries before starting work on your test scripts this avoids having to modify scripts that have not used Alias Map entries. You should Record a few trial scripts against your target application to see if non-standard control types are used. Begin recording a script and use all the available control types in your application. Turn Record off and examine the script. If you have mouse-clicks appearing where you would expect to see button clicks, check box selections, and other control usage, then you may have candidates for alias mapping.

74

It is not necessary to register every non-standard control as a standard control. You should only need to register one example of each non-standard type. The Alias Map will then apply the same mapping to all other controls of the same class.

Adding Alias Map Entries


Use the following procedure to create a new Alias Map Entry: 1. Run your target application to a point where the non-standard control type is displayed. 2. From the menu system select Tools->Alias Map to display the Alias Map window.

3. Click on the Create button (just above Class Name) and the Object Selection window appears.

75

4. Click the Identify button and place the mouse pointer over the object to be registered. The object must be highlighted (surrounded by a shadow border) to be registered in the Alias map. Note: If the object is not highlighted then it is not a true control. It is a bitmap (picture) with the appearance of a control and cannot be registered. Use Image mapping rather than alias mapping to register this type of control. 5. Click once with the left mouse button; the object's details are automatically entered into the identify window. 6. Click the OK button on the object selection window. The Add Class Alias dialog box displays:

76

7. Type a Description of the control and select a standard control alias from the Alias name drop-down list. 8. Click OK to complete the registration. 9. The entry is made into the Alias Map window, to add another entry click on the Create button again. If there are no more objects to register then close the Alias Map (Winclose button or menu entry file->close). You should test the registration by learning your trial script again. In some circumstances, alias mapping does not produce the results you might expect. This usually happens when the internal behavior of the non-standard control does not resemble the type of control it is mimicking.

Modifying Alias Map Entries


You can modify any control definition after it is identified in the Alias Map. Use the following procedure to edit an existing Alias Map entry: 1. Highlight the entry in the Alias Map. 2. Click on the Edit button, note this is grayed out until an entry is selected.

77

3. Change the Class name, Description, and Alias name entries as required. Note: Modifying Alias Map entries will cause the scripts that use the old definition to fail.

Deleting Alias Map Entries


Use the following to delete an Alias Map entry: 1. Highlight the entry in the Alias Map. 2. Click on the Delete button, note this is grayed out until an entry is selected. Note: Deleting Alias Map entries will cause the scripts that use the old definition to fail.

78

Exercise 6 Alias Mapping


Objective Record against a Delphi Application Modify the Alias Mapping for a better recording

Instructions: STEP 1: Switch off the Text Select option for recording. STEP 2: Record Loading the delphi sample application supplied by the instructor. STEP 3: Record clicking on the Open Dialog Button, Click on the OK button displayed in the Sample Dialog window, Click on the Close App button. STEP 4: Set up an Alias for the buttons. STEP 5: Record the script again and look at the differences.

79

Examples. Script before using Alias's. Sub Main() Window("Window").Attach Button("Caption=Start").Click Window.PopupMenuSelect "Run..." Window("Run Window").Attach ComboBox("Label='&Open:'").SetText _ "C:\Program Files\Compuware\TestPartner\DelphiSample.exe" Button("Caption=OK").Click Window("This Is A Delphi Program Window").Attach Window.Size 870, 691 Window.Move 77, 38 Window("This Is A Delphi Program Window").Attach Window.Size 870, 691 Window.Move 77, 38 GUIObject("ClassName=TButton Caption='Open Dialog'").Click 68, 22 Window("Sample Dialog 1 Window").Attach GUIObject("ClassName=TButton Caption=OK").Click 152, 44 Window("This Is A Delphi Program Window").Attach GUIObject("ClassName=TButton Caption='Close App'").Click 27, 19 End Sub Setting the Alias

80

The Final script with the Alias. Sub Main() Window("Window").Attach Button("Caption=Start").Click Window.PopupMenuSelect "Run..." Window("Run Window").Attach ComboBox("Label='&Open:'").SetText _ "C:\Program Files\Compuware\TestPartner\DelphiSample.exe" Button("Caption=OK").Click Window("This Is A Delphi Program Window").Attach Window.Size 870, 691 Window.Move 77, 38 Window("This Is A Delphi Program Window").Attach Button("Caption='Open Dialog'").Click Window("Sample Dialog 1 Window").Attach Button("Caption=OK").Click Window("This Is A Delphi Program Window").Attach Button("Caption='Close App'").Click End Sub

81

82

Chapter 7 Image Mapping and Text Selects


Image Mapping
Image mapping lets you capture images (pictures) that are not true Windows objects and store them by allocating a descriptive name to each one. Thereafter, whenever you record a mouse-click on that image, your defined image name is used within the script. The use of images within Windows applications is becoming increasingly common. Clicking on a picture to initiate a task is now a familiar practice. If you have used a web browser to access the Internet, you should be familiar with screen hotspots. Many new Windows applications allow you to change their appearance. You can often add or remove buttons from toolbars, rearrange their order, or even move the entire toolbar to a different location. The problem with controlling this type of application is that the individual hotspots or toolbar buttons are not necessarily true Windows objects. They may not exist as discrete entities with a name of their own, they are simply areas within windows. Normally, recording this type of system results in a script full of mouse-click commands. The Image Map allows you to change all that. We switch on Image mapping by selecting the Tools menu and Options entry.

83

Then within the Options window, in the Record section ensure that the Bitmap selects is set to Yes.

The following is a recording against a calculator (below) where what appear to be buttons are actually just pictures within a window. The recording is done without the bitmap select option, and is a recording of 4 * 5 = .

84

The resulting script is: Sub Main() Window("Calculator Window").Attach Window.Click 79, 131 Window.Click 195, 135 Window.Click 120, 134 Window.Click 237, 199 End Sub While the above code is valid, and will always work it is not possible to understand which buttons have been clicked. To make the script clearer, we can use the bitmap select option. This, if on will automatically generate bitmaps according to the window name and position on the image that is clicked. However even this is not very satisfactory as in the above case the script would be: Window("Calculator Window").Attach Window.BitmapSelect "Calculator" Window.BitmapSelect "Calculator1" Window.BitmapSelect "Calculator2" Window.BitmapSelect "Calculator3" Not only can we still not understand from the script what keys are being pressed, but if we go to the object map in testpartner:

85

Then we double click on an entry (Calculator1) in the window to display the details and select the Preview Image tab. Unfortunately we discover that we must have clicked on the corner of the button and the image learnt still does not tell us which key this is.

The solution to all the above problems is to learn all the required images first. We learn images by ensuring we are in the object map section of the asset browser, right click on Object Map in the left pane, select New Map Entry and then Image:

86

This takes us to a screen where we can name what we are going to capture (Calculator_Button_No4) and then click on the Capture button to go and draw a box around the key whose image we want to store.

If we then check the preview image tab of the Image Map window we will find we have a good recording of the image.

87

And we can then save and close the image details. By repeating the above process for every image we require to capture we can ensure that we have an understandable script as follows: Window("Calculator Window").Attach Window.BitmapSelect "Calculator_Button_No4" Window.BitmapSelect "Calculator_Button_Multiply" Window.BitmapSelect "Calculator_Button_No5" Window.BitmapSelect "Calculator_Button_Equals" The basic rule of using bitmap images is that if they are required it is best to learn them first to ensure good naming conventions and sensible stored bitmap images.

88

TextSelects
The TextSelect option allows the selection of text when this text may not be on a recogniseable control. The TextSelect option generates simpler code which does not require storing information in the database. The text select option is selected in the same way as bitmap selects above.

Now when we record our Calculator example we get the following script: Sub Main() Window("Calculator Window").Attach Window.TextSelect "4" Window.TextSelect "*" Window.TextSelect "5" Window.TextSelect "=" End Sub

89

You must be careful to click exactly on the character, if you miss the character then the bitmap option will be used instead (assuming bitmap selects are still switched on), however Text Selects always take priority over Bitmap Selects. Also with Text Selects care must be taken that the same text does not exist elsewhere in the window as the first occurrence of this text will be the one selected when playing back the script.

90

Exercise 7 Image Mapping and Text Selects


Objective To learn a bitmap image To manually insert a bitmap select into a script To manually insert Text Selects to improve script readability

Instructions: STEP 1: Switch on Bitmap selects and Text Selects STEP 2: In the Signon Script add a recording of clicking on the ? on the toolbar and then closing the information window. STEP 3: Learn the bitmap image for the ? icon and replace the recorded "HTMLBrowser.Click 184, 71" with a Window.BitmapSelect command for the for the image. STEP 4: Examine the Shutdown script and where the menu was used to logoff replace the Clicks with TextSelects.

Examples:

Mouseclick on the ? icon. Window("Microsoft Internet Explorer").Attach HTMLBrowser("Caption='QADemo - Main'").Attach HTMLBrowser.Click 184, 71 Window("Microsoft Internet Explorer").Attach Window.Close

91

Code with the BitmapSelect. Window("Microsoft Internet Explorer").Attach HTMLBrowser("Caption='QADemo - Main'").Attach Window.BitmapSelect "ToolBar_Question_Mark" Window("Microsoft Internet Explorer").Attach Window.Close Shutdown code with click commands Sub Main() Window("Microsoft Internet Explorer").Attach HTMLBrowser("Caption='QADemo - Main'").Attach HTMLTD("ID=td_1").Click 16, 9 HTMLTD("ID=td_1_3").Click 21, 8 Window.Attach Window.MenuSelect "File~Close" End Sub Shutdown script with TextSelects Sub Main() Window("Microsoft Internet Explorer").Attach HTMLBrowser("Caption='QADemo - Main'").Attach HTMLBrowser("Caption='QADemo - Main'").TextSelect ("File") HTMLBrowser("Caption='QADemo - Main'").TextSelect ("Logoff") Window.Attach Window.MenuSelect "File~Close" End Sub

92

Chapter 8 Test Data Handling


TestData Files
TestData files provide an efficient way for scripts to access external data. The use of TestData files enables the logic of a script to be separated from its data. For example, to input 500 entries into a database application, you only need to script a single entry. The script can read the 500 sets of input data from an external TestData file at runtime. A TestData file is, typically, a comma separated variable file. In the file each line constitutes a record, and each record contains a number of fields separated by commas. (Note. VBA can be written to read any type of input file or database required). The following would be a CSV file containing 3 records with 3 fields per record. Brown,Joe,1234 Little Street Smith,Sally,5678 Big Street Green,Sam,135 New Street Testdata files can be created with a text editor (such as Notepad), or they can be produced from a spreadsheet (Excel) or database program that can export or save files in CSV format. Note there should not be any spaces between the fields and their comma separators as this will be considered part of the data. This chapter will describe three methods of accessing testdata, how to access a standard CSV file, how to access a spreadsheet file directly, and how to access a CSV file with a header record to give each field a unique id.

93

Accessing a Standard CSV file


In order to open a file we must obtain the next available file number using the FreeFile function and then open the file. The code to achieve this is as follows Dim myFile As Integer myFile = FreeFile() Open "YourTestDataFilename.csv" For Input As #myFile We need to process all the records in the file until we reach the end of the testdata, this is achieved by the use of the While loop and the EOF function: Do While Not EOF(myFile) ' code goes here Loop The value in myFile was obtained in the earlier code example, "Loop" is the end of the While loop and returns control to the "While" statement which tests for having reached the end of the file "EOF(myFile)". If the end of the file has been reached then control is returned to the statement after the "Loop" statement. In order to access the separate fields we must read in the line of data with the "Line Input" statement and then split the line into separate fields using the "split" function to store the fields in an array. Dim TextLine As String Dim SplitArray() As String Line Input #myFile, TextLine SplitArray = Split(TextLine, ",") The first element of an array is 0, so the first field must be accessed as SplitArray(0), we are splitting our fields on a "," character, but any character could be used as the field separator. The individual fields would thus be accessed as follows: EditBox("Label='&Name :'").SetText SplitArray(0) EditBox("Label='&LastName :'").SetText SplitArray(1) EditBox("Label='&Address :'").SetText SplitArray(2) Finally to close the TestData file when processing is finished you should use the "Close" statement:

94

Close (#myFile) The final script to use the above code would thus look similar to the following: Sub Main() Dim myFile As Integer Dim TextLine As String Dim SplitArray() As String myFile = FreeFile() Open "C:\testdata\customer.csv" For Input As #myFile ' start the loop Do While Not EOF(myFile) ' input a record and split into fields Line Input #myFile, TextLine SplitArray = Split(TextLine, ",") Window("New Customer Details Window").Attach EditBox("Label='&Name :'").SetText SplitArray(0) EditBox("Label='&LastName :'").SetText SplitArray(1) EditBox("Label='&Address :'").SetText SplitArray(2) Button("Caption=OK").Click Loop ' End of the while not eof loop

Close #myFile

95

Accessing an Excel Spreadsheet


Before you can access a spreadsheet directly you must have the correct option configured. Within TestPartner ensure that you have a script loaded (new or existing). Go to the "Tools" menu item and select entry "References", and in the references window ensure that the "Microsoft Excel 8.0 Object Library" has a check mark.

We need variable definitions for the Excel application, workbook and worksheet as follows: Dim apExcel As Excel.Application Dim wbCustomer As Excel.Workbook Dim shAddress As Excel.Worksheet Then to start the excel interface and open a workbook and worksheet we need the following code: Set apExcel = New Excel.Application Set wbCustomer = apExcel.Workbooks.Open("C:\testdata\customer.xls") Set shAddress = wbCustomer.Worksheets("customer")

96

Obviously the filename and worksheet name should match your spreadsheet and not be exactly as above. The rows and columns within the spreadsheet are accessed with the "shAddress.Cells.Item(r, c)" statement. "r" is the row, and the first row is 1, "c" is the column and the first column is 1. Thus using the data given earlier in this chapter, if it was in an excel spreadsheet, "shAddress.Cells.Item(1, 2)" would return "Joe" and "shAddress.Cells.Item(2, 1)" would return "Smith". The final script to duplicate what is being done in the CSV file example above would be similar to the following: Sub Main() Dim apExcel As Excel.Application Dim wbCustomer As Excel.Workbook Dim shAddress As Excel.Worksheet Dim i, j As Integer Set apExcel = New Excel.Application Set wbCustomer = apExcel.Workbooks.Open("C:\testdata\customer.xls") Set shAddress = wbCustomer.Worksheets("customer") For i = 1 To 3 Step 1 Window("New Customer Details Window").Attach EditBox("Label='&Name :'").SetText shAddress.Cells.Item(i,1) EditBox("Label='&LastName :'").SetText shAddress.Cells.Item(i,2) EditBox("Label='&Address :'").SetText shAddress.Cells.Item(i,3) Button("Caption=OK").Click Next ' End of for loop End Sub Note that we now need to know the number of rows in the spreadsheet, this could be overcome by putting a special terminator record in the spreadsheet and testing for it.

97

Accessing a CSV file with Column Headings


Using a testdata file where the first row contains a unique heading for each column allows us to access the data using the heading as a field name. This gives us much more reliable code, as we are no longer concerned with the order of the fields within the record. It also provides an easier to understand script, as it is immediately obvious which field we are dealing with. The final script is thus less error prone, easier to maintain, and does not require maintenance if additional fields are added to the data. In order to achieve this, the following code must be added as a Class Module, following examples assume it has been added with the name TestDataFunctions. '***************************************************************** '* This module provides functions for processing a CSV file '* where the first row (record) contains the names of the '* Columns (Fields) used to access the data starting at row (record) 2 '***************************************************************** Option Explicit Dim FieldNames() As String Dim Data As New Collection Dim myFile As Integer Dim TextLine As String Dim SplitArray() As String Dim FieldCount As Integer '***************************************************************** '* Open the data file and read the first line as field names for later use '***************************************************************** Public Function OpenData(TestFile As String) As Integer Dim I As Long '-----------------------' Open the test data file '-----------------------myFile = FreeFile Open TestFile For Input As #myFile Line Input #myFile, TextLine '-----------------------------------------------------' Store the first line as the field names for later use '-----------------------------------------------------FieldNames = Split(TextLine, ",") '---------------------------------------'Count the number of fields in the record '---------------------------------------FieldCount = 1 ' Number of fields is 1 more than seperators For I = 1 To Len(TextLine) If Mid(TextLine, I, 1) = "," Then 98

FieldCount = FieldCount + 1 End If Next OpenData = myFile End Function Public Function ReadNextDataRecord() As Boolean '***************************************************************** '* Read the next data record and store the data in a collection using '* the fieldnames obtained at file open for reference '***************************************************************** Dim I As Integer If Not EOF(myFile) Then '-----------------------------------------' 1st remove existing items from collection '-----------------------------------------For I = Data.Count To 1 Step -1 Data.Remove (I) Next '-----------------------------------------------' read the next line and split on field seperator '-----------------------------------------------Line Input #myFile, TextLine SplitArray = Split(TextLine, ",") '----------------------------------------------------------' Store in the data collection using the fieldnames as a key '----------------------------------------------------------For I = 0 To FieldCount - 1 Data.Add SplitArray(I), FieldNames(I) Next ReadNextDataRecord = True Else ReadNextDataRecord = False End If End Function '************************************************* '* Return the data item at the named key position '************************************************* Property Get DataItem(ItemName As String) As String DataItem = Data.Item(ItemName) End Property '************************************************* '* Close the file '*************************************************

99

Public Function CloseData() Close #myFile End Function

100

Using the above code is very straightforward, but to demonstrate how we first need a simple test data file: Reference,Make,Color Car0012,Ford,Green Car0023,Pontiac,Blue Car0045,Chevrolet,Black The above file is a comma separated file with 3 fields in each of 3 data records. The header record provides us with field names Reference, Make, and Color. Before we can access the functions within the Class Module from our script we will have to include the class module and define a new instance of the TestDataFunctions object: '$TPInclude "TestDataFunctions" Sub Main() Dim TD As New TestDataFunctions we will call our test data object TD

Once this is done we can access the functions within the class module: TD.OpenData ("C:\Temp\TestFile.csv") Opens the data file for us and reads in the heading details. TD.ReadNextDataRecord Reads the next data record and returns a value of True if there is a data record and False if there is not a record. TD.DataItem("Reference") Returns the data item for Reference in the current record (Car0012 in the first record). TD.CloseData This closes the data file. 101

A small script to read the above data and display each record could look like the following: '$TPInclude "TestDataFunctions" Sub Main() Dim TD As New TestDataFunctions TD.OpenData ("C:\Temp\TestFile.csv") Do While TD.ReadNextDataRecord = True MsgBox (TD.DataItem("Reference") & " " & TD.DataItem("Make") _ & & TD.DataItem("Color")) Loop TD.CloseData End Sub

102

Exercise 8 Test Data Handling


Objective Create a Class Module for handling test data files. Record a script to enter one data record Create a test data file Modify the script to read from a test data file.

Instructions: STEP 1: Create a class module called TestDataFunctions as described in the chapter above. STEP 2: Copy Script EX05 and save as Script EX08. STEP 3: Place an end statement between the Run ClearDataBase and the Run Shutdown statements in the script. Execute the script, when the End statement is encountered the application will be left at the correct position to start recording a script to enter data. STEP 4: Create a new script called AddCars. Record the following actions on QADemo Web: Select File->Main Options Select Add Car in the list box and click on OK Type the following information into the Add Car Window: 1. Ref: Car 1 2. Make: Ford 3. Engine Size: 3000 4. Year: 1999 5. Doors: 4 6. Color: Blue 7. Sale Price; 4000 8. Dealer Discount: 15 9. Quantity: 1 Select all 6 Extras (checkboxes) Click the Add button Click the Cancel button (On the Add Car Window) Click the Cancel button (On the New Window) The application should be back at the point the script started. 103

STEP 5: Add a Run AddCars to script EX08 in place of the End statement inserted in step 3. Run script EX08 to ensure it is functioning correctly. STEP 6: Create the following comma separated test data file (cars.csv) using notepad or excel, ensure the first row contains the header information.

STEP 7: Modify the Add Cars Script to open the test data file and read the first line of data. '$TPInclude "TestDataFunctions" TD.OpenData ("C:\Temp\cars.csv") TD.ReadNextDataRecord STEP 8: Modify the HTMLEditBox commands to use the DataItem Function to return the required value from the file. HTMLEditBox("Add Car Window Reference Edit").SetText "Car 1" Becomes HTMLEditBox("Add Car Window Reference Edit").SetText TD.DataItem("Ref") STEP 9: Modify the script to use an if statement on the checkbox values from the test data file to decide whether to click on the checkbox or not. If TD.DataItem("Radio") = "on" Then HTMLCheckBox("Name=chkRadio").Click End If STEP 10: Run the script and ensure it reads the first line of data and enters it into the application.

104

STEP 11: Build a while loop into the AddCars script to read the entire test data file: TD.OpenData ("C:\Temp\cars.csv") While TD.ReadNextDataRecord = True STEP 12: Run the script to ensure it is functioning correctly.

105

Examples: QADemo Web application at required point to record a script to input data.

Add Car Data Window

106

Initial AddCars Script Sub Main() Dim oe As TOnError Set oe = OnError("QADemoErrorFunction") Window("Microsoft Internet Explorer").Attach HTMLBrowser("Caption='QADemo - Main'").Attach HTMLTD("ID=td_1").Click 16, 4 HTMLTD("ID=td_1_1").Click 30, 7 HTMLBrowser("Caption='QADemo - New'").Attach HTMLListBox("Name=lstNew").Select "Add Car" HTMLButton("OK HTMLButton").Click HTMLBrowser("Caption='QADemo - Add Car'").Attach HTMLEditBox("Add Car Window Reference Edit").Click 9, 10 HTMLEditBox("Add Car Window Reference Edit").SetText "Car 1" HTMLEditBox("Add Car Window Make Edit").SetText "Ford" HTMLEditBox("Add Car Window Engine Size Edit").SetText "3000" HTMLEditBox("Add Car Window Year Edit").SetText "1999" HTMLEditBox("Add Car Window Doors Edit").SetText "4" HTMLEditBox("Add Car Window Color Edit").SetText "Blue" HTMLEditBox("Add Car Window Cost Edit").SetText "4000" HTMLEditBox("Add Car Window DealerDiscount Edit").SetText "15" HTMLEditBox("Add Car Window Quantity Edit").SetText "1" HTMLCheckBox("Name=chkRadio").Click HTMLCheckBox("Name=chk4wd").Click HTMLCheckBox("Name=chkSunRoof").Click HTMLCheckBox("Name=chkLeather").Click HTMLCheckBox("Name=chkAirCond").Click HTMLCheckBox("Name=chkMetallic").Click HTMLButton("Add HTMLButton").Click HTMLBrowser("Caption='QADemo - Add Car'").Attach HTMLButton("Cancel HTMLButton").Click HTMLBrowser("Caption='QADemo - New'").Attach HTMLButton("Cancel HTMLButton").Click Window.Attach End Sub

107

Script Modified to read a line of test data file. TD.OpenData ("C:\Temp\cars.csv") TD.ReadNextDataRecord HTMLBrowser("Caption='QADemo - Add Car'").Attach HTMLEditBox("Add Car Window Reference Edit").Click 9, 10 HTMLEditBox("Add Car Window Reference Edit").SetText TD.DataItem("Ref") HTMLEditBox("Add Car Window Make Edit").SetText TD.DataItem("Make") HTMLEditBox("Add Car Window Engine Size Edit").SetText TD.DataItem("Size") HTMLEditBox("Add Car Window Year Edit").SetText TD.DataItem("Year") HTMLEditBox("Add Car Window Doors Edit").SetText TD.DataItem("Doors") HTMLEditBox("Add Car Window Color Edit").SetText TD.DataItem("Color") HTMLEditBox("Add Car Window Cost Edit").SetText TD.DataItem("Price") HTMLEditBox("Add Car Window DealerDiscount Edit").SetText TD.DataItem("Discount") HTMLEditBox("Add Car Window Quantity Edit").SetText TD.DataItem("Quantity") If TD.DataItem("Radio") = "on" Then HTMLCheckBox("Name=chkRadio").Click End If If TD.DataItem("4wd") = "on" Then HTMLCheckBox("Name=chk4wd").Click End If If TD.DataItem("SunRoof") = "on" Then HTMLCheckBox("Name=chkSunRoof").Click End If If TD.DataItem("Leather") = "on" Then HTMLCheckBox("Name=chkLeather").Click End If If TD.DataItem("AirCond") = "on" Then HTMLCheckBox("Name=chkAirCond").Click End If If TD.DataItem("Metalic") = "on" Then HTMLCheckBox("Name=chkMetallic").Click End If HTMLButton("Add HTMLButton").Click

108

Script Changes for While loop TD.OpenData ("C:\Temp\cars.csv") While TD.ReadNextDataRecord = True HTMLBrowser("Caption='QADemo - Add Car'").Attach HTMLEditBox("Add Car Window Reference Edit").SetText TD.DataItem("Ref") HTMLEditBox("Add Car Window Make Edit").SetText TD.DataItem("Make") Main code goes here HTMLButton("Add HTMLButton").Click Wend TD.CloseData

109

Chapter 9 Multiple Events


It is very probable that while testing it will be necessary to handle more than one possible event. For example when updating a database the update may succeed, which would be one possible event to wait for, but it could also fail for several possible reasons. This is handled by a combination of wait and whenever events. A Wait event tells TestPartner to wait for a specified occurrence before proceeding. Wait events are useful in situations where you cannot anticipate the amount of time a response will take. To account for this variance, you can insert a Wait event that instructs your script to wait for the required response before proceeding. A Whenever event tells TestPartner to watch for a specific occurrence and, if it occurs, perform a special set of steps. Whenever events are useful for trapping unexpected error conditions during a test run. For example, you can include events in your scripts to recognize when the connection to the server has been interrupted by a communications error or a network system message has been received, so that the script can report or work around the problem. The types of events available were covered in detail in the previous manual, for the purpose of describing how to handle this we will just use Screen events, however any combination of event types could be used.

Wait Events
The wait command below may have been inserted into your script to wait for a database update to complete before continuing: If Wait(30, "Add Car to DB", tpWaitSeconds) = True Then TestLog.Comment "Event Add Car to DB triggered" Else TestLog.Comment "Event Add Car to DB did not trigger, timeout of 30 _ seconds has been exceeded." End If This could have been inserted using ALT-F7 the shortcut while recording or using the insert menu option while in a script:

110

Whenever Events
If we need to be able to handle another event at the same time we must use a Whenever event command, and this must be defined prior to the wait command to ensure it can be triggered while waiting for the wait event. This could have also been done via an ALT-F7 while recording or it can also be done through the Insert menu. As a whenever event is unlikely to occur at the correct time while recording it is more likely the event will have already been learnt and will now be inserted as follows:

111

With the cursor positioned at the start of the script but after Sub Main the insert menu option is used to insert an event.

Select the event that it is required to use and click on the Insert button.

112

Select the Whenever radio button and Click on the OK button. Sub Main() Whenever (Duplicate Car) If Wait(30, "Add Car to DB", tpWaitSeconds) = True Then TestLog.Comment "Event Add Car to DB triggered" Else TestLog.Comment "Event Add Car to DB did not trigger, timeout of 30 _ & seconds has been exceeded." End If ---------------------------------------------------------------------------------------------Private Sub Script_Whenever(ByVal TheEvent As TPEvents.TEventGroup) End Sub The result, as shown above, is a Whenever event command inserted where we had the cursor positioned, and a subroutine called Script_Whenever inserted at the end of our script to handle the event. Regardless of the number of Whenever commands, there is only one subroutine to handle them in a script. So we must add the following code to determine which Whenever event has just triggered: Private Sub Script_Whenever(ByVal TheEvent As TPEvents.TEventGroup) Select Case TheEvent.Name Case "Duplicate Car" Put code here to handle the error prior to returning to the script ResumeScript Case Else MsgBox "Unknown Event " & TheEvent.Name End End Select End Sub

113

The above select statement switches on the return value from the Object method TheEvent.Name, which returns the name of the whenever event that has just been triggered. Code must be added to handle the event here, if this event occurred while waiting on another event, such as the wait in the example above, then you may need to execute code to ensure the wait event works without error on exiting from the whenever code. The command ResumeScript returns control to the script at the point the whenever event was triggered.

114

Exercise 9 Multiple Events


Objective: Insert a wait event to check data has been added correctly. Insert Whenever events to handle error conditions Add data to existing testdata file to create errors

Instructions: STEP 1: Copy script EX08 to script EX09, within the script change the Run AddCars to Run AddCarsEvents. Copy script AddCars to AddCarsEvents. STEP 2: Place an End instruction after adding the first car details in AddCarsEvents and run script EX09. This should position the application (QADemo Web) with a blank add cars window. Remove the End from AddCarsEvents. STEP 3: With the cursor positioned after the HTMLButton("Add HTMLButton").Click in script AddCarsEvents add a wait screen event which checks that the Ref: field is blank. If the event works, log that the data was added to the database, if not log that the data addition failed. STEP 4: Add the same car details to QADemo Web twice to create a duplicate car error window. At the beginning of the AddCarsEvents script insert a Whenever Screen event to look for the Duplicate Record text. STEP 5: In the Script_Whenever subroutine added to the bottom of the AddCarsEvents script, add code to determine which error has occurred, output a suitable Usercheck command, and add (record) code to recover back to the add car window. STEP 6: Add the following two lines of data to the cars.csv data file.
Ford Taurus Chrysler Sebring 6 cyl 6 cyl 1997 1997 4 Green 2 Black 17500 18995 20 15 10 on 10 on off on on on off on on on off on DUP DUP

STEP 7: Run Script EX09 and ensure everything is working correctly (2 duplicates). STEP 8: Add an extra column to the data called Results, in this column put the words ADD or DUP according to the expected results. STEP 10: Modify the error reporting so that if the result is as expected the usercheck gives a pass and not a fail.

115

Examples: The Reference Field Event.

116

Wait Event Code


HTMLButton("Add HTMLButton").Click If Wait(30, "Add Car Reference Field Blank", tpWaitSeconds) = True Then UserCheck "AddCarsEvents", True, "Car Reference " & TD.DataItem("Ref") & "Added to DB" Else UserCheck "AddCarsEvents", False, "Car Reference " & TD.DataItem("Ref") End If Wend TD.CloseData

Duplicate Record Event

117

Modified data File


Make Ford Taurus Plymouth Breeze Chrysler Sebring Ford Taurus Plymouth Breeze Chrysler Sebring Ford Taurus Chrysler Sebring Size 6 cyl 4 cyl 6 cyl 6 cyl 4 cyl 6 cyl 6 cyl 6 cyl Year Doors Color 1997 1997 1997 1997 1997 1997 1997 1997 4 2 2 4 2 2 4 2 Green White Black Green White Black Green Black Price 17500 12250 18995 17500 12250 18995 17500 18995 Discount Quantity Radio 4wd 20 10 15 20 10 15 20 15 10 10 10 10 10 10 10 10 on off on on off on on on off on on off on on off on SunRoof Leather AirCond Metali c on off on off off on off on on on on on on off on off off on off on on on on on on off on off on on on on Result ADD ADD ADD ADD ADD ADD DUP DUP

Final Script Whenever Subroutine


Private Sub Script_Whenever(ByVal TheEvent As TPEvents.TEventGroup) Select Case TheEvent.Name Case "Duplicate Record" If TD.DataItem("Result") = "DUP" Then UserCheck "AddCars Duplicate Error Event", True, "Car Reference " & TD.DataItem("Ref") Else UserCheck "AddCars Duplicate Error Event", False, "Car Reference " & TD.DataItem("Ref") End If HTMLBrowser("Caption='QADemo - Add Car - Duplicate Record'").Attach HTMLEditBox("Add Car Window Reference Edit").SetText "" HTMLBrowser("Caption='QADemo - Add Car - Duplicate Record'").Attach HTMLButton("Cancel HTMLButton").Click HTMLBrowser("Caption='QADemo - New'").Attach HTMLListBox("Name=lstNew").Select "Add Car" HTMLButton("OK HTMLButton").Click HTMLBrowser("Caption='QADemo - Add Car'").Attach ResumeScript Case Else UserCheck "AddCars UNKNOWN Error Event", False, "Car Reference " & TD.DataItem("Ref") End End Select End Sub

118

Chapter 10 Capturing Data


One of the most important aspects of testing is to capture data from the screen and check if it is the expected value. The script can then be passed or failed by a usercheck method.

Identify icon
This is achieved by the use of the Object Selection screen which is accessed via the identify icon.

The recording must be stopped and the cursor positioned with the script at the point you wish to capture. If you are adding captures to an existing script you can reach this point by inserting a stop command in the script and running the test script(s) to this point which ensures the script and the application are synchronized. In the following example of inputting data to the QADemo Car Database we wish to capture the Dealer Discount value to check if this has been calculated correctly.

119

Having recorded he input of the following information:

We now have a script that contains the following:

120

Use of the Stop Command


This script would normally be one of a series of scripts, for the purpose of this example we will ignore the other scripts required to get the application to this point. We want to insert a capture of the Dealer Price before we click on the ADD button. To reach this pint we will insert a stop command before the Add command and then run the script(s) again. HTMLEditBox("Add Car Window Quantity Edit").SetText "2" HTMLCheckBox("Name=chkRadio").Click HTMLCheckBox("Name=chkAirCond").Click Stop HTMLButton("Add HTMLButton").Click Having reached the Stop command we stop the script by clicking on the stop Icon:

121

Object Selection Screen


We then delete the Stop command and with the cursor positioned on this line (The place we wish to insert the capture) we enter the Object Selection Screen using the Identify Icon as described earlier in the chapter.

We now identify the field that we wish to capture. This is achieved by clicking on the Identify button on the Object Selection Screen. This takes us back to the application with a cursor that we should position over the field we wish to capture and then click the mouse button. Note that Testpartner displays the field type as the cursor is positioned over it.

122

Control is returned to the Object Selection Screen once you have clicked on the required field in the application. You can check in the right hand pane that the field details match what you intended to click on (mistakes do happen).

123

In our case we can tell that the type is an HTMLEditBox and that its name is txtDealerPrice, which is the field we are interested in. We then click on the OK button and the field details are pasted into the script: HTMLEditBox("Add Car Window Quantity Edit").SetText "2" HTMLCheckBox("Name=chkRadio").Click HTMLCheckBox("Name=chkAirCond").Click HTMLEditBox ("Application=IEXPLORE.EXE Name=txtDealerPrice") HTMLButton("Add HTMLButton").Click We should add a variable to receive the captured value, not forgetting to define this variable (as a string) earlier in the script. Dim DealerPrice as String
HTMLEditBox("Add Car Window Quantity Edit").SetText "2" HTMLCheckBox("Name=chkRadio").Click HTMLCheckBox("Name=chkAirCond").Click DealerPrice = HTMLEditBox ("Application=IEXPLORE.EXE Name=txtDealerPrice") HTMLButton("Add HTMLButton").Click

CaptureText Method
By then typing a period at the end of the Dealer Price line we are presented with a list of methods available on this object, one of these is CaptureText, which we select.

124

The resulting code is as follows:


HTMLEditBox("Add Car Window Quantity Edit").SetText "2" HTMLCheckBox("Name=chkRadio").Click HTMLCheckBox("Name=chkAirCond").Click DealerPrice = HTMLEditBox("Application=IEXPLORE.EXE Name=txtDealerPrice").CaptureText HTMLButton("Add HTMLButton").Click

Now that the contents of the Dealer Price edit field have been captured, they may be processed as required within the script.

125

Exercise 10 Capturing Data


Objective: To verify the dealer price is correctly calulated. Use Capture to capture necessary fields. Output a Usercheck based on the results.

Instructions: STEP 1: Copy script EX09 to script EX10, within the script change the Run AddCarsEvents to Run AddCarsCapture. Copy script AddCarsEvents to AddCarsCapture STEP 2: In the AddCarsCapture script place an End statement prior to the HTMLButton("Add HTMLButton").Click statement and run script EX10. This should place application QADemo Web at the correct place to capture fields from the Add Cars window. STEP 3: Replace the End statement with Capture commands for the following fields: Sale Price, Dealer Discount, Dealer Price. STEP 4: The dealer price should be equal to: SalePrice (SalePrice * Discount / 100) Add a calculation to check this and report the results with an appropriate usercheck.

126

Examples: Capture code and calculation


SalePrice = HTMLEditBox("Add Car Window Cost Edit").CaptureText Discount = HTMLEditBox("Add Car Window DealerDiscount Edit").CaptureText DealerPrice = HTMLEditBox("Application=IEXPLORE.EXE Name=txtDealerPrice").CaptureText TempPrice = SalePrice - (SalePrice * Discount / 100) If TempPrice = DealerPrice Then UserCheck "Dealer Price", True, "Valid Dealer Price: " & DealerPrice Else UserCheck "Dealer Price", False, "INValid Dealer Price: " & DealerPrice _ & "Expected: " & TempPrice End If HTMLButton("Add HTMLButton").Click

127

Chapter 11 Error Handling


When a system error is encountered Testpartner displays a Microsoft Visual Basic error message box of the type below:

While this is fine during development of the script, it is less desirable when executing the script in the final test environment. It requires someone to be present to take action and it stops any further tests running on that machine until that action is taken. It is possible to detect these errors within your script and take whatever action is possible to either recover or, at a minimum, to log the error details and terminate the script to enable another to continue.

128

Defining an Error Handling Subroutine


Error handlers are defined in the function that errors are to be trapped in, e.g. Sub Main. Any subroutine or function can create an error handler; the error handler for the subroutine is called before that of its parent. If a subroutine does not have an error handler the parents error handler will be used. The syntax for defining an error handler is: variable = object.OnError( ErrorFunction ) As TOnError The "object" is Testpartner and is optional and usually left out. "ErrorFunction" is the name of the function that will be called when an error occurs. "Variable" is a reference to an instance of the TestPartner TError object The code within the Main subroutine of the script would thus look similar to the following: Sub Main() Dim oe As TOnError Set oe = OnError("MyErrorFunction") ' normal script code End Sub The Error Function must be defined as a function that returns a tpOnErrorType. The following code shows an error function that would be invoked by the above OnError command. Function MyErrorFunction() As tpOnErrorType ' Code to handle the error here MyErrorFunction = tpResumeNext End Function

129

Error Properties
There are several error properties which can be used to obtain the details of the error. The syntax to obtain error properties is as follows: variable = object.Error.{property} "Variable" is a reference to the Testpartner TError object. "Object" is Testpartner and again is usually ommitted. "Property" is one of the properties of the TError object that describes the nature of the error and where it occurred. Error.SourceFile returns the name of the script the error occurred in. Error.SourceLine returns the numeric line number in the script the error occurred on. Error.Message returns the error message. Error.Function returns the command in error. To output the error details to the script log, the following code could be used: TestLog.Comment "error in script " & Error.SourceFile TestLog.Comment "error on line " & Cstr (Error.SourceLine) TestLog.Comment "error in function " & Error.Function TestLog.Comment "error message " & Error.Message Note. The Cstr function is used to convert the numeric line number to a string.

Exit from an Error Function


While it may not be possible to recover from an error condition and all that can be done is to log the error and terminate, there may be circumstances when the error is recoverable and it is required to continue the script. The enumeration tpOnErrorType (this is the error handling function type) has the following values defined which allow for return from the function. TpRetry TpResumeNext TpNextError retry the failed command Resume at the command after the command causing the error. Call the next error handler in the chain.

Thus the last line of the error handling function might be: MyErrorFunction = tpResumeNext

130

Which will exit back to the command after the one which caused the error.

The Error Handler in a Shared Module


The same error handling routine may be required across many scripts, in this case it would be best to define the error handler in a Shared Module to make it accessible from any script. In this case a change needs to be made to the Set command to ensure the shared module is accessed, the module name as well as the error function name must be specified. Set oe = OnError("MyErrorFunction") Now becomes: Set oe = OnError("SharedRoutine.MyErrorFunction") Note: The error handling routine must be in the projects modules, an error routine in the common project can not be accessed from other projects.

131

Exercise 11 Error Handling


Objective Create a function for reporting fatal errors and stopping the script. Create a function for stopping the application. Update the default script to use the error handler.

Instructions: STEP 1: Open a new Shared Module called ErrorHandling. STEP 2: Create a function called QADemoErrorFunction. STEP 4: Within the Function insert a log comment that a fatal error has occurred and add log comments for all the details available. Add an End statement to terminate execution. STEP 5: Create another function called AppStop. Use a window event to check if the browser exists and record closing the IE Browser in the function if it does. STEP 6: Add a call to AppStop in QADemoErrorFunction before the End. STEP 7: Via the options menu change the default script to always contain code to use QADemoErrorFunction. STEP 8: Copy EX10 script to EX11 and add the code to enable error handling via QADemoErrorFunction. STEP 9: Add a window.attach to EX11 at the end of the script to force an error. Run the script to ensure error handling works. Remove the window.attach from the script.

132

Examples: Error Handling Module Function QADemoErrorFunction() As tpOnErrorType TestLog.Comment "Fatal Error in QADemo Web Application" TestLog.Comment "error in script " & Error.SourceFile TestLog.Comment "error on line " & CStr(Error.SourceLine) TestLog.Comment "error in function " & Error.Function TestLog.Comment "error message " & Error.Message If AppStop() Then TestLog.Comment "Application Terminated" End If End End Function Function AppStop() As Boolean If Wait(3, "IE Explorer Present", tpWaitSeconds) = True Then Window("Microsoft Internet Explorer").Attach Window.MenuSelect "File~Close" AppStop = True Else TestLog.Comment "IE Explorer not present." AppStop = False End If End Function

133

Default Script

Script EX11 Option Explicit '$TPInclude "ClassTimerMod" Sub Main() Dim oe As TOnError Set oe = OnError("ErrorHandling.QADemoErrorFunction") Dim EX05Time, SignonTime, ClearDBTime, ShutdownTime As Double Main script code goes here
TestLog.Comment ("Shutdown Time: " & Minute(ShutdownTime) & " minutes " _

& Second(ShutdownTime) & " seconds.") Window.Attach End Sub

134

135

Chapter 12 User Dialogs and Script Debugging


There are two simple VBA functions available for simple display and input of information from within scripts. These are MsgBox which displays information and allows selection of a button to continue, and InputBox which not only can display information but will also accept input back.

MsgBox
This displays a dialog box containing a message, buttons, and optional icon to the user. The action taken by the user is returned by the function in the form of an integer value. The syntax of the command is as follows: MsgBox (Prompt [, buttons][, title]) Prompt: A required parameter of data type string, this is the message to display. Buttons: An optional parameter of data type numeric, the default value is vbOKOnly (value 0) which displays an OK button. This value can be the sum of values for the buttons displayed, the icon required, and the default button. Button Types Constant vbOkOnly vbOKCancel vbAbortRetryIgnore vbYesNoCancel vbYesNo vbRetryCancel Value 0 1 2 3 4 5 Buttons to Display OK Only OK and Cancel Abort, Retry, and Ignore Yes, No, and Cancel Yes and No Retry and Cancel Icon to Display Critical Message Warning Query Warning Message Information Message Default Button First Button Second Button Third Button Fourth Button

Icon Display Constants Constant Value vbCritical 16 vbQuestion 32 vbExclamation 48 vbInformation 64 Default Button Constants Constant Value vbDefaultButton1 0 vbDefaultButton2 256 vbDefaultButton3 512 vbDefaultButton4 768

136

Return Values Constant Ok Cancel Abort Retry Ignore Yes No

Value 1 2 3 4 5 6 7

Title: An optional title (string) for the message box. Note! Additional helpfile parameters are beyond the scope of this manual. Example: reply = MsgBox("My Prompt", vbAbortRetryIgnore + vbDefaultButton2, "My Title") This outputs the following message box:

The default Retry button will return a value of 4 The following MsgBox: reply = MsgBox("My Prompt", vbExclamation + vbDefaultButton1 + vbYesNo, "My Title") Gives:

The Yes button would return a value of 6.

137

The message box can be useful to display values without having to use the VBA debugging system, and can also be useful for controlling a demonstration of the script as it stops processing until a button is pressed.

InputBox
This function displays a dialog box containing a lable, which prompts the user about the data you expect them to input, a text box for entering the data, an OK button, aCancel button, and optionally a Help button. When the user clicks OK, the function returns the contents of the text box. The syntax of the command is as follows: InputBox (Prompt [,title] [,default] [,xpos] [,ypos]) Prompt: A required string which is the message in the box. Title: An optional string for the titlebar.

Default: An optional string to be displayed in the text box on loading, provides a default return value. Xpos: The optional position measured from the left of the screen. Ypos: The optional position measured from the top of the screen. Examples: reply = InputBox("MyPrompt", "The Title", "Default value")

If default value is not changed and OK is clicked then Default value is returned. If the Cancel button is clicked then nothing is returned. This can be used as a simple method of inputting data and also to display and give the option to change values within a script.

138

Debugging Scripts
The debugging options available through the debug menu enable you to set breakpoints at various commands, step through your script, and examine variables.

A breakpoint may be set by clicking in the gray column next to the line the breakpoint is required to be on. When the script is run it will stop execution on the breakpoint line, contents of a variable can be examined by placing the cursor over the variable.

139

A variable may be added to the watch window by double clicking on it or via the debug menu add watch. Then the variable can be examined as you step through the script with Step Into, Step Over, Step Out, and Run to Cursor commands. A section of script can be skipped by placing the cursor on the line you wish to continue exucution and taking the debug option Set Next Statement. The breakpoints can be toggled on a specific line using the Toggle Breakpoint menu option, and all breakpoints can be removed by the Clear All Breakpoints menu option.

User Forms
It is possible within testpartner to create your own forms. A form provides fields where you can enter additional information or read additional information. Forms can also provide formatted output in ways that a message box cant. Forms can be activated from within your Testpartner script. Within Testpartner to create a form, in the Asset browser right click on UserForm and select New UserForm The resulting display shows a blank userform and a toolbox with the basic controls that are available. 140

The tools in the toolbox from left to right are: Top Row: Select Objects Label TextBox ComboBox ListBox CheckBox RadioButton ToggleButton Bottom Row: Frame CommandButton TabStrip MultiPage Scrollbar SpinButton Image RefEdit

141

We can add controls to the window by clicking on the required control and then Clicking on the required position within the window. The following diagram shows a simple input window with a Heading (using a label), two Labels, two Editboxes and two Buttons.

142

We can give the labels, fields, and buttons meaningful names and contents by invoking the properties window from the view menu:

143

144

By changing the name and the caption we can give our fields sensible names and meaningful display values, we can also change the font type and size used. The size of the display can be adjusted by clicking on the small boxes and dragging the edge of the field to the required size.

145

On the following form the label Names and Captions are now: LabHeading - UserID and Password Window LabUserID - UserID LabPassword - Password The edit field names are TxtUSerID and TxtPassword. The button names and captions are: BtnAdd - ADD BtnClose - CLOSE

146

In order to add code to handle events such as clicking on a button we can get to the event code by double clicking on the button on the form. The image below is from double clicking on the ADD button.

The following image shows code that has been added to obtain and display the userid and password fields when the ADD button is clicked, when the CLOSE button is clicked the window is closed. Note we have now saved the form with the name FormUserPwd.

147

Note, you can always return to the code for the form by selecting Code from the Testpartner View menu while in the form.

148

Activation of a UserForm
In order to display a userform from within a script the form must be included with the standard $TPInclude statement and then the show method is used to display the form and pass control to that form. Control will return to the script when the form is hidden as in the close button code above.

149

Exercise 12 User Dialogs and Script Debugging


Objective: To create a script to input a password for a username. Use debug to check the code is working correctly

Instructions: STEP 1: Create a script (Password) using the InputBox function to request the input of a password for the userid dtl STEP 2: Use the debug options to step through the script.

150

Examples: Script Option Explicit Sub Main() Dim Reply As String Reply = InputBox("Input password for Userid dtl", "Password Input") End Sub Display

Debug Run with a breakpoint and watch window

151

Chapter 13 User Id/Password Encryption


It is often required for security that information such as passwords do not appear in either a script or a test log. It is easy to switch off logging a test so that information is not written out to the log by using the logging property of the playback object.

Switching Logging Off


The command: Playback.Logging = False The command: PlayBack.Logging = True will switch off all script logging. will switch the logging back on.

However, even if we switch off logging then the password will still be contained within the script, and thus easily accessible. One method around this is to encrypt the password and then store it in the registry (or a file) using the UserId as a key value to lookup the password and decrypt it when required.

Encryption and Decryption Routines


Below are two simple functions for Encrypting and Decrypting information. Option Explicit Function Encrypt(Password As String) As String Dim I As Integer Dim ParLen As Long Dim Encoded As String Dim NextChar As String Dim Ansi As Long Dim SaveLogging As Boolean SaveLogging = Playback.Logging Playback.Logging = False Encoded = "" For I = 1 To Len(Password) NextChar = Mid(Password, I, 1) Ansi = Asc(NextChar) Ansi = Ansi - I Encoded = Encoded & Chr(Ansi) Next Encrypt = Encoded Playback.Logging = SaveLogging End Function 152

Function Decrypt(Password As String) As String Dim I As Integer Dim ParLen As Long Dim Decoded As String Dim NextChar As String Dim Ansi As Long Dim SaveLogging As Boolean SaveLogging = Playback.Logging Playback.Logging = False Decoded = "" For I = 1 To Len(Password) NextChar = Mid(Password, I, 1) Ansi = Asc(NextChar) Ansi = Ansi + I Decoded = Decoded & Chr(Ansi) Next Decrypt = Decoded Playback.Logging = SaveLogging End Function With the above two functions stored in Testpartner as a Shared Module the Encrypt and Decrypt functions become available for any script to use. Because we do not want the decryption or encryption process logged, the logging has been turned off at the start of the code. However if logging was already off we do not want to switch it back on by mistake at the end of the code. To handle this, the current logging status is stored in the variable SaveLogging, and then logging is set back to this status at the end of the functions. The following simple code using the above functions should display an encrypted version of pass as o_po and then convert it back to pass. Dim Original As String Dim Encoded As String Dim Decoded As String Original = "pass" Encoded = Encrypt(Original) MsgBox (Encoded) Decoded = Decrypt(Encoded) MsgBox (Decoded)

153

Storing and Retrieving from the Registry


If we wish to store the encrypted passwords in the registry we can use the SaveSetting command to write the information to the registry and then the GetSetting command to retrieve it. The following is a simple example of using these commands: Dim Original As String Dim Encoded As String Dim Decoded As String Original = "pass" Encoded = Encrypt(Original) MsgBox (Encoded) SaveSetting "QADemo", "Passwords", "dtl", Encoded Encoded = "" Encoded = GetSetting("QADemo", "Passwords", "dtl", "") Decoded = Decrypt(Encoded) MsgBox (Decoded) Again the MsgBox displays should show o_po and pass as outputs, but this time the value has been stored in the registry and is being read from the registry. Subsequent executions of this code would not need to store the encrypted password again unless it had changed. The Syntax for these commands is as follows: SaveSetting appname, section, key, setting appname is required and a string value, it should be the application name under which information is to be stored. section is required and a string value, this is the section within appname where the information will be stored. key is required and a string value, it is the key value to be used to retrieve the stored data from the above section. setting is required and a string value, this is the data to store. GetSetting appname, section, key [, default] appname is required and a string value, it should be the same application name under which information was stored.

154

section is required and a string value, this is the section within appname where the information will be looked for. key is required and a string value, it is the key value to be used to retrieve the stored data from the above section. default is a default value to be returned if the requested value is not found. GetSetting returns a string. It is recommended that the reader should also look at commands GetAllSettings and DeleteSetting.

155

Exercise 13 User Id/Password Encryption


Objective: To input encryption and decryption routines. To use the Password script from EX12 to store an encrypted password. To modify the Signon script to use the stored encrypted password.

Instructions: STEP 1: Copy script EX11 to script EX13, within the script change the Run Signon to Run SecureSignon. Copy script Signon to SecureSignon. STEP 2: Implement the encryption and decryption routines from the above chapter as a shared module called security. STEP 3: Modify the Password script from EX12 to encrypt the password and save it in the registry using an Appname of QADemoWeb, a section of Passwords and the userid (dtl) as a key. STEP 4: Hide the code in script Password from the log by disabling the logging. STEP 5: Build a loop handling several userids in script Password. STEP 6: Modify the SecureSignon script to obtain the password from the registry, decode it, and then use this for logging in to QADemo Web. Ensure the password does not appear in the log. STEP 7: Ensure all your code from EX13 is still functioning correctly. Examples Password Script '$TPInclude "security" Option Explicit Sub Main() Dim Reply As String Dim Encoded As String Dim User(4) As String Dim Index As Integer User(0) = "John" User(1) = "Fred" User(2) = "dtl"

156

User(3) = "####" Index = 0 Playback.Logging = False While User(Index) <> "####"


Reply = InputBox("Input password for Userid " & User(Index), "Password Input")

Encoded = Encrypt(Reply) SaveSetting "QADemoWeb", "Passwords", User(Index), Encoded Index = Index + 1 Wend End Sub SecureSignon Script HTMLBrowser("Caption='QADemo - Login'").Attach HTMLEditBox("Signon Window User Id Edit").SetText "dtl" SaveLogging = Playback.Logging Playback.Logging = False Encoded = GetSetting("QADemoWeb", "Passwords", "dtl", "") Decoded = Decrypt(Encoded) HTMLEditBox("Signon Window Password Edit").SetText Decoded Platback.Logging = SaveLogging HTMLRadioButton("Signon Window Paris Radio").Click HTMLButton("OK HTMLButton").Click

157

Chapter 14 File Handling


A full description of the filehandling abilities of VBA is beyond the scope of this manual. However the ability to write and read a simple text file could be useful and is the area of filehandling that we will concentrate on.

Microsoft Scripting Runtime


Before being able to implement the filehandling code below you must first enable the Microsoft Scripting Runtime. This is achieved from the Testpartner Tools Menu and the References option is selected.

158

This displays the References Window where you must ensure that the Microsoft Scripting Runtime is selected.

The FileSystemObject
Once the above option has been selected you can reference the FileSystemObject. This is a very flexible object which provides methods and properties for accessing every folder and file on the host computer. We shall use this object to test for the existence of a file and then to create a TextStream object for file access. However this is only a small part of the objects abilities and the reader is recommended to do further reading. First in our script we must create a new FileSystemObject, this is achieved by the following code: Dim Fsys as New Scripting.FileSystemObject Or simply: Dim Fsys As New FileSystemObject After this when we type the Fsys followed by a period we are presented with a list of the components of the scripting object. The object we are interested in from this list is FileExists as we wish to test if a file exists or not. The code in our script to create the object and test if a file exists or not would look similar to the following: 159

Option Explicit Sub Main() Dim Fsys As New FileSystemObject Dim Filename As String Filename = "C:\Temp\Test.txt" If Fsys.FileExists(Filename) Then MsgBox ("File Exists") Else MsgBox ("File Missing") End If The above code is testing for the existence of a file C:\Temp\Test.txt and displays a message box stating if the file exists or not.

The TextStream Object


If the file does not exist we want to create it, if it does exist we want to open and append to existing information in the file. We have two methods available from the FileSystemObject which can be used to create or open a textstream file, they are CreateTextFile and OpenTextFile. Set FObj = Fsys.CreateTextFile(Filename, True) The above creates a new file, the True parameter says to replace an existing file. Set FObj = Fsys.OpenTextFile(Filename, ForAppending) The above opens a file for appending to existing data. Now we have the FObj object we can use this to write data to the file and when finished to close the file. The method to write a line of data is WriteLine and the method to close the file is Close. Again there are many methods available on this object which the reader should investigate. Our final script to check if the file exists and then write out two lines of data is as follows:

160

Option Explicit Sub Main() Dim FObj As TextStream Dim Fsys As New FileSystemObject Dim Filename As String Filename = "C:\Temp\Test.txt" If Fsys.FileExists(Filename) Then MsgBox ("File Exists") Set FObj = Fsys.OpenTextFile(Filename, ForAppending) Else MsgBox ("File Missing") Set FObj = Fsys.CreateTextFile(Filename, True) End If FObj.WriteLine ("This is Line One") FObj.WriteLine ("This is Line Two") FObj.Close End Sub To open and read the file is also straight forward, we use the OpenTextFile method to open the file for input and the Readline method to read each line. If we add the following code to the end of the code above (before the End Sub) it will read and display the information written to the file. Set FObj = Fsys.OpenTextFile(Filename, ForReading) While FObj.AtEndOfStream = False TLine = FObj.ReadLine MsgBox ("Read: " & TLine) Wend FObj.Close

161

Exercise 14 File Handling


Objective: To Create an output text file. To append to the file details of successes and failures during adding cars to QADemoWeb. Instructions: STEP 1: Copy script EX13 to script EX14, within the script change the Run AddCarsCapture to Run AddCarsFiles. Copy script AddCarsCapture to AddCarsFiles. STEP 2: In script AddCarsFiles add code to test for the existence of output file testlog.txt. Open the file for output if it does not exist and for append if it does. Write a line giving the date and time of the file open (Use the Now function). STEP 3: Everytime a car is added or not output the details to testlog.txt, add details on the dealer price as well. Ensure the file is easily readable. Examples: Code to open the text file Dim Fobj As TextStream Dim Fsys As New FileSystemObject Dim Filename As String Filename = "C:\Temp\Testlog.txt" If Fsys.FileExists(Filename) Then Set Fobj = Fsys.OpenTextFile(Filename, ForAppending) Else Set Fobj = Fsys.CreateTextFile(Filename, True) End If Fobj.WriteLine ("=================") Fobj.WriteLine (Now) Fobj.WriteLine ("=================")

162

Code to add car details to the file.


Fobj.WriteLine ("==============================================================") Fobj.WriteLine ("Car Reference: " & TD.DataItem("Ref") & " Make: " & TD.DataItem("Make"))

. . .
If TempPrice = DealerPrice Then UserCheck "Dealer Price", True, "Valid Dealer Price: " & DealerPrice Fobj.WriteLine (" Valid DealerPrice: " & DealerPrice) Else UserCheck "Dealer Price", False, "INValid Dealer Price: " & DealerPrice _ & "Expected: " & TempPrice Fobj.WriteLine ("INVALID Dealer Price: " & DealerPrice & "Expected: " & TempPrice) End If HTMLButton("Add HTMLButton").Click If Wait(30, "Add Car Reference Field Blank", tpWaitSeconds) = True Then UserCheck "AddCarsEvents", True, "Car Reference " & TD.DataItem("Ref") & "Added to DB" Fobj.WriteLine (" Added to Database") Else UserCheck "AddCarsEvents", False, "Car Reference " & TD.DataItem("Ref") Fobj.WriteLine (" Database write FAILURE!") End If Wend TD.CloseData Fobj.Close

Example Testlog file ========== 7/12/2003 12:01:46 PM ========== =============================================================== Car Reference: car-1889 Make: Ford Taurus Valid DealerPrice: 14000 Added to Database =============================================================== Car Reference: car-996 Make: Plymouth Breeze Valid DealerPrice: 11025 Added to Database =============================================================== Car Reference: car-1997 Make: Chrysler Sebring Valid DealerPrice: 16145.75 Added to Database =============================================================== Car Reference: car-889 Make: Ford Taurus

163

Valid DealerPrice: 14000 Added to Database =============================================================== Car Reference: car-1996 Make: Plymouth Breeze Valid DealerPrice: 11025 Added to Database =============================================================== Car Reference: car-997 Make: Chrysler Sebring Valid DealerPrice: 16145.75 Added to Database

164

Chapter 15 Using SQL


Microsoft ActiveX Data Objects
In order to use SQL within your scripts you must select the Microsoft ActiveX Data Objects option (use the highest library number) from within the Tools->References menu option.

To fully cover SQL and DB access is beyond the scope of this manual, so we shall cover enough to enable a Database to be accessed and its contents checked.

Connection and Record Set Objects


We need to define 2 objects, one is the connection object and the other is the recordset object. Dim Cnn As ADODB.Connection 'stores the connection object Dim RS As ADODB.Recordset 'stores a recordset object We make the connection to an odbc database as follows:

165

Set Cnn = New ADODB.Connection Cnn.ConnectionString = "DSN=qademo;UID=;PWD=;" We can execute an sql statement and store the results into a recordset as follows: MySql = "Select * From CarList Set RS = Cnn.Execute(MySql) We can then examine the results in the record set with the following: Do Until RS.EOF MsgBox RS("Ref") & " " & RS("Make") RS.MoveNext Loop RS.Close It is recommended that the user examines the options available when typing RS. such as BOF, MoveFirst,MoveLast, etc. The QADemo database consists of the following three tables : CarList Ref Make Engine Size Year Door Cost Discount QuantityA QuantityB QuantityC Cond1 Cond2 Cond3 Cond4 Cond5 Cond6 Customers Account Number Name Address Details User Password UserName

166

Exercise 15 Using SQL


Objective: To Check the cars added in previous exercises exist in the QADemo database. To use SQL to access the QADemo database Instructions: STEP 1: Ensure there is an ODBC entry for qademo pointing to the database C:\Program Files\Apache Group\www\qademo\data\qademo.mdb STEP 2: Copy Script EX14 to EX15, at the end of script EX15 add a run statement for script SQLDatabaseCheck. STEP 3: Create a script SQLDatabaseCheck which reads the test data file and ensures that every record added is in the database. Note! A select statement of the form "Select * From CarList Where Ref = Car-889 will only return one record as the reference number is unique. STEP 4: Add a fail usercheck for every car not found and a pass usercheck if they are all found.

167

Examples: SQLDatabaseCheck Script '$TPInclude "ErrorHandler" '$TPInclude "TestDataFunctions" Option Explicit Sub Main() Dim oe As TOnError Set oe = OnError("QADemoErrorFunction") Dim TD As New TestDataFunctions Dim Cnn As ADODB.Connection 'stores the connection object Dim RS As ADODB.Recordset 'stores a recordset object Dim MySql As String Dim ErrorCount As Integer Set Cnn = New ADODB.Connection Cnn.ConnectionString = "DSN=qademo;" Cnn.Open ErrorCount = 0 TD.OpenData ("C:\Temp\cars.csv") While TD.ReadNextDataRecord = True
MySql = "Select * From CarList Where Ref = " & "'" & TD.DataItem("Ref") & "'"

Set RS = Cnn.Execute(MySql) If RS.EOF = True Then ' Reference was not found UserCheck "SQL Database", False, TD.DataItem("Ref") & " Not Found." ErrorCount = ErrorCount + 1 End If Wend If ErrorCount = 0 Then UserCheck "SQL Database", True, "All items found in database" End If TD.CloseData End Sub

168

Chapter 16 Screenshots
While testing it can be useful to take a screenshot, possibly to verify the screen is as expected, or more likely to provide additional information in the event of an error. In this chapter we will assume that we want to take a screenshot after an error has occurred, write that screen image out in a word document allowing for any previous files, and log the name of the word file to our script log. Taking a screenshot can be achieved by recording typing the printscreen key on the keyboard. This will give recorded code similar to the following:

PrintScrn
Window("Microsoft Internet Explorer").Attach Window.Type "{PrintScrn}" Here we were in the Internet Explorer when we recorded the printscreen. You must be sure you can attach to this window whenever you are going to execute this code if you include the attach statement. Normally you will already be attached to a window and the Window.Type {PrintScrn} will be all that is required. It is worth mentioning that because the PrintScn is enclosed in curly brackets it is treated as a special keyboard function and not a string value. Other special keys will record in a similar way, for example: the End key gives {ExtEnd}, Ctrl-C and Ctrl-V give {Ctrl C} and {Ctrl V} respectively. Once we have our Screenshot stored on the computer clipboard, we can record loading an application such as word in which to save this. We add the image to a document by using the Ctrl-V keyboard option to paste the image into the document. Then record saving the document to the required folder on disk, and close everything down as required.

Storing in Files
The above process will work fine once, but we need to modify the filename we save the image in so as not to overwrite any existing files. The following code assumes the output filename has the format ScreenDumpxxxx.doc where the xxxx is a number starting at 0001 and rising to a possible 9999. It uses the FileSystemObject we were introduced to in Chapter 14, and uses the FileExists method of that object to check if a filename already exists. The filename to check for is created by concatenating together 3 169

components, the full path filename up to the 4 digit number, the 4 digit number derived from a For loop, and finally the word .doc extension. As soon as it is found that the file does not exist then we exit the for loop with the Exit For command, and the variable filename contains the full filename to use for saving the captured screen shot. Dim FObj As New FileSystemObject Dim Filename As String Dim Prefix As String Dim Suffix As String Dim Count As Integer Prefix = "C:\Errors\ScreenDump" For Count = 1 To 9999 Step 1 Suffix = Format(Count, "0000") Filename = Prefix & Suffix & ".doc" If FObj.FileExists(Filename) = False Then Exit For End If Next Finally we can log to our script log the name of the file containing the screenshot using the standard TestLog.Comment command. TestLog.Comment ("Screenshot in file: " & Filename)

170

Exercise 16 Screenshots
Objective: To write a function which takes a screen dump and outputs it to a word file. To add the function to the standard error handling function. Instructions: STEP 1: Manually do a print screen, then in a script record loading Microsoft word, paste the screen dump into the word document, and save the screen dump as a file (C:\Temp\ScreenDump0001). STEP 2: Delete the saved file, at the beginning of the script use the Currently Active Window code in the appendix to attach to the currently active window and add a Window.Type "{PrintScrn}". Ensure the script works. STEP 3: Add the code to calculate the next filename to use (see chapter above) and insert into script. Run script several times to ensure it works. STEP 4: Add a run statement for this script to the beginning of the error handling function "QADemoErrorFunction" in shared module "ErrorHandling" developed in chapter 11. This will cause a screendump to be taken on every error.

171

Examples ScreenDump Script '$TPInclude "ErrorHandler" Private Declare Function GetForegroundWindow Lib "user32" () As Long Option Explicit Sub Main() Dim oe As TOnError 'Set oe = OnError("QADemoErrorFunction") Dim FObj As New FileSystemObject Dim Filename As String Dim Prefix As String Dim Suffix As String Dim Count As Integer
Dim lHwnd As Long Dim WindowName As String lHwnd = GetForegroundWindow WindowName = Window("hwnd=" & lHwnd).AttachName

Window(WindowName).Attach Window.Type "{PrintScrn}" '----------------------'Load Microsoft Word Window("Window").Attach Button("Caption=Start").Click Window.PopupMenuSelect "Programs~Microsoft Word" Window("Microsoft Word - Document").Attach Window.Type "{Ctrl V}" 'Paste in the screen Window("Microsoft Word - Document").Attach Window.MenuSelect "File~Save As" Window("Save As Window").Attach '------------------172 'Take the screen dump

'Calculate the next filename to use Prefix = "C:\Temp\ScreenDump" For Count = 1 To 9999 Step 1 Suffix = Format(Count, "0000") Filename = Prefix & Suffix & ".doc" If FObj.FileExists(Filename) = False Then Exit For End If Next '------------------'Save as new filename and shutdown word GUIObject("ClassName=RichEdit20W Caption=''").Attach GUIObject.Type Filename Window("Save As Window").Attach Window.BitmapSelect "Save As2" 'Note! following object needs changing for diff. window titles Window("Microsoft Word - ScreenDump Window").Attach Window.MenuSelect "File~Exit" TestLog.Comment ("Screenshot in file: " & Filename) End Sub

173

Appendix A - Some Extra Notes


Working with Lists and Combo Boxes
It is often useful to be able to obtain a count of entries in Lists and Comboboxes, this is easily achieved with the "count" function as shown in the following examples. cnt = HTMLComboBox("Name=state").Count cnt = HTMLListBox("Name=lstNew").Count cnt = ListBox("Label=&New").Count Retrieving a specific item from a listbox can be achieved as follows: Item = ListBox("Label=&New").GetItem(5) ' retrieves the 5th item from the list Selecting a specific list item by its content is achieved as follows: ListBox("Label=&New").Select "Inquire"

ScrollBars
Scrollbars can vary according to the application they are contained in. For example in MSWord Scrollbars are objects, however in Notepad they are part of the editbox. This difference limits what you can do with Scrollbars in Notepad. With a Scrollbar as an object the following functions are available: To obtain the maximum value that can be scrolled to (ie end of document) Height = ScrollBar("Index=1").Height To scroll to the start of a document: Position = 0 ScrollBar("Index=1").SetPosition Position To scroll to the very end of a document: Position = Height ScrollBar("Index=1").SetPosition Position 174

Working with scroll bars in Notepad. Notepad must be opened. The scroll bar is part of the edit box and the size of the edit box determines the bottom position of the scrollbar. You can not use the "height" function but must use the "linecount" function to determine how far you can scroll in Notepad. EditBox("Index=1").Attach Count = EditBox("Index=1").LineCount Scroll to the bottom of the document: EditBox("Index=1").Attach EditBox.Scroll Count, tpScrollVertical Scroll to the top of the document: EditBox("Index=1").Attach EditBox.Scroll 0, tpScrollVertical

Checkboxes
While the standard checkbox click command is fine for setting a checkbox: CheckBox("Caption=Rad&io").Click It does not allow you to clear an existing check from the checkbox. It is worth considering using the setcheck method on a checkbox as this can both set a checkbox and clear it: If TD.DataItem("Radio") = "on" Then CheckBox("Caption=Rad&io").SetCheck (True) set the checkbox Else CheckBox("Caption=Rad&io").SetCheck (False) clear the checkbox End If

175

Loading an application
While recording the loading of a program through the menu system is fine, there are times when an application may not be available through the menus, or it is required to load the program faster. This can be achieved by a combination of the chdir command, which sets the working directory, and the shell command which loads the program:
ChDir "C:\Program Files\Compuware\Demos" Ret = Shell("C:\Program Files\Compuware\Demos\QADemo.exe", vbNormalFocus)

The Currently Active Window


It is possible to get the name of the currently active window with the following code:
Private Declare Function GetForegroundWindow Lib "user32" () As Long Sub Main() Dim lHwnd As Long Dim WindowName As String lHwnd = GetForegroundWindow WindowName = Window("hwnd=" & lHwnd).AttachName MsgBox WindowName

End Sub

176

Search Functions
It is often required to find if a value exists in a window where we do not have individual fields that can be captured and examined (Chapter 10). If the functions below are included as a module then the window can be captured and the functions used to check if the required value is in that window. Textselect (Chapter 7) can be used to select the entry if required. Sub Main() Dim CapturedWindow As String Dim LineNo As Integer Window("Display Details Window").Attach CapturedWindow = Window("Display Details Window").CaptureText LineNo = FnFindLine(CapturedWindow, "Ref 100111") If LineNo <> 0 Then use textselect to select the entry in the window Window("Display Details Window").TextSelect ("Ref 100111") Else MsgBox Value not found End If .. . .. End Sub '*********************************************************************** Search the string ToBeSearched for the string SearchFor and return how many are found '*********************************************************************** Function FnStringSearch(ToBeSearched As String, SearchFor As String) As Integer Dim StartPos As Integer Dim FoundCount As Integer Dim Pos As Integer StartPos = 1 FoundCount = 0 While StartPos + Len(SearchFor) - 1 <= Len(ToBeSearched) Pos = 0 Pos = InStr(StartPos, ToBeSearched, SearchFor) If Pos <> 0 Then StartPos = Pos + Len(SearchFor) FoundCount = FoundCount + 1 177

Else StartPos = Len(ToBeSearched) + 1 ' force exit of while End If Wend FnStringSearch = FoundCount End Function '*********************************************************************** 'This function processes the Inputstring to detect which line the first 'occurrence of Searchvalue is found on. 1st Line is 1, a 0 means not found '*********************************************************************** Function FnFindLine(ByVal InputString As String, SearchValue As String) As Integer Dim LineArray() As String Dim crlf As String Dim Count As Integer Dim LineLen As Integer Dim StringLength As Integer Dim LineNumber As Integer Dim I As Integer LineNumber = 0 crlf = Chr(13) & Chr(10) 'Only continue if the SearchValue exists in the InputString, return 0 otherwise '-------------------------------------------------------------------------------------If FnStringSearch(InputString, SearchValue) > 0 Then 'Obtain the string length and the line length '------------------------------------------StringLength = Len(InputString) LineLen = InStr(1, InputString, crlf) + 1 'Create an array of lines from the string splitting them on a crlf '-----------------------------------------------------------------LineArray = Split(InputString, crlf) LineNumber = UBound(LineArray) 'Now search line by line to see which line has the required string in it '----------------------------------------------------------------------For I = 0 To LineNumber 'Note 1st LineNumber was 0 as array starts at 0 Count = FnStringSearch(LineArray(I), SearchValue) If Count > 0 Then

178

Exit For End If Next FnFindLine = I + 1 ' This is the line number starting at 1 Else FnFindLine = 0 ' Value was not found anywhere End If End Function

179

Das könnte Ihnen auch gefallen