Sei sulla pagina 1di 15

QuickTest Professional Scripting Standards

THE BASIC FORMAT OF THE SCRIPT:


All new scripts/components/actions will have the following template automatically created.
Adjust as needed.

'########################################################################################
##
'#Test/Action Name:
'#Author :
'#Creation Date:
'#Copied From:
'#Modified By:
'#Modification Date:
'#Action Objective :
'#Verifications:
'########################################################################################
Option Explicit

'####Dim Generic Variables


Dim i 'acts as storage for loop counter value

'####Initialize Variables####
i=1

'####TRIM VARIABLES

'### Start of Script #################

'Reset SAP app to expected initial condition – Remove if not using for SAP
SAPGuiSession("Session").Reset

'###Validation Point#########

1) All QTP machines will have a copy of the ActionTemplate.mst (shown above)
placed in the dat folder of the QTP folder to foster the formatting standards
stated for all newly created Actions/Components following.

2) All scripts/actions/functions will provide an objective statement detailing


what is to be accomplished and how with any special instructions for data
included in header. This information will be copied to the test case
description in Quality Center for use in reporting.

3) Load only those add-ins required to run the test to avoid function library
conflicts.

4) All existing actions will have a header like template shown above.

5) Use distinct and descriptive variables names – no generic variables.


THE CODE SECTION OF SCRIPT:

6) Always reset the initial status of application at the beginning of each script.
For SAP, simply resetting the application takes care of this but for other
applications it is important to ensure that all scripts have an expected initial
and end condition that is the same. For example, starting and ending a script
at the Home Page of a web site.

7) Use i and j as a commonly known loop counter variables.

8) Use x as a place holder for retrieved values in the code if not using
descriptive variable.

9) Use the REPORTEVENT method of the Reporter object to output


information into results.

10) All Reporter.ReportEvent messages should be clear and fully explanatory, no


generic messages can be used.

11) Use white space where appropriate, such as between if statements, when
navigating to new SAP screen, etc.
12) Indent within flow control (looping) and conditional statements (if/then and
Select Case) one tab.

13) Object names in QTP script should be descriptive. (If process of finding name
is too cumbersome/ time consuming please make note of it in QA Audit)

14) Use “’##VALIDATION POINT” comment for checkpoints.

15) Add comments in code when appropriate, especially to describe situations


where your logic determines flow - especially when BP is not obvious or
performing calculations / data manipulations, etc.

16) No commented hardcode values.

17) No commented code, except for actual comments.


18) Any values used in pick lists should be trimmed. If data picked from list is
insignificant in terms of performance of scenario use index (ie #0 instead of
“Select” for Stage of Development field shown below to ensure first item is
selected. This allows script to continue regardless of whether same value is
first position or not.

19) If possible, import data sheets directly to the local sheet where used - use
index position of table to direct it to correct sheet. (This is for new scripts.)

20) Use section/frame names if possible to describe parameter - otherwise use


underscore and a number for parameters that have same name. (Example:
Main_CustomerNumber and Department_CustomerNumber versus
CustomerNumber_1 and CustomerNumber_2) (Not Applied to existing reusables)

21) Use underscore and “Act” for verification parameter names describing
information retrieved/returned from application at runtime. (Example:
ReturnedRecords_Act) (Not Applied to existing reusables – previously used _Val”)

22) Use underscore and “Exp” for verification parameter names describing
information retrieved/returned from application to set baseline or expected
value. (Example: ReturnedRecords_Exp) (Not Applied to existing reusables)

23) Use underscore and “Out” for output parameters names. (Example:
VendorNumber_Out) (Not Applied to existing reusables)

For Reusable Actions


24) Validation parameters and Output parameters should be at the end of the
datasheet for reusable. (Not Applied to existing reusables)

For Reusable Actions

25) Standard checkpoints should only be used when verifying texts and other
generic validations. Dynamic validations more often require custom
checkpoints but can also use standard checkpoints if able to put values in
datatable.

26) Avoid using hardcoded values if possible. Hardcoded values should only be
used for “any old data” pieces that do not affect outcome or business process
flow.

27) Use functions when appropriate to:


 Easily identify the tasks performed by the script
 Prevent needless duplication of code
 Make your code portable and reusable
 Allow your code to be encapsulated in code libraries to provide one point of
maintenance.
 Business processes should not be made into functions – but reusable actions

28) Functions should be maintained by a specific person. (To be determined).

29) All functions should be stored in the ‘BPT Resources’ folder under the
‘Libraries’ folder in Quality Center.
30) All shared object repositories should be stored in the ‘BPT Resources’ folder
under the ‘Object Repositories’ folder in Quality Center.

31) No hard coded wait statements unless impossible to sync otherwise.


Use the WaitProperty statement or create your own sync loop on visual cue. For
example, if the visual cue is text on a screen then the following code can be better
employed (as a function) rather than a wait statement. (This is a generic
function that can be used for any window in any application.)
Public Function WaitForTextInWindow(WindowName,MyDesiredText,MaxTimeWillingToWait)
Dim TheHandle: Dim CurText : Dim i: Dim MyCtr
TheHandle = Window(WindowName).GetROProperty("hwnd")
For i = 1 To MaxTimeWillingToWait
CurText = TextUtil.GetText(TheHandle)
If InStr(CurText,MyDesiredText) > 0 And MyCtr <= MaxTimeWilingToWait Then
WaitForTextInWindow = "found it"
MyCtr = MaxTimeWillingToWait 'get out of loop
else
wait(1)
MyCtr = MyCtr + 1
End If
Next
If WaitForTextInWindow <> "found it" Then
WaitForTextInWindow = "failed"
End If
End Function

32) Only declare needed input and output parameters. (Extraneous parameters
can confuse in case of maintenance needs. – Often a result of copying
components and making changes but forgetting to change options)

Optional:
33) Use the “Generate ‘With’ statements” option found in the Options General
tab to ensure coding is grouped by current focused window.

34) Any scripts that are audited should be transformed to use the ‘With’ by
selecting EditAdvancedApply With menu item.

QuickTest Professional Sample Script


'######################################################################
'#Test/Action Name: File Tab
'#Author : Jane Smith
'#Creation Date: APRIL 28, 2007
'#Copied From: \Subject\Core\Driver Script… (For Reusable Actions only)
'#Modified By: Dave Mark
'#Modification Date: APRIL 29, 2007
'#'#Action Objective : This test is designed to automate the Search functionality of
'# the File tab in the StrIDE environment.
'#Verifications: Verifies the number of records returned matches expectations.
'######################################################################
Option Explicit

'#### DIM GENERIC VARIABLES


Dim rc ' Return Code (rc) of a function
Dim ExtFile

'#### INITALIZE VARIABLES


FieldSkip = "<SKIP>"

'####TRIM VARIABLES
StageOfDevelopment = Trim (StageOfDevelopment)

'#### START OF SCRIPT


'Reset SAP app to expected initial condition
SAPGuiSession("Session").Reset

Script ….

'##VALIDATION POINT
x =JavaWindow("Search").JavaStaticText("Your Search Returned").GetROProperty("label")
rc = CompareValue(RecordsReturned_Val,TempArray(1),"Number of Records Returned")

Best Practices

Object Repository
• Object Repositories should be created prior to creation of scripts.
– Rename objects logical name to reflect user interface
• Makes scripts more readable and more easily maintained
• Enforces uniformity of reference
– Map custom objects prior to scripting
• Allows custom objects that behave like standard objects to be
treated as standard giving greater context sensitivity and
increases reliability
– Use shared object repositories in all Apps but SAP – otherwise
business process fosters local repository method as one-time use.
– Create one Shared Object Repository for application functionality
• For instance – Creating sales order – Materials Management, etc
• currently all reusables have own local repository –
should share one
• Do not overlap objects by storing same in multiple
repositories
• * Set as Default when working in same area – client setting in
Action Properties –Associated Repositories tab option.

