Is there a way for SilkTest to test VB and ActiveX dependent objects that the recorder does not recognize?
Yes, can test dependent VB and ActiveX objects in SilkTest Classic using the special method _GetSubObjProp.
Dependent Objects Explained
SilkTest introduced a feature which many users had requested - the ability to drill down into ActiveX or Visual Basic controls to get at objects which are contained within.
Such objects are referred to as "dependent objects" in Microsoft tech notes, and they often expose properties and methods which are needed for verification. So how can SilkTest users get at these contained objects in order to make these calls? The answer is that the containing control provides a property which returns a handle to the desired dependent object.
Visual Basic hides this detail by providing syntax which automatically dereferences the inner object and makes the requested call against it in one step. An example is the Data control, which contains a Recordset control. To access the Count property of the Recordset object, one line of code in VB will suffice:
iRows = Data1.Recordset.Count
However, this syntax isn"t available in the 4Test language, nor can you get a handle on the Recordset object, and then make the call, since there is no callable "object" data type in 4Test. The solution is to use a special method implemented in the Agent called _GetSubObjProp.
Here is the signature:
ANYTYPE _GetSubObjProp (STRING sObjProp, STRING sPropName)
The first argument is a string which provides the name of the property which gives access to the inner object. In the current example, that would be "Recordset." The second arg is the name of the desired property exposed by the inner object. So the above VB call would look like this in 4Test:
iRows = Data1._GetSubObjProp("Recordset", "Count")
Of course, if you try to simply add this line of code to an existing testcase, you will get a compile error - because "_GetSubObjProp" is not part of the Data class definition. More on this later.
There is a special case of the dependent object scenario, in which two or more objects of the same class are arranged in a sequence or series.
Individual items within the series are typically referenced either with a numeric index, or with some sort of unique identifier in the form of a string, such as a column header. These sequential groups of objects are
referred to as collections, and in order to allow users to iterate through an entire series, or specify an individual element within the series, an intermediate object is provided called a Collection object. The
Collection object provides a standard, limited interface for enumerating and specifying objects in a collection. In order to get at the Collection object, the outer control will expose a property whose name typically is the plural of the class of item in the collection. A typical example is a Grid ActiveX, which contains a collection of Column objects. These objects expose properties, such as Value, which are needed for verification. An individual Column object is accessed through the Columns collection, and, as before, Visual Basic provides syntax which combines the various calls into one step:
iCurrVal = Grid1.Columns(3).Value
In this case, the index was used to specify the desired column. The column header could have been specified instead:
iCurrVal = Grid1.Columns("Customers").Value
In order to get at the same data in 4Test, users must call the method _GetItemProp. Here is the signature:
obj ANYTYPE _GetItemProp (STRING sCollProp, INT nIndex,
STRING sKey, STRING sPropName)
The first argument gives the name of the Collections property, for example, "Columns." The next two args provide alternative ways to specify the desired item--if the sKey arg is non-empty, that"s what will be used; otherwise, the nIndex arg will be used. Note the index is typically zero-based. The last argument is the name of the desired property. Thus, the VB collection call above will look like this in 4Test with a numeric index:
iCurrVal = Grid1._GetItemProp("Columns", 3, "", "Value")
Or with a string value:
iCurrVal = Grid1._GetItemProp("Columns", 0, "Customers", "Value")
Note that if the user wants to make calls against the Collection object itself, this is really the same as calling one of the SubObj methods. Nonetheless, a special set of methods is provided just for clarity--they do the same thing. In other words, the following two calls are equivalent:
iFields = Grid1._GetCollectionProp("Columns", "Count")
iFields = Grid1._GetSubObjProp("Columns", "Count")
Bringing It All Together
In order to make it easy to add the methods needed for accessing dependent objects, a special base class has been created called CompoundControl. The definition for this class is found in the file OLECLASS.INC in the Silk directory. In addition to providing the ability to get properties, this class provides methods for setting properties and calling methods against dependent objects and items in a collection. By having your class
inherit from CompoundControl you will then be able to use these methods in your scripts.