preload

GP/QTP Automation: Creating Dexterity Macro XML template

Posted by Albert Gareev on Dec 07, 2009 | Categories: Great PlainsSource code

All related posts: Reference Page – GP/QTP Automation 

Dexterity Macro Limitation 

One of the major limitations identified in Dexterity Macro System is totally hard-coded data with no functionalities to read them from any external source. Running scripts that always look for exactly the same account number or check balance on always the same date would provide a little value for functional testing. While we can not change or add to functionality of Dexterity Macro, we can change macro file itself.

Solution 

Since Dexterity Macros are required as a workaround for the cross-dictionary scripting issue, they are supposed to be executed in the context of the main test flow driven by testing script (VBScript in QTP). Thus, controller script may dynamically generate files from a template.

Requirements

A template for Dexterity Macro should have a structured recognition-friendly format, should be easily handled manually, provide parameterization instructions, and be expandable for any additional future functionalities.
If data for a parameterized step are not provided (empty string) the according step is not generated. That allows building flexible data entry script that skips not required GUI controls (they will retain the default value).
Using XML format in this case fulfills all the requirements.


Sample QTP script

Used resources:

Service Functions – XML (QTP, VBScript)

Using built-in and system dialogs in QTP

Service Script


' Input: Dexterity Macro file
'Output: XML template
'----------------------------------
'To open a dialog , for the user to select an xml file
sRootPath = "<em>- define your root path here -</em>"

Set objDialog = CreateObject( "UserAccounts.CommonDialog" )
objDialog.Filter = "Dexterity Macro Files|*.mac"
objDialog.InitialDir = sRootPath & "Test Logic\"
objDialog.FilterIndex = 1
intRC = objDialog.ShowOpen
sFilename = objDialog.FileName

'extract macro file name
Set regEx = New RegExp
regEx.Pattern = "[^\\]{1,}\.mac"
regEx.IgnoreCase = True
regEx.Global = True
Set Matches = regEx.Execute(sFilename)
For Each Match in Matches
sDestinationFileName = Match.Value
Next
Set regEx = Nothing
Set Matches = Nothing

' Building the destination path for the xml file with the same name as the mac file

strlen = Len(sDestinationFileName)
sDestinationFileName = Left(sDestinationFileName,strlen-4)
sDestinationPath = sRootPath & "<em>- define your subfolders here -</em>\" & sDestinationFileName &".xml"

'Create new XML File
Set objXMLTemplate = XMLUtil.CreateXML("Template")
Set objRoot = objXMLTemplate.GetRootElement
objRoot.AddAttribute "type", "DexMacro"

'Open Macro text file
'...not checking whether it exists

Set FSO = CreateObject("Scripting.FileSystemObject")
Set objMacFile = FSO.OpenTextFile(sFilename, 1)

'insert pre-defined commands
Set objLine = CreateChildElementByName(objRoot, "Line", "")
objLine.AddAttribute "type", "code"
objLine.AddAttribute "data-driven", "Yes" ' by default
objLine.AddAttribute "text", "Logging file %GP.Macro.Log.File"

Set objDataNode = CreateChildElementByName(objLine, "Data", "GP.Macro.Log.File")
objDataNode.AddAttribute "name", "GP.Macro.Log.File"

'Main loop - generating the template
intLineCount = 1

Do While TRUE
'File is empty?
boolRC = objMacFile.AtEndOfStream
If boolRC Then
Exit Do
End If

'Get text line
sLine = objMacFile.ReadLine()
intLineCount = intLineCount + 1
'Comment or code ?
If Trim(sLine) = "" Then
sLine = "#--------------------------"
End If

If (Left(LTrim(sLine), 1) = "#") Then
Set objLine = CreateChildElementByName(objRoot, "Line", "")
objLine.AddAttribute "type", "comment"
objLine.AddAttribute "text", sLine
Else
Set objLine = CreateChildElementByName(objRoot, "Line", "")
objLine.AddAttribute "type", "code"
objLine.AddAttribute "data-driven", "No" ' by default
objLine.AddAttribute "text", sLine
End If
Loop

objRoot.AddAttribute "linecount", CStr(intLineCount)
objXMLTemplate.SaveFile sDestinationPath 

Parameterization

Open generated XML file using available editor, for example, Microsoft XML Notepad.

Manually replace any character sequence representing parameterizable value with a unique (in the context of current line) identifier. Identifier should be preceded by “%” character. Manually create “Data” child nodes to map each identifier to a variable or cell name.

In the examples below parameterizable lines are highlighted.

Sample Dexterity Macro


ActivateWindow dictionary 'SmartList'  form 'Account_Lookup' window 'Account_Lookup'
  MoveTo field 'PB_Advanced_Search'
  ClickHit field 'PB_Advanced_Search'

NewActiveWin dictionary 'SmartList'  form 'ASI_Advanced_Search' window 'ASI_Explorer_Criteria'
ActivateWindow dictionary 'SmartList'  form 'ASI_Advanced_Search' window 'ASI_Explorer_Criteria'
  MoveTo field 'ASI_Search_Field'[1]
  TypeTo field 'ASI_Search_Field'[1] , 'Account Number'

  MoveTo field 'ASI_Search_Type'[1]
  ClickHit field 'ASI_Search_Type'[1] item 2  # 'is equal to'

  MoveTo field 'ASI_Start_Account_Number':'Account_Segment_Pool1'[1]
  TypeTo field 'ASI_Start_Account_Number':'Account_Segment_Pool1'[1] , 111

  MoveTo field 'ASI_Start_Account_Number':'Account_Segment_Pool2'[1]
  TypeTo field 'ASI_Start_Account_Number':'Account_Segment_Pool2'[1] , 1111

  MoveTo field 'OK Button K'
  ClickHit field 'OK Button K'

Generated XML Template


<?xml version="1.0" encoding="utf-8"?>
<Template>
<Options type="DexMacro" linecount="35" wrap="'" />
<Line type="code" data-driven="Yes" text="Logging file %GP.Macro.Log.File">
<Data name="GP.Macro.Log.File">GP.Macro.Log.File</Data>
</Line>
<Line type="comment" text="#--------------------------"></Line>
<Line type="code" data-driven="No" text="ActivateWindow dictionary 'SmartList' form 'Account_Lookup' window 'Account_Lookup' "></Line>
<Line type="code" data-driven="No" text=" MoveTo field 'PB_Advanced_Search' "></Line>
<Line type="code" data-driven="No" text=" ClickHit field 'PB_Advanced_Search' "></Line>
<Line type="comment" text="#--------------------------"></Line>
<Line type="code" data-driven="No" text="NewActiveWin dictionary 'SmartList' form 'ASI_Advanced_Search' window 'ASI_Explorer_Criteria' "></Line>
<Line type="code" data-driven="No" text="ActivateWindow dictionary 'SmartList' form 'ASI_Advanced_Search' window 'ASI_Explorer_Criteria'"></Line>
<Line type="code" data-driven="No" text=" MoveTo field 'ASI_Search_Field'[1] "></Line>
<Line type="code" data-driven="No" text=" TypeTo field 'ASI_Search_Field'[1] , 'Account Number'"></Line>
<Line type="comment" text="#--------------------------"></Line>
<Line type="code" data-driven="No" text=" MoveTo field 'ASI_Search_Type'[1] "></Line>
<Line type="code" data-driven="No" text=" ClickHit field 'ASI_Search_Type'[1] item 2 # 'is equal to' "></Line>
<Line type="comment" text="#--------------------------"></Line>
<Line type="code" data-driven="Yes" text=" MoveTo field 'ASI_Start_Account_Number':'Account_Segment_Pool1'[1] ">
<Data name="account_segment1">account_segment1</Data>
</Line>
<Line type="code" data-driven="Yes" text=" TypeTo field 'ASI_Start_Account_Number':'Account_Segment_Pool1'[1] , %account_segment1">
<Data name="account_segment1">account_segment1</Data>
</Line>
<Line type="comment" text="#--------------------------"></Line>
<Line type="code" data-driven="Yes" text=" MoveTo field 'ASI_Start_Account_Number':'Account_Segment_Pool2'[1] ">
<Data name="account_segment2">account_segment2</Data>
</Line>
<Line type="code" data-driven="Yes" text=" TypeTo field 'ASI_Start_Account_Number':'Account_Segment_Pool2'[1] , %account_segment2">
<Data name="account_segment2">account_segment2</Data>
</Line>
<Line type="comment" text="#--------------------------"></Line>
<Line type="code" data-driven="No" text=" MoveTo field 'OK Button K' "></Line>
<Line type="code" data-driven="No" text=" ClickHit field 'OK Button K' "></Line>


  • One response to "GP/QTP Automation: Creating Dexterity Macro XML template"

  • Brian
    2nd March 2010 at 23:20

    Hi Albert,
    Your automation approach is totally different from the “common practices” promoted everywhere. Where did you learn it?
    Can you give us more posts about automation methodology you use?

    Brian

    [ Albert’s reply.
    Well, expanding the headline of my blog, it is an engineering and scientific approach, end-user oriented and situational feedback driven. I use what I learnt before, and I keep reading, learning, and thinking a lot.
    I’m not stuck with a single methodology but I’ll definitely post more about what I use. ]

Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported
This work by Albert Gareev is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported.