Writing C# Scripts

Applies to TestComplete 15.44, last modified on November 10, 2022

C#Script is a specific dialect of the C# programming language supported by TestComplete. It is based on JScript.

Note: C#Script is a legacy language. We do not recommend that you use it to create new tests. Instead, we recommend that you use JavaScript or Python. See Selecting Scripting Language.

C#Script was designed to let C# developers easily port script routines to their C# Self-Testing and Connected Applications.

Note: Connected and self-testing applications are deprecated. We do not recommend using them.

TestComplete can both record and play back C#Script routines. That is, you can record a script in TestComplete, debug it there, then import this script to your C# application and make it work by adding just few lines. For instance:

// This code was recorded by TestComplete:>
> function Test()
{
  var p, w;
  p = Sys["Process"]("notepad");
  w = p["Window"]("Notepad", "*");
  w["Activate"]();
  w["Window"]("Edit")["VScroll"]["Pos"] = 0;
  w["Window"]("Edit")["Click"](9, 9);
  Sys["Keys"]("Test");
  w["MainMenu"]["Click"]("File|Exit");
}

// This code was imported to a C# Connected Application:>
using AutomatedQA.script;
using AutomatedQA.TestComplete;

void Test()
{
  var p, w;
  p = Sys["Process"]("notepad");
  w = p["Window"]("Notepad", "*");
  w["Activate"]();
  w["Window"]("Edit")["VScroll"]["Pos"] = 0;
  w["Window"]("Edit")["Click"](9, 9);
  Sys["Keys"]("Test");
  w["MainMenu"]["Click"]("File|Exit");
}

In fact, the language of the code recorded by TestComplete for your C# projects is JScript. Therefore, you can simply write anything that is allowed in JScript and this script will be operational. For instance, in JScript and C#Script all variables and constants are VARIANT. You must declare them and you should do this using the following format:

var p, w;

This code will also be valid in C# self-testing and connected applications.

The syntax of C# scripts is the same as the syntax of C++ scripts (since C++Script is also based on JScript). This is so while the scripts reside in TestComplete. If you export scripts to a Connected Application, they will be different. That is, the syntax of C++Script and C#Script routines exported to C++ and C# connected and self-testing applications will differ.

Once again, the idea of having C#Script as a separate script language for TestComplete projects is to let developers, who are used to C#, write script code that requires minimal changes when being imported to C# applications. When writing such code in C#Script, please keep in mind the following rules, which distinguish C#Script from JScript:

  1. When calling methods, use only the following notation: method names are quoted and placed in brackets, and their parameters are placed in parentheses:

    C#Script

    Log["Message"]("My Message", "My Message Description", 0, 1);

    TestComplete uses this notation when recording C#Script routines. JScript uses another notation for method calls:

    C#Script

    Log.Message("My Message", "My Message Description", 0, 1);

    You should avoid this notation, since it is not supported in C# Self-Testing and Connected Applications. Otherwise, you will have to rewrite code when porting it to C#.

  2. To address properties in C#Script, you should also use square brackets. For instance:

    C#Script

    i = Sys["MouseX"]; //Getting the Sys.MouseX property
    Sys["MouseX"] = 120; // Setting the Sys.MouseX property

    To address an indexed property, use the following syntax: object_name["property_name"](index). For instance:

    C#Script

    // Getting the first object in the TestedApps collection
    var TestedAppObj = TestedApps["Items"](0);
    //Saving the object to the TestedApps list
    TestedApps["Items"](2) = MyTestedAppObj;
  3. Do not use JScript statements with and for…in and JScript operators ===, !==, >>> and >>>=. They are not supported in C#. If you use them, you will have to update your code when porting it to a C# application.
  4. In addition, these JScript objects are not currently supported in C# applications: Array, Boolean, Date, Function, Global, Math, Number, Object, RegExp, Error and String.
  5. Use the semicolon at the end of each statement.

When you have inserted your C#Script routines into C# code, you should modify its syntax. The copied code will not work “as is”, since there is a number of differences between C#Script and C#:

  • To execute the C#Script code in your C# Connected and Self-Testing applications, you will have to add the AutomatedQA.script.dll and AutomatedQA.TestComplete.CSConnectedApp.dll assemblies to these applications. For more information on this, see Creating Connected Applications in C# and Creating Self-Testing Applications in C#.

  • Change the syntax of copied functions: replace the keyword function with the function’s result type. For instance:

    // C#Script in TestComplete:
    function Test()
    {
     …

    // C#Script in a C# Connected Application:
    void Test()
    {

  • Inherit the class, which contains the script code imported from TestComplete, from the Connect class. Connect is defined in AutomatedQA.TestComplete.CSConnectedApp.dll. It contains fields that provide access to TestComplete programming objects and to global constants that you can use in scripts. For instance:

    • Connect.Sys - Provides access to the Sys object.

    • Connect.Log - Provides access to the Log object.

    • Connect.TestedApps - Provides access to the TestedApps object.

    • Connect.Regions - Provides access to the Regions object.

    Since the field names coincide with the object names and your class is inherited from Connect, you can call TestComplete programming objects in the same manner as you do this in TestComplete scripts:

    C#

    // Script code in a class inherited from the Connect class
    Log["Message"]("My message"); // Calls the Log.Message method
    Sys["Desktop"]["ActiveWindow"](); // Calls the Sys.Desktop.ActiveWindow method
    int i = Sys["MouseX"]; // Getting the Sys.MouseX property
    Sys["MouseX"] = 120; // Setting the Sys.MouseX property

    If you do not want to inherit your class from Connect, you should prefix the names of TestComplete programming objects in imported script routines with Connect. For instance:

    C#

    // Script code in a class that is not inherited from the Connect class
    Connect.Log["Message"]("My message"); // Calls the Log.Message method
    Connect.Sys["Desktop"]["ActiveWindow"](); // Calls the Sys.Desktop.ActiveWindow method
    int i = Connect.Sys["MouseX"]; //Getting the Sys.MouseX property
    Connect.Sys["MouseX"] = 120; // Setting the Sys.MouseX property

  • Note for Visual Studio .NET 2003 users:

    To work with objects and variables the C#Script code imported into a C# application, uses objects of the var type. These objects are analogues to Variant variables in Visual Basic or Delphi. If you assign a C# object object to a variable or property of the var type, the subsequent use of this variable or property will cause an error. For example, this may happen within an event handling routine:

    C#

    private void axEventControl1_OnLogError(object sender, AxEventControl.ItcControlEvents_OnLogErrorEvent e)
    {
      var lp = (var)e.logParams; // Incorrect
      lp["AdditionalText"] = "Message"; // <-- An error occurs
      …
    }

    The error happens because Visual Studio does not allow automatic construction of the base class (named object) to any other object:

    Compiler Error CS0553 'conversion routine' : user defined conversion to/from base class
    User-defined conversions to values of a base class are not allowed; you do not need such an operator.

    To solve the problem, use any of the following approach:

    C#

    private void axEventControl1_OnLogError(object sender, AxEventControl.ItcControlEvents_OnLogErrorEvent e)
    {
      var lp = new var(e.logParams); // Correct!
      lp["AdditionalText"] = "Message"; // Correct!
      …
    }

  • Change the syntax of statements that use indexed properties.  To set an indexed property, use the following syntax: object["property_name", index]. To read an indexed property, use the syntax object["property_name"](index). For instance:

    C#

    // Getting the first object in the TestedApps collection
    var TestedAppObj = TestedApps["Items"](0);
    // Saving the object to the TestedApps list
    TestedApps["Items", 2] = MyTestedAppObj;

  • Make sure that the variables that obtain references to script objects have the var type.

    C#

    // We assume that the testing code is inside of the class inherited from the Connect class,
    // so we do not use Connect to get to the TestComplete Sys object
    var p = Sys["Process"]("MyProcess", 1);
    var w = p["Window"]("My Windows Class", "My Window Caption");
  • Change the code that works with arrays that are returned by methods of TestComplete objects, for instance, by FindAll or FindAllChildren. The problem is that the script engine uses the Variant-array format that is not adopted in C#. So, to convert these values, you will have to call the UnWrap method of the var object.

    The following code demonstrates how you can call the FindAllChildren method from a C# Connected Application:

    C#

    void FindProcessMultiple()
    {
        // Creates arrays of properties and values
        String[] PropArray = new String[2];
        String[] ValuesArray = new String[2];

        // Specifies property names
        PropArray[0] = "ProcessName";
        PropArray[1] = "UserName";

        // Specifies the property values
        ValuesArray[0] = "*";
        ValuesArray[1] = Connect.Sys["UserName"];

        // Searches for the process
        var p = Connect.Sys;
        var res = p["FindAllChildren"](new var(PropArray), new var(ValuesArray), 1);

        // Posts the search results
        if (Connect.BuiltIn["VarArrayHighBound"](res, 1) >= 0)
        {
            object[] ManagedArray = (object[])res.UnWrap();
            for (int i = 0; i < ManagedArray.Length; i++)
            {
                var ArrayEntry = new var(ManagedArray[i]);
                Connect.Log["Message"]("Found: " + ArrayEntry["ProcessName"].UnWrap());
            }
        }
        else
            Connect.Log["Message"]("Not found");
    }

Note that the AutomatedQA.script.dll assembly allows you to work with other OLE servers, for example, with Microsoft Word, in the same easy manner as you work with TestComplete. AutomatedQA.script.dll simplifies the syntax used in C# applications to work with OLE servers via late binding. Once you have obtained the OLE server, you can address its methods and properties using the C#Script syntax rather than calling Type.InvokeMethod and other methods:

C#

using AutomatedQA.script;
 ...
class TestClass
{
  void Test()
  {
   var wrd = new var().GetObject("Word.Application");
 
   /* The following code performs some operations with the COM Server */
    wrd["Visible"] = true;
    wrd["Documents"]["Add"]();
    wrd["Selection"]["InsertAfter"]("Hello, world!");
  }
}

See Also

Script Tests
JScript, C#Script and C++Script - Specifics of Usage
Handling Exceptions in Scripts
Creating Connected Applications in C#
Creating Self-Testing Applications in C#

Highlight search results