Reusable Actions
• You can use principles of Modular Scripting or Business Process Testing
(BPT) even if just using QTP
• Reusable actions imply generic code
• Use reusable actions to mimic common Business Actions
• Code should be generic to allow for variations of business process
• Data entry / Validations should be data driven
• Use custom checkpoints whenever possible to provide greater flexibility
• Use Function Libraries for commonly used low-level activity
• ie: – manipulate external files
• Perform calculations
• Work with custom objects
• Associate function libraries with scripts and set as default
• Create external function libraries and organize by task type
• ie: Calculation, String Manipulation, File manipulation etc.

One point of maintenance is key


• Avoid creation of local functions unless being reused only within script.
• Think at an object level and not business process level – to foster generic code.
• Data in spreadsheet should determine where and what is being done
• Reduce duplication of code within reusable actions
• Data drive tests whenever possible
• Avoid hard coded data regardless – parameterize everything!
• Maintain external spreadsheets – define shared folder location with folder
structure to mirror QC.
• Use ImportSheet command – reference data table parameters – do not
reassign to variables.
• Create a column called TestName for looping purposes if needed
• Reference Environment(“TestName”) as follows:
RowCount = DataTable.LocalSheet.GetRowCount
For i= 1 to RowCount
If DataTable(“TestName”,dtLocalSheet) = Environment(“TestName”)
Do this stuff…..
End If
Next

Initial Conditions - QTP

• Use the “Record on any open Browser” option for Web Apps
– You control the initial condition of browser in script
– Use the SAPGuiSession(“Session”).Reset command for SAP
• Use the “Record on any open Application” for Desktop Apps
– You control the initial condition of AUT in script
• Run Options – make sure the following are checked:
– Allow other Mercury products to run tests and components
– Save still image captures to results: select For errors and warnings
– Normal run mode with 100 milliseconds delay
– Automatically generate “With” statements after recording to establish
focus and increase readability of script. (General option)
– Ignore Quality Center (Web option)
• Test/Component Settings
– Make sure proper associated add-ins loaded – only those needed.
– Run on all rows if global datatable has multiple rows
– Establish realistic timeout value – currently 20

• Action Settings
– Each new action will automatically be formatted to fit current format
requirements – be sure to provide needed information where
appropriate.
– ActionTemplate.mst will be stored locally at:
• C:\Program Files\Mercury Interactive\QuickTest Professional\dat

Reusable\Flexible Code
Always think in terms of “where else can I use this” or “how can I make this as
generic (usable) as possible”. See the example above for the synchronization
function. Although it was created for a use in a specific application, the code is
written so that any windows application could use it without changing any code.
This train of thought will make your reusable code and your scripting efforts
more efficient not just for yourself but the entire team. This does not merely
apply to functions but components and actions as well. You need to get out of
the mode of thinking “how do I get this one business process piece to work?”, to
thinking “how do I make this work and make it so that it is most easily reused
and maintained?”.

• Descriptive Programming
– Use when the properties of an object are dynamic and its properties
are unknown for each iteration of the script
– Use descriptive programming in Web apps for dynamically created
objects like text links and web elements where expectations can be
defined or “actuals” easily retrieved.
– Use when same object is duplicated dynamically based on data input
and varies widely.

Recovery Scenarios
• Recovery Scenarios can be used for unexpected situations / errors / common
pop ups
• Use recovery scenarios when the pop up messages are predictable unless
messages are BP status related.
• Weigh Positive vs. Negative testing needs
• Use conditional logic for predictable errors and put logic in the script and not
in recovery scenario.
• Checkpoints should only be in script – never in RS.
• *Makes script execution more reliable and maintenance more efficient
providing one point of maintenance when/if things change.

Efficient coding example:


The following is an example of utilizing code to most efficiently perform a
verification. At the same time, this code allows for the user to verify both a
positive and negative scenario, without having to change verification statements.
The idea is that flexibility is built in to the code based on what you know may or
may not be tested for the application.

For example, the VNet home page is comprised of various links to other pages.
Some of these links are to dynamic materials (ie news stories), others are to static
web pages that will always be there (ie Mission Statement, Committee) . The
ones that will always be there can be considered “always expected” so they will
pretty much be “positive” tests. Those that won’t always be there can be either
positive or negative depending on when the testing takes place.

If testType = “Pos” then a=0:b=1 else a=1:b=0 End If ‘where testType tells if pos or neg test
If Exp_Condition = Act_Condition Then
Reporter.ReportEvent a, “Conditional Check”,”The condition specified above was met.”
Else
Reporter. ReportEvent b, “Conditional Check”,”The condition specified above was not met.”
End If

BPT Specific Information (Left in for possible shift back to BPT Usage)

Parameters vs. Local Sheet Usage


 Parameters are to be used for data values when the data in question needs to
be controlled by the end user. During requirements gathering period
analysts should ask questions regarding need/desire to be able to change
specific values.
o Does this data piece have an affect on business process flow?
o Is this data replenished /can it be used up?
o Is this data retrievable from database in way that can make script
dynamic and work into flow of BP seamlessly?
o Does data exist in reference table that may affect other data or be
affected by other data in such a way that it may used for other
dependent scenarios?

 Answers to the previous above questions will affect how data is


parameterized. If the answers to questions are ‘no’, then parameterize the
data in the local sheet of the Action or the Component. If ‘yes’ then
parameterize the data in component parameters table to allow end user to
manipulate as needed. Provide a default value so that users do not have to
provide data for each piece.
 If data is retrievable through dynamic SQL and is based on conditional
criteria, that is determined by objective statement, gather info from subject
matter experts to create SQL statement and code action/component to
retrieve data and store in local data sheet to be used for input.
 Importing data from an external sheet should be imported directly to the
localsheet desired.
 Avoid duplication of storage of data by referencing the datatable or
parameter where data was originally defined unless the need for
manipulation within the script would cause issues with the use of the value
later in the script.

Functions and Function Libraries


'** Please add all new function names and objectives to this list as they are added to the library and in order in which they
appear.
'****************************************************************************************************************************************
' User Defined Database Functions
' -------------------------
'
' Available Functions:
' * DataGrab - grab data from the defined database and write it to the local sheet
' *
' Version: QTP9.2 February 2008
'
'*****************************************************************************************************************************************
'######################################################################################
'Function DataGrab(MyDSN,MySQL)
'Objective: This function will grab data from the defined database and write it to the
' local sheet of the action from which the function is called - it automatically
' creates columns in the local sheet with the names of the database columns retrieved
' and adds the number of rows needed to completely write out the data to the sheet.
'Parameters: MyDSN - name of the system DSN that has connection string settings needed
' MySQL - the SQL statement to run to retrieve data from the database
'
'Created By; Unknown
'Date Created:
'Modifications:
'######################################################################################
'Function to grab the values from database to runtime data sheet
Public Function DataGrab(MyDSN,MySQL)
Dim TheDB 'Declare the database object name alias
Set TheDB = CreateObject("ADODB.Connection") 'Create connection object to allow dynamic
connection to database
TheDB.ConnectionString = "DSN="&MyDSN 'Reference System DSN to establish connection
TheDB.Open 'Make connection
Set MyResults = TheDB.Execute(MySQL) 'Store record set (returned info) in object called
MyResults
'MsgBox MyResults.Fields.Count 'Find out how many columns exist with data
'MsgBox MyResults.Fields(0).Name 'Find out what the name of the first column is
For a = 1 To MyResults.Fields.Count 'Establish loop begin and end conditions - start at
row one and end at last row
ParamName=DataTable.LocalSheet.AddParameter(MyResults.Fields(a-1).Name, "").Name
i=1
'Establish intial for my data entry loop
Do Until MyResults.EOF 'Keep looping while there is still data to be read
DataTable.LocalSheet.SetCurrentRow (i) 'Set focus on row i in data table localsheet
DataTable(MyResults.Fields(a-1).Name,dtLocalSheet)=MyResults(ParamName)
'write out the value to the datatable for the current record
MyResults.MoveNext 'Advance to next record in recordset
i=i+1 'Increment counter to push datatable focus to the next row
Loop
MyResults.MoveFirst 'Go back to the first record in recordset for next column (if any)
Next
MyResults.Close 'Clean up by closing database connection and removing objects from memory
TheDB.Close
Set MyResults = Nothing
Set TheDB = Nothing
End Function

