Knowledge Base Article

Data Structures for Application Object Definitions

The easiest and most efficient way I have found to manage object definitions is by grouping related object definitions within data structures stored in library files.

Library files containing data structure objects like JavaScript objects, Map objects, and JSON objects work well across multiple projects and suites.  These files are also nice to work with in source control.  Changes in any library file can be easily seen and tracked.  Each of these object types will integrate seamlessly with methods like FindChild and work equally well with desktop and web applications.  

  • JavaScript objects are directly usable in TestComplete scripts. 
  • Map objects have some advantages over JavaScript objects such as built in looping methods and properties. This adds some complexity in implementation as these methods must be used to access the data structure.
  • JSON is a 'portable' object definition.  Many different languages support JSON.  JSON requires a parse operation to return a JavaScript object prior to use in JavaScript. JSON would be preferred if the object definitions were created directly from the application code base by development.

Object Definition Examples

This code defines an object named customOptionObjDefs. It contains two UI object definitions: btnOK and btnCancel (It could contain many definitions).  The code below shows examples of a JavaScript Object, a JavaScript Map and a JSON Object and the code used with the TestComplete method FindChild.  

JavaScript Object

const customOptionObjDefs = {
  btnOK: { propertyNames:["WPFControlName","WPFControlText"] ,propertyValues: ["btnOK","OK"], depth: 16},
  btnCancel: { propertyNames:["WPFControlName","WPFControlText"] ,propertyValues: ["btnCancel","Cancel"], depth: 16}      
}
const btnOKDef = customOptionObjDefs.btnOK; // directly accessable 
const btnOKObject = parentObject.FindChild(btnOKDef.propertyNames,btnOKDef.propertyValues,btnOKDef.depth);

JavaScript Map Object

const customOptionObjDefs = new Map([
  ["btnOK", { propertyNames: ["WPFControlName", "WPFControlText"], propertyValues: ["btnOK", "OK"], depth: 16 }],
  ["btnCancel", { propertyNames: ["WPFControlName", "WPFControlText"], propertyValues: ["btnCancel", "Cancel"], depth: 16 }]
]);
const btnOKDef = customOptionObjDefs.get("btnOK"); // .get method
const btnOKObject = parentObject.FindChild(btnOKDef.propertyNames,btnOKDef.propertyValues,btnOKDef.depth);

JSON Object 

const customOptionObjDefs = {
  "btnOK": { "propertyNames": ["WPFControlName", "WPFControlText"], "propertyValues": ["btnOK", "OK"], "depth": 16 },
  "btnCancel": { "propertyNames": ["WPFControlName", "WPFControlText"], "propertyValues": ["btnCancel", "Cancel"], "depth": 16 }
};
const btnOKDef = JSON.parse(customOptionObjDefs).btnOKDef; // .parse method
const btnOKObject = parentObject.FindChild(btnOK.propertyNames,btnOK.propertyValues,btnOK.depth);

I prefer to organize object definition libraries in files by application and form and 'importing them in scripts or in the class structure of a project using 'require'.  These files can be stored externally to the project, shared and organized as desired.

const orderEntryDefs = require("orderEntryDefinitions");

Sometimes application objects are not well named or require a variable to be calculated dynamically in order to be defined. These objects are a challenge to define for automation and usually lead to brittle code.  In such cases code is written to determine the values needed for definition and passed directly to the FindChild method or a 'helper' class method or function.

In most cases a helper class method or a function is used to create and return the objects defined in the definition libraries.  The use of a 'helper' class method or function will provide a layer of abstraction, centralized error handling and more modular code.  The file(s) containing these functions or methods would also be imported for each script using 'require'.

Conclusion

The use of data structures provides a modular way to define and create instances of objects for automation scripts.  These objects can be easily looped over to find and create container objects for entire forms or very complex object like grids or trees. I have found that creating all available objects for a form or in groups if the form changes dynamically and storing them in a object makes the script easier to write and to read.  

Scott Holmes
WW Wood Products Inc.

 

Updated 2 months ago
Version 1.0
No CommentsBe the first to comment