Posts Tagged ‘QTP 9’

QuickTest Pro (9.0 or 8.2) method: WebRadioGroup.SelectByText

Tuesday, March 21st, 2006

We've had to solve this problem quite a bit, so Will finally turned it into an object method.

Here's the problem:

Milk

Butter

Cheese

You want to be able to say "Select the 'Butter' radio button", but the enterprising and oh-so-efficient programmer has made it so that each option has a value that corresponds to some GUID (e.g. "AFED-0839-02E8A5-0923CDB"), and "Option A" is nowhere to be found anywhere in the object's properties.

The method below allows you to send the text you wish to select, and the radio group will know exactly which button to select.

Select a Radio Button based on the adjacent descriptive text
- The WebRadioGroup to use
- The text to look for
- optional: The sWhere statement for getAdjacentText. Default is afterEnd
- optional: The Index number of the matched button to select. 0 selects first match, 1 selects second. Default is 0

Visual Basic:
  1. Public Function WebRadioGroupSelectByText ( ByRef oRadGroup, sSelectText, _
  2.                                                               sWhereOpt, sIndexOpt )
  3.     If isNull(sWhereOpt) Then
  4.         sWhereOpt = "afterEnd"
  5.     End If
  6.  
  7.     If isNull(sIndexOpt) Then
  8.         sIndexOpt = 0
  9.     End If
  10.  
  11.     sMatches = Array()
  12.  
  13.     Set oParent = oRadGroup.GetTOProperty("parent")
  14.     radName = oRadGroup.GetROProperty("name")
  15.     Set oRadioButtons = oParent.Object.GetElementsByName( radName )
  16.  
  17.     For each oElement in oRadioButtons
  18.         sName = oElement.getAdjacentText("afterEnd")
  19.         If sSelectText = sName Then
  20.             ArrayPush sMatches, oElement.Value
  21.         End If
  22.     Next
  23.  
  24.     If Ubound(sMatches) <0 Then
  25.         ' TODO: report error...item doesn't exist in list.
  26.         Exit Function
  27.     End If
  28.  
  29.     If Ubound(sMatches) <sIndexOpt Then
  30.         sIndexOpt = Ubound(sMatches)
  31.         ' TODO: report warning...index doesn't exist.  selecting last match
  32.     End If
  33.  
  34.     sSelectValue = sMatches(sIndexOpt)
  35.     oRadGroup.Select sSelectValue
  36.    
  37. End Function
  38. RegisterUserFunc "WebRadioGroup", "SelectByText", "WebRadioGroupSelectByText"

Now, to select the radio button I want, I just to this:

Visual Basic:
  1. Browser("B").Page("P").WebRadioGroup("All Options").SelectByText "Option B"

Note that this performs an exact string match. The next step is to create our WebRadioGroup.SmartSelect function, which would be much more flexible, and would allow for partial matches of either adjascent text or the traditional button values. It would also allow for pattern matching via regular expressions. We'll post that one later.

Named Optional Arguments in VBScript

Thursday, March 16th, 2006
QuickTest was my introduction to VBScript. I think and dream in Perl, but I am coming around to a point where I can enjoy coding in VBScript. One of my biggest VBScript annoyances early on was the inability to define optional arguments for my functions.As I said, I think in Perl, so I set about trying to find a solution similar to how I pass arguments to subs in Perl. In Perl, I like to name my arguments, so I pass an array of arguments that the sub collects into a hash as named values. The syntax looks something like this.

PERL:
  1. printsentence(
  2.     'Subject'   => 'The quick brown fox',
  3.     'Predicate' => 'jumps over the lazy dog.'
  4. );
  5.  
  6. sub printsentence {
  7.     my %args = @_;
  8.     print "$args{'Subject'} $args{'Predicate'}";
  9. }

I found an article on 4guysfromrolla.com about using optional arguments in VBScript. It suggests passing an array of arguments to the function. This is a good first step, but I don't like having to remember which value is which in the array. I still wanted my named arguments. Obviously I couldn't use a hash for this, so I used VBScript's nearest data type: a dictionary object. Once I have my parameters in a dictionary object, I can call them by name using syntax like oOptions("optionname"). The question was how to easily get all my options in a dictionary object.

I came up with a function I call DictBuild (insert platypus-related humor here). It takes an array and turns it into a dictionary object. The first value in the array is a dictionary element, the second value is that element's value, third - element, fourth - value...and so on. Basically, all even numbered values are dictionary elements and the odd value after each element name is its value.

This allows me to easily build a dictionary object with all my parameters.

Visual Basic:
  1. printsentence ARRAY( _
  2.     "Subject",     "The quick brown fox", _
  3.     "Predicate",   "jumps over the lazy dog." _
  4. )
  5.  
  6. Public Function printsentence(aOptions)
  7.     Set oOptions = BuildDict(aOptions)
  8.     MsgBox oOptions("Subject") & " " & oOptions("Predicate")
  9. End Function

Now this is finally becoming something I can work with, but what about defaults for these parameters? This is where my next function comes in: GetOpts. GetOpts takes two arrays as arguments and returns a dictionary object. The first array is the default values for the function. The second array is the custom options array that was passed to the function. GetOpts starts by building a dictionary object from the defaults array. Then it overwrites the default values with the custom options array if they exist. I also wrote some discipline for myself into GetOpts. If a option isn't listed in the defaults, it won't make it into the final dictionary.

So, now my function looks like this:

Visual Basic:
  1. printsentence ARRAY( _
  2.     "Subject",    "The quick brown fox", _
  3.     "Predicate""jumps over the lazy dog" _
  4. )
  5.  
  6. Public Function printsentence(aOptions)
  7.     Set oOptions = GetOpts( ARRAY( _
  8.         "Subject",     "Coke", _
  9.         "Predicate",   "is it", _
  10.         "Punctuation", "!" _
  11.     ), aOptions)
  12.  
  13.     MsgBox oOptions("Subject") & " " & oOptions("Predicate") & _
  14.         oOptions("Punctuation")
  15. End Function

I think that about does it for my method of using named optional arguments in VBScript functions. I should note that I only use this for optional arguments, I put the variable names directly in the function signature for required values. So one of my real function delcarations looks like

Visual Basic:
  1. Public Function WebCheckBoxSelectByText ( ByRef oCheckBox, sSelectText, aOptions )

The code for BuildDict and GetOpts is here:

Visual Basic:
  1. Public Function GetOpts(ByRef aDefaults, ByRef aCustom)
  2.     Set oDefaults = DictBuild(aDefaults)
  3.     Set oCustom = DictBuild(aCustom)
  4.     For Each vKey in oDefaults
  5.         If oCustom.Exists(vKey) Then
  6.             oDefaults.Item(vKey) = oCustom.Item(vKey)
  7.         End If
  8.     Next
  9.  
  10.     Set GetOpts = oDefaults
  11. End Function

Visual Basic:
  1. Public Function DictBuild(ByRef aArray)
  2.     bWord = True
  3.     Dim oDict
  4.     Set oDict = CreateObject("Scripting.Dictionary")
  5.     Dim sWord, sDef
  6.     If isArray(aArray) Then
  7.         For Each sString in aArray
  8.             If bWord Then
  9.                 sWord = sString
  10.                 bWord = False
  11.             Else
  12.                 sDef = sString
  13.                 oDict.Add sWord, sDef
  14.                 bWord = True
  15.                 sWord = NULL
  16.                 sDef = NULL
  17.             End If
  18.         Next
  19.     End If
  20.     set DictBuild = oDict
  21. End Function

Technorati Tags: , , ,

QuickTest 9 Coming Soon!

Wednesday, March 15th, 2006

The feature set for QuickTest 9 Beta is impressive, and some of it speaks to our wish list. Will & I were both a part of the beta program, and we're preparing a comprehensive review of how well the new features stack up (against their list as well as ours), as well as some new issues that came up during testing. The non-disclosure agreement we signed prevents us from saying anything about it right now, but we'll be full of information as soon as it goes GA.