Custom Search

Saturday, October 6, 2007

QTP Coding

Overview

1.1       About this document

This document defines the prescribed coding conventions and practices for Test Automation using Mercury Quick Test Professional. Since QTP uses VBScript as the scripting language,   most of the conventions are derived from Microsoft's conventions defined for VBScript.

The document provides a set of conventions and best practices for Mercury QTP, which can be used as a reference by the individual project teams to define their own standards by tailoring the recommendations.

This document is organized into the following sections:

·         Structure Conventions: standards to adhere to while writing and laying out(indenting) code.

·         Documentation Conventions: standards to adhere to while documenting code.

·         Naming Conventions: standards to adhere to while naming identifiers (Scripts, function names, variable names, etc.)

·         Recommendations: suggestions and rules-of-thumb that help avoid some common automation pitfalls.

 

1.2      Target Audience

This document is addressed to the following set of audience

§         Testers/developers involved in automation script development using Mercury QTP

§         Testers/developers involved in code reviews of Mercury QTP automation scripts.

 

1.3       Definitions

A convention is one of the following:

·         A standard (S) is a mandatory constraint on the content or format of something ( e.g., code, documentation).  You must follow standards unless you obtain a waiver from the Process Team and you document the deviation from the standard.

·         A guideline (G) is an optional constraint on the content or format of something ( e.g., code, documentation).  You should follow guidelines in most cases.  You must document any deviation from the guideline.

·         A recommendation (R) offers advice.   It is less constraining than either a standard or guideline.  You may follow or ignore recommendations as appropriate.   You need not document any deviations from recommendations.

 

Code Conventions

Code Organization

·         Keep modules to a manageable size.   Each module should be less than about 1000 lines, and contain a set of procedures that are related to each other.  If a module is becoming larger than 1000 lines, consider splitting it based on some functional criteria.

Rationale:   Small, cohesive modules are more manageable and easier to understand.  They also reduce sharing conflicts in version control tools.

·     Keep procedures to a manageable size.   Each procedure should be concise enough that its entire purpose can be easily expressed and understood.  One rule of thumb is that the well-commented procedure should fit on a printed page.   A more relevant rule when editing the code is that it fit on one screen in the development environment.

     Rationale:  Small procedures are easier to understand and verify.

Exception:  A single control structure (for example, a Select structure) may be unavoidably longer than the recommended procedure length.   In this case, the control structure should be placed in its own procedure, separate from other code, so as not to obscure the function of the code around it.

·     All script level variables should be defined at the beginning of the script.

 

Indentation

·         Use the indentation by setting 'Tab spacing' property to 4 characters (In QTP – Tools>Editor options).

Rationale:   Indentation improves readability.  Using the standard tab-stop indentation improves maintainability, allowing the indent level of blocks of code to be easily changed.

·         Use four spaces for each indent level.   The default tab spacing in VB is four spaces, and this should be maintained. 

Rationale:   Four spaces are enough to make the indentation level obvious, without taking up too much horizontal space.

·         While breaking up long lines, a spill-over indentation of 4 spaces should be used.

Characters per Line

Avoid lines longer than 80 characters. This rule also applies for documentation lines.

Rationale: Longer lines are more difficult to read.  Also, many terminals and tools do not handle longer lines well.

Use Line Continuation

To break your strings and/or code apart on multiple lines using the underscore character '_'.

 

"Break up long procedure declarations on to multiple lines with each parameter aligned".

Rationale:   This makes the code much easier to read and makes it less likely that maintenance will introduce new bugs.

 

Example :

Function CollectStats(sFileName, _
       iStartLine As Long, _
       iEndLine As Long) _

Blank Lines

Put a blank line between logical sections of a procedure.

Rationale:   This improves readability.

Example :

Sub ProcessData()

 

CheckPrecondition

 

DoFoo

DoFam

 

CheckPostcondition

 

End Sub

Comment:   If the method is long or violates other standards, it should be factored based on the logical sections described above.

Control Flow Statements

If...Then...Else Statements

The if-else class of statements should have the following form:

 

If – End If Statement

 

If (condition) Then

 

        Statements

 

End If       

 

 

If – else nested statements

If condition Then

 

    If condition Then

 

        statements

 

    Else

 

        statements

 

    End If

 

Else

 

    If condition Then

 

        statements

 

    Else

 

        statements

 

    End If

 

End If

 

If – elseif nested statements

 

If condition Then

 

    statements

 

ElseIf condition Then

 

    statements

 

Else

 

    statements

 

End If

While...WEnd Statements

while condition statement

 

while condition

 

   statements

 

Wend

 

 

 

 

 

 

 

 

 

 

 

 

Do... Loop Statements

             1> Do Until... Loop

Do Until condition

                         

    Statements

 

Loop 

 

2>Do...Loop, Do While...Loop

Do

 

    statements

 

    Do While condition                 

 

        statements

 

    Loop

 

Loop   Until condition

For...Next Statements

A For statement should have the following form

1>

for <initialization condition> To <update> statement

2>

for <initialization; condition> To <update>

 

    statements

 

    for <initialization; condition> To <update>

 

        statements

 

    Next          

 

Next

ForEach...Next Statement

A ForEach statement should have the following form

 

ForEach <element> in <block>

 

    statements

 

Next

Select Statement

A Select statement should have the following form

1>

Select Case <test expression>

 

    Case <expression> Statement       

      

    Case <expression> Statement

 

    Case Else Statement

 

End Select      

2>           

Select Case <test expression>

 

    Case <expression>

 

        Statements

 

    Case <expression>

 

        Statements

 

    Case Else  

 

        Statements

 

End Select      

 

With Statement

A With statement should have the following form

With Object

    Statements

End With

Documentation Conventions

The following Visual Basic comment standards provide a consistent approach to documenting the code.

Comment Formatting

Begin comments with '* (an apostrophe, an asterisk, and a space).  All VB comments start with an apostrophe and end with a line break.  This convention adds an asterisk and space before the actual comment text.

Rationale:   When viewing VB code, the apostrophe alone does distinguish the comment well from the code. The asterisk and space improves legibility by setting the comments off more clearly.

File Comments

Write a comment block at the top of each script/File.   The comment block will include the name of the module, a description of its purpose, its authors, and its revision history.  It should also contain version and copyright information, if appropriate.   Each entry in the revision history will include the date that the change was made, the author who made the change.

     Following is the example of the header:

'********************************************************************************************************

'* Copyright ©  2004, <team name>, Hyderabad.
'* This is UNPUBLISHED PROPRIETARY SOURCE CODE of <team name>;                                  '* The contents of this file may not be disclosed to third parties copied or duplicated in any     '* form, in whole or in part, without the prior written permission of <team name>.
'* ALL RIGHTS RESERVED.
'* Author:                               : Xxxxxxx xxx.
'* Project:                                     :  <Project Name>.
'* Filename:                       :  <File/Script/Action Name>
'* Created on:                              :  <Date dd/mm/yyyy>
'* File path:                        :  <Relative Path from the root of automation
'* Abstract                          : <purpose/content of the file/script/action>                                                                         '* Last modified date         :            -  
'* Last modified by            :            -
'********************************************************************************************************

Procedure Comments

Begin each procedure with a comment block.  The comment block shall precede the declaration accordingly, and contain a description of the procedure, including the reason why it is needed.   Following that should be a list of the pre-conditions and post-conditions necessary for its operation<optional>, a description of its parameters and return value, and possible errors which may occur.

Rationale: Well-commented procedures make the code easier to understand.

Example: 

'* Run the spell checker on the textbox.  This prevents
'* spelling errors from being stored and displayed to the
'* customers.

'* Pre conditions: Textbox has been filled
'* Post conditions: The data in the textbox may change if
'*   spelling corrections have occurred

'* Parameters:
'*   txtComments – Textbox  containing free-form text
'* Return Value:
'*   Boolean indicating whether spelling errors were found.

Function CheckSpelling ( txtComments )

1.4  Declaration Comments

Describe the abstraction of all declared constants, types, and variables, the meanings of which are not obvious from the name.   This includes both module- and procedure-level declarations.  Also, describe any constraints of the variables.

Rationale : This will make the code easier to understand and maintain.

Example :

Dim intPrevPos As Long '* Previous cursor position
                                    '* (0..MAXPOS)

1.5  General Comments

·  Do not comment obvious code . 

If the code is not obvious, then first see if you can rewrite the code so that the use of comments will be unnecessary.

