TestComplete includes a powerful recorder which allows testers record new tests instead of creating them from scratch. When creating a custom keyword test operation that wraps actions a tester can perform during test recording (such as a custom checkpoint), you may consider adding recording support for this operation. This way, you can enable TestComplete to record your custom operation instead of the corresponding standard operation(s).
This topic explains how to implement custom keyword test operations with recording support. The end of the topic contains the source code of a script extension that provides a sample operation that can be recorded.
About Keyword Recording Process
Before we go into detail on creating recordable operations, we would like to explain how keyword test recording takes place in TestComplete.
TestComplete records all tests, both scripts and keyword tests, in a script form. At that, keyword tests are generated based on the recorded script code by analyzing it and replacing individual statements by the corresponding keyword test operations. Script extensions can also be involved in analysis of the recorded code and thus can make TestComplete use custom operations where appropriate.
When analyzing the recorded script, TestComplete divides it into individual statements and searches for the keyword test operation(s) matching each of the statements. This search is performed as follows:
TestComplete raises the
IsSupportedevent on all keyword test operations and passes the script statement as a parameter.
TestComplete checks the return value of event handlers to determine which operations correspond to the statement. (Appropriate operations return True in this case.)
If there is only one appropriate, TestComplete adds it to the resulting keyword test. At that, it raises the
OnGenerateevent on the operation to initialize parameter and field values of the given operation instance.
If several operations reported that they correspond to the specified code snippet, TestComplete opts for the operation that has higher priority. The order of priority is as follows:
- Standard operations of the Checkpoints category (highest priority).
- Custom operations created with script extensions (high priority).
- Other standard operations (normal priority).
If candidate operations have the same priority, TestComplete decides between them at random. There is no way to determine or control this choice. This also means that TestComplete can choose different operations at different times.
If the statement being analyzed contains nested statements (this applies to conditional, loop and other statements), TestComplete repeats steps 1-2 for each of them.
About Creating Keyword Test Operations that can be Recorded
As it is mentioned in the previous section, TestComplete raises the
OnGenerate events on custom keyword test operations when constructing a keyword test based on the recorded data. So, to create a recordable operation, you need to subscribe to these events and handle them in the operation code.
The IsSupported event occurs when TestComplete is analyzing the recorded code and checks if a certain code snippet corresponds to your custom operation. The event has one parameter -- a string holding the script statement. This statement can be a method call, a property assignment, a conditional or any other statement supported by the scripting language of the user’s project. Note, that a statement can be multi-lined and include other statements (an example of such statement is
if … then).
The event handler should parse the specified code and return True if it corresponds to the operation and False otherwise. If it returns True, the operation will be considered as a candidate for adding to the keyword test in place of that code.
The OnGenerate event occurs if the operation’s
IsSupported event handler returned True. In this case, TestComplete creates a new instance of the operation and fires this event to initialize the operation parameters and fields according to the recorded code.
The event has three parameters - a string holding the script code and objects that provide access to the operation fields and parameters. (See the event description for details.)
The event handler should parse the code, retrieve values for the operation parameters and fields and initialize the latter with captured values.
OnGenerate event handlers is a nontrivial task, because it requires parsing the script code. TestComplete provides no built-in means for this purpose, so you need to analyze the code yourself. In most cases, you can do this using regular expressions. Note, however, that different scripting languages supported by TestComplete have different syntax, so you need to define code patterns for each of the supported languages. Also note that many object methods, whose calls can be present in the recorded script, use a variable number of parameters of variable parameter types, so it can be difficult to extract the parameter values from the script code.
|Be careful when implementing the
This example contains the code of a sample script extension that provides the following items:
The Copy File keyword test operation, which is a wrapper over the
aqFileSystem.CopyFilemethod. The operation has two parameters that specify the source and destination file names.
The Copy File record-time action. When selected during keyword test recording, it records the Copy File operation that copies the TestComplete help file to the Desktop. During script recording, the action records the corresponding
Below is the script code of the operation and the contents of the description.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Category Name="Keyword Test Operations">
<ScriptExtension Name="Copy File Operation" Author="SmartBear Software" Version="1.0">
<Script Name=""> <!- - Specify the script file name (script.vbs or script.js) in the Name attribute - ->
<KDTOperation Name="Copy File">
<Parameter Name="Source" DefaultValue=""/>
<Parameter Name="Destination" DefaultValue=""/>
<Column Name="Item" Value="Copy File" />
<Column Name="Value" Editable="True" EditorType="Parameters" />
<Event Name="OnExecute" Routine="CopyFile_OnExecute" />
<Event Name="IsSupported" Routine="CopyFile_IsSupported" />
<Event Name="OnGenerate" Routine="CopyFile_OnGenerate" />
// This routine is executed by the operation during the test run
function CopyFile_OnExecute (Data, Source, Destination)
if (aqFileSystem.CopyFile(Source, Destination))
Log.Message("The file \"" + Source + "\" has been copied successfully.")
Log.Error("Failed to copy the \"" + Source + "\" file.")
// Holds parsed script code
// This routine checks if the operation is equivalent to the specified code snippet
// Construct a regular expression that matches the aqFileSystem.CopyFile method call
re = /aqFileSystem\.CopyFile\(\"(.*)\", \"(.*)\"\)/; break;
case "VBScript" :
re = /Call aqFileSystem\.CopyFile\(\"(.*)\", \"(.*)\"\)/; break;
re = /aqFileSystem\.CopyFile\('(.*)', '(.*)'\)/; break;
case "C#Script" : case "C++Script":
re = /aqFileSystem\[\"CopyFile\"\]\(\"(.*)\", \"(.*)\"\)/; break;
// Test the Code against the regular expression
match = re.exec(Code);
return (match != null);
// This routine initializes the operation instance corresponding to the specified code
function CopyFile_OnGenerate(Code, Data, Parameters)
The Code has already been parsed in the IsSupported event handler.
So, we only need to initialize the operation parameters with
values retrieved from the Code.
// Replace double backslashes in file names with single ones
Parameters.Source = aqString.Replace(match, "\\\\", "\\");
Parameters.Destination = aqString.Replace(match, "\\\\", "\\");
' This routine is executed by the operation during the test run
Sub CopyFile_OnExecute (Data, Source, Destination)
If aqFileSystem.CopyFile(Source, Destination) Then
Log.Message "The file """ & Source & """ has been copied successfully."
Log.Error "Failed to copy the """ & Source & """ file."
' Holds parsed script code
' This routine checks if the operation is equivalent to the specified code snippet
' Construct a regular expression that matches the aqFileSystem.CopyFile method call
Set re = New RegExp
Select Case Syntax.CurrentLanguage
re.Pattern = "aqFileSystem\.CopyFile\(""(.*)"", ""(.*)""\)"
re.Pattern = "Call aqFileSystem\.CopyFile\(""(.*)"", ""(.*)""\)"
re.Pattern = "aqFileSystem\.CopyFile\('(.*)', '(.*)'\)"
Case "C#Script", "C++Script"
re.Pattern = "aqFileSystem\[""CopyFile""\]\(""(.*)"", ""(.*)""\)"
' Test the Code against the regular expression
Set Matches = re.Execute(Code)
CopyFile_IsSupported = (Matches.Count > 0)
' This routine initializes the operation instance corresponding to the specified code
Sub CopyFile_OnGenerate(Code, Data, Parameters)
' The Code has already been parsed in the IsSupported event handler.
' So, we only need to initialize the operation parameters with
' values retrieved from the Code.
' Replace double backslashes in file names with single ones
Parameters.Source = aqString.Replace(.SubMatches(0), "\\", "\")
Parameters.Destination = aqString.Replace(.SubMatches(1), "\\", "\")
You can test this example in the following way:
Copy the folder containing the script file and the description.xml file to the <TestComplete>\Bin\Extensions\ScriptExtensions folder.
Launch TestComplete and create a new project.
Start recording a keyword test and specify the test name.
In the list of custom actions on the Recording toolbar, select Copy File.
The recorded keyword test will contain the Copy File operation. The operation parameters will specify the <TestComplete>\Help\TestComplete15.chm file as a source and <Users>\<User_Name>\Desktop\TestComplete15.chm (on Windows Vista, Windows 7, Windows Server 2008 and later operating systems) or <Documents and Settings>\<User_Name>\Desktop\TestComplete15.chm (on other operating systems) as the destination file.