TestComplete supports the JScript engine version 5.8. C#Script and C++Script are based on JScript, so all of these languages have the same specifics of usage.
Note: JScript, C#Script, and C++Script are rarely used and are legacy languages. We do not recommend that you create script tests with them. We recommend that you use JavaScript (or Python) to create tests. See Selecting the Scripting Language.
Variable Scope
Variables that are declared with the var
statement within a function are only visible within this function. Variables that are used without declaring them with var
, become global variables. This behavior may cause hidden influence of functions onto other functions. For instance, the execution of the following code never ends:
JScript, C#Script, C++Script
function ChildFunc()
{
for(i = 0; i < 5; i++)
…
}
function ParentFunc()
{
for(i = 0; i < 10; i++)
ChildFunc();
}
This happens because after a call to ChildFunc
, the i
variable is always 5 and never 10, so the loop within the ParentFunc
function becomes an infinite loop.
Arrays
Some TestComplete methods that accept arrays (for example, AddNamedChild
), do not support native JScript arrays. You need to convert JScript arrays to TestComplete-compatible arrays using the following function:
JScript
function ConvertJScriptArray(JScriptArray)
{
// Uses the Dictionary object to convert a JScript array
var objDict = Sys.OleObject("Scripting.Dictionary");
objDict.RemoveAll();
for (var i in JScriptArray)
objDict.Add(i, JScriptArray[i]);
return objDict.Items();
}
C++Script, C#Script
function ConvertJScriptArray(JScriptArray)
{
// Uses the Dictionary object to convert a JScript array
var objDict = Sys["OleObject"]("Scripting.Dictionary");
objDict["RemoveAll"]();
for (var i in JScriptArray)
objDict["Add"](i, JScriptArray[i]);
return objDict["Items"]();
}
Similarly, arrays returned from TestComplete methods (FindAllChildren
, EvaluateXPath
and others) need to be converted to the JScript array format:
JScript, C#Script, C++Script
var jscript_array = original_array.toArray();
This may also apply to arrays passed to and returned from COM objects.
JSON
The JSON.stringify
, JSON.parse
and toJSON
methods work only with native JScript objects. They are not supported for TestComplete objects, for example, Aliases.browser.MyPage.
Passing Parameters by Reference
JScript, C#Script and C++Script do not support passing function parameters by reference. However, you may be able to call such functions by using the OutParameterWrapper extension.
This restriction also applies to calling DLL functions. However, when an object is passed through a function’s parameters in JScript, the function actually obtains a reference to the object. If the callee routine modifies some members of such an object passed through its parameters, the caller routine can access the updated object after the routine execution is over. Therefore, when a custom structure, array or string value created by the DLL.New
or IDLLAccessProcess.New
method (see Using Custom Data Structures in DLL Function Calls, Using Arrays in DLL Function Calls and Using String Parameters in DLL Function Calls) is passed from your JScript, C#Script or C++Script test to a DLL routine, you can access the modified structure, array or string after the routine execution is over. The point is that the New
method creates a wrapper object for such structures, arrays and strings and such an object is passed to a DLL routine by reference. So, such structures, arrays and strings can be modified and returned from the routine to which they are passed from JScript, C#Script and C++Script tests.
No Circular References Allowed Between Units
In TestComplete script units can refer to each other, so you can call routines and variables defined in other units. But JScript, C#Script and C++Script do not support circular references between units.
Using Objects Defined in Other Units
In TestComplete, if a script calls an object method that is defined in another unit, and this method throws an exception, the exception cannot be caught and handled by the try {}
block in the main script. Keep this in mind when developing object-oriented test scripts using native JScript functionality.
The following code demonstrates the issue:
JScript, C#Script, C++Script
[Unit1]
//USEUNIT Unit2
function Main()
{
try
{
var obj = new MyObject();
obj.SomeMethod(); // This causes an error that won't be caught
}
catch (e)
{
Log.Error(e);
}
}
[Unit2]
function MyObject()
{
this.SomeMethod = function()
{
1 = 2; // Raises an error
}
}
Prototype Methods
JScript, C#Script and C++Script support extending objects with custom methods declared as prototype methods. The way you call prototype methods of such objects from TestComplete units depends on the corresponding object. If you created a custom scripting object manually, you can call its prototype methods from any unit in a project. Prototype methods of JScript, C#Script and C++Script built-in objects (such as Array) can be called only in the same unit where these methods are declared; these custom methods are not available in other units.
A workaround for working with built-in objects is to insert code that creates an object instance to the same unit that contains the prototype method declaration. In this case, you will be able to use this object and its prototype methods in other units. For example, you can define a function that creates and returns an object instance and use this function instead of the object constructor in other units. The following code illustrates this approach:
JScript, C#Script, C++Script
[MainUnit]
//USEUNIT CommonUnit
function Main()
{
// This won’t work:
var arr = new Array(6, 7, 8, 9);
Log.Message(arr.indexOf(7)); // Error: "Object doesn't support this property or method"
// This will work:
var arr2 = NewArray().concat([1, 2, 3, 4, 5]);
Log.Message(arr2.indexOf(3));
}
[CommonUnit]
// Prototype method declaration
Array.prototype.indexOf = function(item)
{
for (var i = 0; i < this.length; i++)
{
if ((i in this) && (this[i] == item)) return i;
}
return -1;
}
// Creates and returns a new Array object
function NewArray()
{
return new Array();
}
Releasing COM Objects
When a variable goes out of scope, it is released. However, if the variable held a reference to an object, the JScript engine does not release this object until the entire script run is over. This happens because the JScript engine cleans up memory and references at a certain point and not when a variable is destroyed or you set it to null
.
This restriction may cause problems when working with certain program objects and COM servers. Suppose you have the following code:
JScript, C#Script, C++Script
function Foo()
{
Obj = new ActiveXObject("MyCOMObject.MyCOMObject");
…
Obj = null;
}
function MainFoo()
{
…
Foo();
// MyCOMObject still exists
…
}
In this example, MyCOMObject exists after a call to Foo
. Assigning null
to the Obj
variable marks it as a candidate for releasing, but the object still exists in memory. To force the releasing of all such objects and variables, call JScript’s CollectGarbage
method:
JScript, C#Script, C++Script
function Foo()
{
Obj = new ActiveXObject("MyCOMObject.MyComObject");
…
Obj = null;
CollectGarbage();
}
instanceof Operator
The instanceof
operator returns an incorrect value if the checked objects are passed between script units. Suppose you have the following code:
JScript, C#Script, C++Script
function fooA()
{
try
{
throw new Error(10, "This is an error."); // Simulates exception
}
catch(err)
{
var res = err instanceof Error;
Log.Message("fooA: err instanceof Error = " + res);
fooB(err);
}
}
function fooB(err)
{
var res = err instanceof Error;
Log.Message("fooB: err instanceof Error = " + res);
}
If both fooA
and fooB
reside in the same script unit, in both functions the res
variable will be true
. If you place fooB
to another unit, then the res
variable in fooA
will be true, and the res
variable in fooB
will be false
.
caller Property
In TestComplete, when a routine is called from another script unit, the caller
property of the Function object that corresponds to the current routine returns null
. Normally, when a function is called by another routine declared in the same script unit, the caller
property returns a reference to the function that invoked the current function. If the caller
property is used in a string context, it contains the text of the function that called the current routine. See the description of the Function
object and its caller
property in the MSDN Library.
debugger Statement
JScript’s debugger
statement has no effect in TestComplete. To pause the script execution and activate the debugger, use the Runner.Pause
method.
Accessing the script engine after fixing the script engine vulnerability
A critical security vulnerability has been reported in the script engine. To fix it, you can use the instructions at portal.msrc.microsoft.com/en-us/security-guidance/advisory/ADV200001.
However, applying this fix prevents TestComplete from accessing the engine and running tests. If you have already applied the fix and are facing the situation when your TestComplete tests have stopped running correctly, for instance, the tests stop immediately after the start generating an empty test log, you can do the following:
If you use a 32-bit version of Windows
-
Temporarily revert the fix by executing the following command:
cacls %windir%\system32\jscript.dll /E /R everyone -
Copy the C:\Windows\system32\jscript.dll file to the <TestComplete>\Bin folder.
-
Reapply the security vulnerability fix again as described at portal.msrc.microsoft.com/en-us/security-guidance/advisory/ADV200001.
-
Restart TestComplete.
If you use a 64-bit version of Windows
-
Temporarily revert the fix by executing the following commands:
cacls %windir%\system32\jscript.dll /E /R everyone
cacls %windir%\syswow64\jscript.dll /E /R everyone -
Copy the C:\Windows\system32\jscript.dll file to the <TestComplete>\x64\Bin folder.
-
Copy the C:\Windows\syswow64\jscript.dll file to the <TestComplete>\Bin folder.
-
Reapply the security vulnerability fix again as described at portal.msrc.microsoft.com/en-us/security-guidance/advisory/ADV200001.
-
Restart TestComplete.
See Also
JavaScript for JScript Users
Specifics of Usage Common for All Languages
Script Tests
About Script Tests
Selecting the Scripting Language