You can add test objects to (and remove them from) the Name Mapping repository from tests. This can be useful, for example, if you want to get the name mapping data from an external source, such as an Excel file.
Requirements
-
The object you want to map must exist in the system.
-
The parent object of the object you want to map must be already mapped.
About
To map an object from tests, use the Mapped_Object.AddNamedChild
method. This method is available for all the mapped objects to which you refer by their alias or by a mapped name (that is, using the NameMapping.Object
or Aliases.Object
syntax).
For each object you are mapping, you can specify the following:
-
A mapped name to assign to the object.
-
The properties and values to use to map the object.
-
Whether to store information on the properties and methods of the mapped object. This way, you will be able to view the object’s properties and methods in test editors even if the tested application is not running.
-
An object description.
To learn more, see the method description.
Mapping objects from tests does not create aliases for these objects.
Mapping all application objects
Suppose, you want to map the application’s entire object hierarchy. To do this:
-
Create a keyword test or script that:
-
Calls the
AddNamedChild
method of the mapped root object (Sys
orMobile
) to map the application process. -
Calls the
AddNamedChild
method of the mapped process object to map each of the windows opened in the application. -
Calls the
AddNamedChild
method of each mapped window object to map controls in that window. -
And so on.
-
Note: The sequence of mapping operations must comply with the actual object hierarchy that you can see in the Object Browser.
You cannot skip intermediate hierarchy levels and, say, map a window as a child of the Sys
object.
Example
The following sample script demonstrates how you can create mapped names for objects in an MFC application. Objects in MFC applications usually have static control IDs that are defined by application developers, so you can use the ControlId
property as an identification property for mapped objects.
The script works with the Visual C++ version of the Orders sample application that can be found in the <TestComplete Samples>\Open Apps\OrdersDemo\MSVC folder. The application must already be running before you launch the script, and the Sys
and application process objects must be mapped to the Sys
and Orders
names respectively beforehand. The script maps the application objects (except for invisible objects and text labels) by using a combination of the ControlId
and WndClass
properties and generates mapped object names based on the object class and either its caption or index.
If you do not have the sample, download the TestComplete Samples installation package from the https://support.smartbear.com/downloads/testcomplete/samples/ page of our website and run it. |
JavaScript
function Main()
{
var p, props;
// Specify an array of identification properties
props = new Array(2);
props[0] = "ControlId";
props[1] = "WndClass";
// Obtain the running application process by its mapped name
p = NameMapping.Sys.Orders;
// Map objects in all of the application's opened windows
for (let i = 0; i < p.ChildCount; i++)
MapObject(p.Child(i), props, p)
}
// Maps Obj using the specified properties as a child of the MappedParent objects
function MapObject(Obj, PropArray, MappedParent)
{
var ValidProps, MappedName, MappedObj;
// Filter out unneeded objects
// (in this example - text labels and invisible Objs)
if (equal(Obj.WndClass, "Static") || !Obj.Visible) return;
// Check if the object supports any of the specified identification properties
ValidProps = new Array();
for (let i = 0; i < PropArray.length; i++)
{
if (aqObject.IsSupported(Obj, PropArray[i]))
ValidProps.push(PropArray[i]);
}
// If the object supports at least one of the specified identification properties, map it
if (ValidProps.length > 0)
{
// Generate the mapped object name based on the object class
// and either its caption or (if the caption is empty) index
MappedName = Obj.WndClass + (Obj.WndCaption != "" ? Obj.WndCaption : Obj.Index);
MappedName = GetValidIdentifier(MappedName);
// Map the object
MappedObj = MappedParent.AddNamedChild(Obj, MappedName, "", ConvertJavaScriptArray(ValidProps));
// Map the object's child objects
for (let i = 0; i < Obj.ChildCount; i++)
MapObject(Obj.Child(i), PropArray, MappedObj);
}
else
{
Log.Error(aqString.Format("The %s object was not mapped because it does not support " +
"any of the specified identification properties.", Obj.FullName));
}
}
// Creates and returns a valid identifier based on the specified string
function GetValidIdentifier(str)
{
// Remove invalid characters and leading numbers and underscores from the string
return str.replace(/\W+/g, "").replace(/^[\d_]+/g, "");
}
// Convert a JavaScript array to a Variant-compatible array
function ConvertJavaScriptArray(JavaScriptArray)
{
var oDict = getActiveXObject("Scripting.Dictionary");
oDict.RemoveAll();
for (var i in JavaScriptArray)
oDict.Add(i, JavaScriptArray[i]);
return oDict.Items();
}
JScript
function Main()
{
var p, props, i;
// Specify an array of identification properties
props = new Array(2);
props[0] = "ControlId";
props[1] = "WndClass";
// Obtain the running application process by its mapped name
p = NameMapping.Sys.Orders;
// Map objects in all of the application's opened windows
for (i = 0; i < p.ChildCount; i++)
MapObject(p.Child(i), props, p)
}
// Maps Obj using the specified properties as a child of the MappedParent objects
function MapObject(Obj, PropArray, MappedParent)
{
var ValidProps, MappedName, MappedObj, i;
// Filter out unneeded objects
// (in this example - text labels and invisible Objs)
if ((Obj.WndClass == "Static") || ! Obj.Visible) return;
// Check if the object supports any of the specified identification properties
ValidProps = new Array();
for (i = 0; i < PropArray.length; i++)
{
if (aqObject.IsSupported(Obj, PropArray[i]))
ValidProps.push(PropArray[i]);
}
// If the object supports at least one of the specified identification properties, map it
if (ValidProps.length > 0)
{
// Generate the mapped object name based on the object class
// and either its caption or (if the caption is empty) index
MappedName = Obj.WndClass + (Obj.WndCaption != "" ? Obj.WndCaption : Obj.Index);
MappedName = GetValidIdentifier(MappedName);
// Map the object
MappedObj = MappedParent.AddNamedChild(Obj, MappedName, "", ConvertJScriptArray(ValidProps));
// Map the object's child objects
for (i = 0; i < Obj.ChildCount; i++)
MapObject(Obj.Child(i), PropArray, MappedObj);
}
else
{
Log.Error(aqString.Format("The %s object was not mapped because it does not support " +
"any of the specified identification properties.", Obj.FullName));
}
}
// Creates and returns a valid identifier based on the specified string
function GetValidIdentifier(str)
{
// Remove invalid characters and leading numbers and underscores from the string
return str.replace(/\W+/g, "").replace(/^[\d_]+/g, "");
}
// Convert a JScript array to a Variant-compatible array
function ConvertJScriptArray(JScriptArray)
{
var oDict = new ActiveXObject("Scripting.Dictionary");
oDict.RemoveAll();
for (var i in JScriptArray)
oDict.Add(i, JScriptArray[i]);
return oDict.Items();
}
VBScript
Sub Main
Dim p, wnd, props(2)
' Specify an array of identification properties
props(0) = "ControlId"
props(1) = "WndClass"
' Obtain the running application process by its mapped name
Set p = NameMapping.Sys.Orders
' Map objects in all of the application's opened windows
For Each wnd In p
Call MapAppStructure(wnd, props, p)
Next
End Sub
Sub MapAppStructure(Obj, PropArray, MappedParent)
Dim ValidProps, i, cnt, MappedName, MappedObj, ChildObj
' Filter out unneeded objects
' (in this example - text labels and invisible objects)
If (Obj.WndClass = "Static") Or Not Obj.Visible Then Exit Sub
' Check if the object supports any of the specified identification properties
ValidProps = Array()
cnt = 0
For i = 0 To UBound(PropArray)
If aqObject.IsSupported(Obj, PropArray(i)) Then
ReDim Preserve ValidProps(cnt)
ValidProps(cnt) = PropArray(i)
cnt = cnt + 1
End If
Next
' If the object supports at least one specified identification property, map it
If UBound(ValidProps) >= 0 Then
' Generate the mapped object name based on the object class
' and either its caption or (if the caption is empty) index
MappedName = Obj.WndClass
If Obj.WndCaption <> "" Then
MappedName = MappedName & Obj.WndCaption
Else
MappedName = MappedName & Obj.Index
End If
MappedName = GetValidIdentifier(MappedName)
' Map the object
Set MappedObj = MappedParent.AddNamedChild(Obj, MappedName, "", ValidProps)
' Map the object's child objects
For Each ChildObj in Obj
Call MapAppStructure(ChildObj, PropArray, MappedObj)
Next
Else
Log.Error aqString.Format("The %s Obj was not mapped because it does not support " & _
"any of the specified identification properties.", Obj.FullName)
End If
End Sub
' Creates and returns a valid identifier based on the specified string
Function GetValidIdentifier(str)
Dim re, str2
Set re = New RegExp
re.Global = True
'Remove invalid characters from the string
re.Pattern = "\W+"
str2 = re.Replace(str, "")
'Remove leading numbers and underscores
re.Pattern = "^[\d_]+"
str2 = re.Replace(str2, "")
GetValidIdentifier = str2
End Function
DelphiScript
procedure MapAppStructure(Obj, PropArray, MappedParent); forward;
function GetValidIdentifier(str); forward;
procedure Main;
var p, props, i;
begin
// Specify an array of identification properties
props := CreateVariantArray(0, 1);
props[0] := 'ControlId';
props[1] := 'WndClass';
// Obtain the running application process by its mapped name
p := NameMapping.Sys.Orders;
// Map objects in all of the application's opened windows
for i := 0 to p.ChildCount - 1 do
MapAppStructure(p.Child(i), props, p);
end;
// Maps an object using the specified identification properties
procedure MapAppStructure(Obj, PropArray, MappedParent);
var ValidProps, i, cnt, MappedName, MappedObj;
begin
// Filter out unneeded objects
// (in this example - text labels and invisible Objs)
if (Obj.WndClass = 'Static') or not Obj.Visible then Exit;
// Check if the object supports any of the specified identification properties
ValidProps := CreateVariantArray(0, 0);
cnt := 0;
for i := 0 to VarArrayHighBound(PropArray, 1) do
begin
if aqObject.IsSupported(Obj, PropArray[i]) then
begin
ValidProps[cnt] := PropArray[i];
cnt := cnt + 1;
VarArrayRedim(ValidProps, cnt);
end
end;
VarArrayRedim(ValidProps, cnt-1); // Remove the extra element
// If the object supports at least one specified identification property, map it
if VarArrayHighBound(ValidProps, 1) > 0 then
begin
// Generate the mapped object name based on the object class
// and either its caption or (if the caption is empty) index
MappedName := Obj.WndClass;
if Obj.WndCaption <> '' then
MappedName := MappedName + Obj.WndCaption
else
MappedName := MappedName + VarToStr(Obj.Index);
MappedName := GetValidIdentifier(MappedName);
// Map the object
MappedObj := MappedParent.AddNamedChild(Obj, MappedName, '', ValidProps);
// Map the object's child objects
for i := 0 to Obj.ChildCount-1 do
MapAppStructure(Obj.Child(i), PropArray, MappedObj)
end
else
Log.Error(aqString.Format('The %s Obj was not mapped because it does not support ' +
'any of the specified identification properties.', Obj.FullName));
end;
// Creates and returns a valid identifier based on the specified string
function GetValidIdentifier(str);
var re, str2;
begin
re := HISUtils.RegExpr;
// Remove invalid characters from the string
re.Expression := '\W+';
str2 := re.Replace(str, '');
// Remove leading numbers and underscores
re.Expression := '^[\d_]+';
str2 := re.Replace(str2, '');
Result := str2;
end;
C++Script, C#Script
function Main()
{
var p, props, i;
// Specify an array of identification properties
props = new Array(2);
props[0] = "ControlId";
props[1] = "WndClass";
// Obtain the running application process by its mapped name
p = NameMapping["Sys"]["Orders"];
// Map objects in all of the application's opened windows
for (i = 0; i < p["ChildCount"]; i++)
MapObject(p["Child"](i), props, p)
}
// Maps Obj using the specified properties as a child of the MappedParent objects
function MapObject(Obj, PropArray, MappedParent)
{
var ValidProps, MappedName, MappedObj, i;
// Filter out unneeded objects
// (in this example - text labels and invisible Objs)
if ((Obj["WndClass"] == "Static") || ! Obj["Visible"]) return;
// Check if the object supports any of the specified identification properties
ValidProps = new Array();
for (i = 0; i < PropArray["length"]; i++)
{
if (aqObject["IsSupported"](Obj, PropArray[i]))
ValidProps["push"](PropArray[i]);
}
// If the object supports at least one of the specified identification properties, map it
if (ValidProps["length"] > 0)
{
// Generate the mapped object name based on the object class
// and either its caption or (if the caption is empty) index
MappedName = Obj["WndClass"] + (Obj["WndCaption"] != "" ? Obj["WndCaption"] : Obj["Index"]);
MappedName = GetValidIdentifier(MappedName);
// Map the object
MappedObj = MappedParent["AddNamedChild"](Obj, MappedName, "", ConvertJScriptArray(ValidProps));
// Map the object's child objects
for (i = 0; i < Obj["ChildCount"]; i++)
MapObject(Obj["Child"](i), PropArray, MappedObj);
}
else
{
Log["Error"](aqString["Format"]("The %s object was not mapped because it does not support " +
"any of the specified identification properties.", Obj["FullName"]));
}
}
// Creates and returns a valid identifier based on the specified string
function GetValidIdentifier(str)
{
// Remove invalid characters and leading numbers and underscores from the string
return str["replace"](/\W+/g, "")["replace"](/^[\d_]+/g, "");
}
// Convert a JScript array to a Variant-compatible array
function ConvertJScriptArray(JScriptArray)
{
var oDict = new ActiveXObject("Scripting.Dictionary");
oDict["RemoveAll"]();
for (var i in JScriptArray)
oDict["Add"](i, JScriptArray[i]);
return oDict["Items"]();
}
To call this script from a keyword test, you can use the Run Script Routine operation.
See Also
Adding Objects to the Name Mapping Repository
Name Mapping
Mapping Objects Automatically
Mapping Objects Manually