
FAQ
What are the best ways to deal with Active-X subobjects?
Detail
ActiveX collection objects are controls that are
comprised of sub-objects. Examples of collection objects include
treeview which is a collection of nodes, toolbar, a collection
of tool icons and statusbar, a collection of statictext fields.
These collection objects pose challenges for test engineers because the
properties and methods of the contained objects can not be directly
accessed from 4Test. For example, exposed methods might be available on
the treeview to select an item, but specific information about a selected
node may only be available on the contained object itself. That
information is often important to thoroughly verify application behavior.
To call the properties and methods of the contained object, it is
necessary to use special access methods found in the 4Test CompoundControl
class.
The CompoundControl class is provided in a file
called oleclass.inc in the directory where SilkTest is installed. The
class contains two sets of function prototypes. The first set includes _GetCollectionProp,
_SetCollectionProp and _CallCollectionMethod. These prototypes allow
access to methods and properties of the container object. The prototype
for _GetCollectionProp is displayed below:
obj ANYTYPE _GetCollectionProp
(STRING sCollProp, STRING sPropName)
_GetCollectionProp takes two arguments. The first,
sCollProp, is the name of the Collection. The second, sPropName, is the
name of the property to get. You might use this method to get the “Count”
property of a collection to determine the number of contained objects,
e.g. the number of tool icons on a toolbar or the number of columns in a
table. A call to this method might be written as follows:
INTEGER iCount
iCount =
this._GetCollectionProp (“Columns”, “Count”)
The second set of prototypes including _GetItemProp,
_SetItemProp and _CallItemMethod allow access to the properties and
methods of the contained objects. The prototype for _GetItemProp is
displayed below:
obj ANYTYPE _GetItemProp
(STRING sCollProp, INT nIndex, STRING sKey, STRING sPropName)
_GetItemProp takes four arguments. The first
parameter sCollProp is the name of the Collection or Interface.
Collections can be found in the property section of the class definition
for the container object. Collections are usually of type PINTERFACE,
which is a pointer to an interface or collection. If you are not sure how
to obtain a class definition, see the SilkTest documentation for
“recording classes”. An example of a collection property definition is
displayed below:
property PINTERFACE ChildNodes alias "$ChildNodes"
The ChildNodes interface provides access to the
contained objects. To get a listing and description of available
properties and methods, you will need to either consult the documentation
for the object or use an Object Browser such as the one within the Visual
Basic development environment.
The next two parameters, nIndex and sKey, provide two
options for specifying the item in the collection. The first option,
nIndex, is the ordinal value of the item in the collection, e.g. the 4th
item. sKey is the name of the item, e.g. the string associated with a node
in a treeview. If the string, sKey, is empty (""), the numeric value,
nIndex, is used. The last parameter, sPropName, is the name of the
property to get.
Typically calls to _GetItemProp will be wrapped in a
higher level method to provide easy access to a specific property. For
example, a method that gets the tool tip associated with a tool in a
toolbar or a node in a treeview might be written as follows:
[-] STRING
GetToolTipText (LISTITEM iListItem)
[-] if TypeOf (iListItem)
== STRING
[ ]
return (this._GetItemProp ("ChildNodes", 0,iListItem,"ToolTipText"))
[-] else
[ ] return (this._GetItemProp ("ChildNodes",
iListItem,"","ToolTipText"))
To call GetToolTipText, the user is required to
provide only the contained item as either a string or index. The method
then returns the value of the property ToolTipText from the ChildNodes
interface.
So far our discussion has been limited to properties.
It is also possible to call methods on a contained object in a similar
manner. To access methods on a contained object, the CompoundClass
prototype _CallItemMethod is used:
obj ANYTYPE _CallItemMethod
(STRING sCollProp, INT nIndex, STRING sKey, STRING sMethName,
varargs lArgs)
_CallItemMethod is similar to _GetItemProp. The first
three parameters are the same. The forth parameter, sMethoName, is the
name of the method to call. The last parameter is a list of the arguments
to pass to that method. As with properties the user needs to consult
documentation to determine the names of the methods and the number and
types of parameters to pass. In the following example, _CallItemMethod is
used to get the state of a tool button in a toolbar:
-
[-]
BOOLEAN GetToolState (LISTITEM iListItem)
-
[-] if TypeOf (iListItem) == STRING
-
[ ] return (this._ CallItemMethod ("ChildNodes",
0,iListItem,"GetState",{}))
-
[-] else
-
[ ] return (this._ CallItemMethod ("ChildNodes",
iListItem,""," GetState",{}))
To call GetToolState, the user is required to provide
only the contained item as either a string or index. The method then
returns a Boolean value which indicates whether the tool is enabled.
Before you can start using the access methods in the
4Test class CompoundClass, you must modify your class definition to
inherit from it. If the class definition of your object inherits from
Control as many ActiveX objects do, you can simply change the inherited
class from Control to CompoundControl as follows;
If your class is defined like this:
winclass
StatusBar20WndClass : Control
change its definition like this:
winclass StatusBar20WndClass :
CompoundControl
If your ActiveX class already derives from a 4Test
class other than Control, it may not be possible to inherit from
CompoundControl as previously described. Changing the derived class in
this manner would result in loss of inherited class-specific properties
and methods. Instead, simply copy the method prototypes from CompoundClass
into your class. Usage of the access methods will not be affected in any
way.
The ability to access properties and methods from
sub-objects will often enable verification of application behavior that
would otherwise be possible only with bitmaps. Using the sub-object
methods and properties will result in more reliable and maintainable
automated tests. |