Standards for functions and function libraries:

1. All user defined function libraries will have a header that indicates the
functions contained within and a description of each for easy perusal.
2. Only “Add-In” libraries created by QTP for use in registering the add-
in functions and the template library file will remain directly in the
Libraries Attachment area. All others will find a place in the functional
structure shown above.

3. Functions will be stored in logically named libraries that indicate the


type of functions contained. For example, functions whose purpose is
to manipulate strings should be contained in a library called
“String_Funcs”, functions that perform mathematical operations
should reside in a library called “Calculation_Funcs”, etc.

4. If the function is relevant only to a specific application and can have no


reasonable use across applications should reside in libraries with the
system abbreviation under the folder indicating the type of function
within. (For example see the VSEC library under the
ENV_Initialize_Funcs folder).

5. All procedures should be developed with the intention that they will
be reused by other scripts. Avoid private Subs in cases where the Sub
is to be called only once within a script. If it is needed multiple times
then it is acceptable to declare/define a Sub at the beginning of the
script. However, it is suggested that you analyze the procedure to see
if/how it could be written to be more generic and thus gain more
efficiency for script creation.

6. All function procedures will have a header similar to the one shown
above in the example function. The header is to include:
a. The function name with the parameters declared.
b. An objective statement to define what the function does
c. A list of the parameters and a description of what they mean so other users
will know how to use the function.
d. The author name
e. Date Created
f. Modification information – be specific as to what you changed and why.

7. Use indentation to show scope of function as well as scope of


conditional statements, whether they are loops, ifs, select case
statements or whatever to increase readability.

8. Provide comments to explain your logic – remember, functions are


basically algorithms that you have thought out to accomplish a goal.
The way you think may be different than the next person so you need
to walk them through your logic to provide understanding in case they
are to be modified by someone else.

9. Business processes should not be wrapped up as a function. If you


want to make a business process reusable – use an action to do so,
unless you need the business process to perform a recovery scenario.

10. Register your function within the project where you created it
whenever possible. This will allow other users to find your functions
using the Step Generator. (If you do not register the function to a specific test object,
the function is automatically defined as a global function. Global functions can be called by
selecting the Functions category in the Step Generator (for function libraries), or the
Operation item in the Keyword View. A list of global functions can be viewed alphabetically
in the Operation box when the Functions category is selected in the Step Generator (for
function libraries), in the Operation list when the Operation item is selected from the Item
list in the Keyword View.)

11. Functions should not contain statements that pass/fail the step, however they
should provide information in the form of an output variable value that can be
used within the script/action to perform a check. We can not always assume
that a function failure is a bad thing, especially in terms of negative testing
unless the test type is taken into consideration when developing the function
and it is made powerful enough to handle pos/neg logic. (see the section on
efficient coding)

12. Recognize that a function is a procedure. There are two kinds of procedures –
Functions and Subs. If your procedure does not return a value then it is to be
declared as a Sub – otherwise update your Function to send a return value
indicating success or failure.

Potrebbero piacerti anche