Rationale : This will make the code easier to maintain.

Bad Example :

Dim lngConnectionCount       '* number of connections

·         Where practical, line up trailing comments .

Rationale : This will make the comments easier to see, compare, and maintain.

Example :

If Not DataReady() Then       '* precondition fails

Error 30005, "Data not available"

Else                                                   '* normal case

ProcessData

End If

·  Use proper spellings and punctuations in comments.

Rationale: Poorly written comments are distracting and can obscure the intended meaning.

 

2         Naming Conventions

2.1  Variable and Parameter Names

Variable and parameter names should be meaningful noun or noun phrases, without spaces, with the first letter lowercase and the first letter of any subsequent words capitalized.   The first few letters of the variable name define the type of the variable.  The remainder of the name describes the role the variable plays.

2.1.1       Constant Names

The names of constants should be meaningful noun or noun phrases with all letters  capitalized and underscore "_" between each word.

Rationale:   Consistency with standard Visual Basic and Windows API naming conventions.  This convention emphasizes and differentiates constants from variables.

Example : MAXIMUM_NUMBER_OF_FILES

2.1.2        Atomic Types

For atomic types, the first letter of the name defines the type, as follows:

Variable Subtype

Prefix

Example

Boolean use of variant variable

bln

blnEditBoxExists

Byte use of variant variable

byt

bytDownloadedData

Date or Time use of variant variable

dtm

dtmCreatedDate

Double use of variant variable

dbl

dblPiValue

Error use of variant variable

err

errLogin

Integer use of variant variable

int

intDuration

Long use of variant variable

lng

lngPopulation

Object use of variant variable

obj

objArtClass

Single use of variant variable

sng

sngGradePointAverage

String use of variant variable

str

strLastName

Variant

var

varGrade

 

Rationale: Consistency with standard Visual Basic and Windows API naming conventions.  This allows easy identification of the type and role of a variable, without adding a lot of naming overhead for frequently used types.

2.1.3        Object Name Conventions

For objects and complex types, and three-letter prefix defines the type, as follows:

Prefix

Type

Example

txt

TextBox

txtFirstName

chk

CheckBox

chkPrimaryAddress

tar

TextArea

tarComments

but

Button

butSave

rgp

RadioGroup

rgpSex

lnk

Link

lnkGetClient

Lst

Dropdown List

lstEmployeeStatus

bro

Browser

broAOSApp

ele

WebElement

elePolicyNumber

pge

Page

pgeAlert

Frm

Form

frmCustInput

lst

ListBox

lstServiceTypes

cmd

Command Button

cmdCancel

cbo

ComboBox

cboCategory

sel

Select (drop down)

selCategory

pic

PictureBox

picLogo

opt

Option Button

optGenderFemale

tmr

Timer

tmrElapsed

lbl

Label

lblCopyright

tbr

Toolbar

tbrEditing

ctl

Control (if type is not known)

ctlSortableList

col

Collection

colFormFields

obj

Object (if type is not known)

objParent

var

Variant (if type is not known)

varNextField

img

Image

imgIcon

Fra

Frame

fraLanguage

Many other types are possible which are not on this list, including user-defined types and objects. For these types, and appropriate three-letter or four-letter prefix convention should be established and documented for the project.

(Note that the "frm" prefix should be used only for a variable in the code which holds a form reference, and not the VB class and file which defines the form.)

Rationale: Consistency with standard Visual Basic and Windows API naming conventions.  Allows easy identification of the type and role of a variable.

2.1.4        Global Variable Names

Names for global variables should follow the above conventions, but with a "g_" prefix before the name.   Likewise, private module-level variables should have a "m_" before the name.

Rationale: This eases identification of global and module-level variables.  While this convention is somewhat cumbersome, it appropriately discourages use of global variables and module-level variables.

Example:

Public g_strCurrentUser As String

Private m_aintTroubleCodes As Integer

2.1.5       Variable Scope Prefixes

As script size grows, so does the value of being able to quickly differentiate the scope of the variables. A one-letter scope prefix preceding the type prefix, separated by an underscore, provides this, without unduly increasing the size of variable names.

Scope

Prefix

Where Variable Is Declared

Example

Procedure-level

None

Event, Function, or Sub procedure.

intDuration

Script-level

s

HEAD section of an HTML page, outside any procedure.

s_blnEditBoxExists

Global-level

g

-

g_strValue

 

2.2  Array Names

Array names should begin with a lower case "a", followed by the prefix which describes the type of the array members, as described above, and followed finally be the descriptive name of the variable.

Note that Variants must often be used to hold arrays when they are passed as return values from functions.   In this case, the Variant should be named according to the array naming convention.

Rationale:   This identifies the variable as an array, and indicates its contents as well.

Example :

Dim astrUserNames(10)

Dim asngVertices()

Dim avarWords
avarWords = Split(strLine, strTab)

2.3  Procedures

A procedure is a grouping of code statements that can be called by an associated name to accomplish a specific task or purpose in a program.

There are 2 types of procedures, sub-routines and functions. A sub-routine is a block of code that can be called from anywhere in the script to accomplish a specific task and it does not return any value. A function is the same as a sub-routine but does return a value.

The syntax for both will be the same.    

Syntax

[SOURCE]+"_"+[PerformedAction]+[Parameterlist]

[SOURCE] is an abbreviation of the library/script name it is implemented at.

[PerformedAction] consists of two words, an action (verb) and an object the action is

performed against.

[Parameterlist] is a sequence of placeholders the function is fed with.

[ReturnValue] is the value returned by the function       

 

Examples:

If EditBox.vbs is the name of the library which implements a set of functions to access the EditBox Control, the naming convention followed by the functions/subroutines in the library is

EB_SetTextValue (strEditBoxObjectName, strValue)

EB_VerifyTextValue (strEditBoxObjectName, strValue)

2.4  Scripts

A QTP Test script is a folder containing the script file with the VBScript code and the corresponding initialization or configuration files required by QTP to load and execute the test. A test script can have a set of actions and collection of datasheets associated with actions. The artifacts which require the naming convention are the test script, action and the data sheets

2.4.1        Test Script

Syntax:

[FEATURE] + "_" + [FUNCTION] + "_" + {optional}

[FEATURE] is an abbreviation of the feature/module[in caps] it is intended to test

[FUNCTION] is the name of the function/sub module[in caps] it is intended to test

{optional} means that the remaining characters preceded by an underscore will be optional and left to each person to define a sensible name which clearly identifies each of the test scripts.

Example:

  The scripts testing a mailing application would use  the following naming conventions[the        naming convention depends on the way the test cases are classified and automated]

MAIL_INBOX_OPENMAIL

MAIL_INBOX_REPLYMAIL

MAIL_COMPOSE_SENDMAIL

2.4.2        Actions

If a script has only one action the name of the action should be the same as the script. If the script has multiple actions, the naming convention for the action should be similar to that of script, [FEATURE] + "_" + [FUNCTION] + "_" + {optional}

2.4.3        Datasheets

The datasheets associated with the script inherit the name from the action unless explicitly created and imported at run time. The naming convention defined below is for the external sheets which are saved in Excel sheets or tab separated txt files and imported by the script at runtime.

The external datasheets can be classified into 3 categories based on its usage

Input Files – The data stored in these files is used exclusively as input for the test case

Output Files - The data stored in these files is saved by the test script/action for further                   operations. ex. Output of an operation saved to file for verification.

Input/Output Files - The data stored in these files is used as input for the test case and some                           of the fields are updated at runtime

Temp Files – The datasheets created and used temporarily to save and use the data at run                           time.

The datasheets should be placed under appropriate directory based on usage.

Example:

       A input data sheet should be placed under

         <root>/datasheets/output/<name of script using datasheet>/<filename>

       Similarly, an output datasheet should be placed under

         <root>/datasheets/output/<name of script using datasheet>/<filename>

2.5  Libraries

Common used functions are placed in libraries.

Syntax:

       [Companyname]+[ShortName]+"vbsl"

Examples:

Companyname UltraGrid.vbs

Companyname WinEditor.vbs

CompanynameEditbox.vbs

 

 

3         Recommendations

This document provides suggestions and guidelines for improving the performance and reliability of your application.

3.1  Declarations

The following conventions help you build good abstractions that maximize cohesion:

·         Use narrow scoping.   Use private variables and constants whenever feasible.  Local (procedure-level) variables are preferred, followed by module-level, with global as a last resort.

Rationale: Increases cohesion.

·         Declare scope explicitly.   Use Private and Public, instead of Dim, for variables declared outside of procedures.

Rationale: VB has different defaults for each type of code module (form, class, etc.).  Explicitly declaring the scope of variables reduces confusion.

·         Declare variables and constants at the beginning of their applicable scoping construct (module or procedure).   VBScript allows you to declare variables anywhere within a module or procedure, but they should be placed at the top.

Rationale: This makes declarations easy to view, and avoids cluttering up the flow of executable code.  Usually the rationale for putting the declarations in the middle of the executable code is that it declares variables near the point where they are used.   But this is only important if procedures are allowed to grow beyond a manageable size.  If a block of code is independent enough to require its own variables, it belongs in a separate procedure.

·         Use narrow typing for objects.   Don't use an Object type when the true type of the object is known.  For example, if a variable contains a reference to a TextBox, the variable should be declared As TextBox, not As Object or As Control

Rationale: Narrow typing makes the true purpose of the variable more obvious.  It also allows VB to catch type mismatch errors at compile time, and execute more quickly at run time through early binding.

3.2   Explicitly destroy all objects and close all connections

Destroying objects and closing connections ensures resources are returned to the system. Objects and connections should be closed and destroyed in the opposite order in which they were created. Wait to create objects and open connections until immediately before they're needed. Likewise, destroy objects and close connections immediately after you're through with them.

Example:

Set objFso = Server.CreateObject("Scripting.FileSystemObject")

set f = objFSO.OpenTextFile…

f.Close

set f = Nothing

set objRS = Nothing

set objConn = Nothing

set objFso = Nothing

3.3   Use Option Explicit

Use Option Explicit.  Option Explicit should be included at the beginning of each module to enforce explicit declarations for all variables.   In the VB environment, the option to "Require Variable Declaration" should be set.  This tells VB to include Option Explicit in all new modules.

Rationale: When variables can be instantiated on the fly, typographical errors in variable names are not caught by the compiler and can cause run-time errors.

3.4   Use Local Variables in Subroutines and Functions

Local variables are those declared within subroutines and functions. Within a function or subroutine, local variable access is faster than global variable access. Use of local variables also tends to make code cleaner, so use them when you can.

3.5   Avoid Redimensioning Arrays

Try to avoid Redim arrays. As far as performance is concerned, if you have a machine that is constrained by physical memory size, it's much better to set the initial dimension of the array to its worst-case scenario—or to set the dimension to its optimal case and Redim as necessary. This does not mean that you should just go out and allocate a couple of megabytes of memory if you know you aren't going to need it.

   The code below shows you gratuitous use of Dim and Redim.

Dim MyArray ()

Redim MyArray (2)

MyArray (0) = "hello"

MyArray (1) = "good-bye"

MyArray (2) = "farewell"

...

'Some other code where you end up needing more space happens, then ...

Redim Preserve MyArray (5)

MyArray (3) = "more stuff"

MyArray (4) = "even more stuff"

MyArray (5) = "yet more stuff"

It is far better to simply Dim the array to the correct size initially (in this case, that's 5), than Redim the array to make it larger. You may waste a little memory (if you don't end up using all of the elements), but the gain will be speed.

3.6   Use a Shared Object Repository

Always use a shared object repository for easier maintenance. Recommended practice is to record all the controls of the application at one go and save the object repository.

Click the Test / Settings menu item to select the shared object repository for the script.

         

3.7   Save Global/Environment variables in a file

Always define the environment/global variables used across different scripts/actions in an ".ini" file and load the file into the test script instead of directly adding them to the script settings. It is easy to maintain the variables defined in a file and can be reused across different scripts by loading the file instead of redefining the variables.

           

3.8   Avoid Usage of Hard Coded Paths

Always use relative paths in specifying the location of a file or action included in the test script. This makes the test scripts portable. The items which are prone to be hard coded are call to external action, Associated Library files, shared Object repository, Environment variables file.

Example:

Assume the test scripts are present in the following location D:\Temp\TestScripts folder and TestScripts is parent folder under which all the automation scripts are saved.

Then, All the paths should be mentioned relative to TestScripts folder. The path D:\Temp\TestScripts should be added in the Tools/Options window, Folders Tab for QTP to identify the parent folder.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

No comments: