Information in this topic applies to desktop applications only. |
Connected and Self-Testing applications are deprecated. These technologies will be removed in one of the future releases of TestComplete. To create test code that runs from within your tested apps, use TestLeft, a SmartBear functional testing tool for developers. |
This topics explains how you can expose an object of a C# application as a scripting object in TestComplete. The explanation applies to applications created with the following compilers:
- Microsoft Visual C# 2005
- Microsoft Visual C# .NET
The explanation is divided into the following sections:
Two notes before you proceed:
-
Objects of C# applications can be exposed in this way only if .NET support is enabled in TestComplete. That is, the .NET Application Support plugin must be installed and enabled in File | Install Extensions. In addition, the application should not be launched without the NotOpenApp command-line argument.
-
TestComplete must be launched before the C# application in order for the latter to be able to expose its objects.
Preparing Your C# Project
In order for you to expose objects of C# applications as TestComplete scripting objects, you need to get access to the TestComplete COM server. The easiest way to manage TestComplete via COM is to transform your application into a Connected Application. C# Connected Applications are created by linking special assemblies to your project. These assemblies provide objects and routines that free you from having to manually write the code needed to connect to TestComplete via COM.
To learn how you can transform your C# application into a Connected one, see Creating Connected Applications in C#.
Writing the Object Code
It is possible to create a scripting object from any existing object of a C# application. So, you can either expose an application’s particular object, or define a special class that implements specific test actions and register its instance as a scripting object. In this example, we will do the latter. Let’s create a sample class that defines a runtime object. This class will contain one property, Text
, and one method, ShowText
. The property will store a text string, and the method will display this string in a message box:
Registering and Unregistering Custom Scripting Objects
In order to add our custom object to the TestComplete object model, you need to register it in the TestComplete extensibility manager (see Creating Scripting Objects From Application Objects). You can obtain this manager using the Connect.Manager
notation.
To register a custom scripting object, use the manager’s AddName
method. The method call can be inserted in the application’s initialization routine, or in a routine that is called upon a specific event. In our example, we will add a button control to the application form and place the registration code in the button’s OnClick
event handler. This way, we will be able to easily re-register our object in subsequent TestComplete sessions while the application is running.
The sample code is provided below. Please pay special attention to the following:
-
The code uses the special
CreateWrapper
function. It creates and returns a wrapper object that implements theIDispatch
interface and provides access to the underlying .NET object. This function is provided by the TestComplete tcClrHook.dll library, so we need to write special code that refers to this function from the application code. -
At the end of the
button1_Click
routine, we call theMarshal.ReleaseCOMObject
method to release the COM wrapper created for the application’s object to be exposed. Make sure that you call this method and release wrappers for all objects that you expose in your code. Otherwise, the work with these objects will not be finished properly and the next attempt to register them as TestComplete scripting objects will fail.
C#
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using AutomatedQA.script;
using AutomatedQA.TestComplete;
namespace SampleRuntimeObject
{
public class Form1 : Form
{
private Button button1;
private SampleRuntimeObject runtimeObj;
private bool registered;
private const string runtimeObjName = "SampleRuntimeObject";
// Function needed to create a wrapper for application objects
[DllImport("tcClrHook.dll", PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
private static extern object CreateWrapper([MarshalAs(UnmanagedType.Interface)] object Obj);
...
public Form1()
{
InitializeComponent();
runtimeObj = new SampleRuntimeObject();
registered = false;
}
private void InitializeComponent()
{
...
this.button1.Click += new System.EventHandler(this.button1_Click);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
...
}
private void button1_Click(object sender, EventArgs e)
{
string projectPath = Path.GetFullPath("..\\..\\TCProject\\SampleRuntimeObject.pjs");
object wrapper = null;
// Open a project suite in TestComplete
Connect.TC["Visible"] = true;
Connect.Integration["OpenProjectSuite"].Call(projectPath);
Connect.Sys["Refresh"];
try
{
// Create a wrapper for runtimeObj and register it in TestComplete
wrapper = CreateWrapper(runtimeObj);
Connect.Manager["AddName"].Call(runtimeObjName, false, new var(wrapper));
registered = true;
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (wrapper != null)
Marshal.ReleaseComObject(wrapper);
}
}
}
}
To unregister an object, use the RemoveName
method of the TestComplete extensibility manager. In our example, we will place the unregistration code in the form’s Closing
event handler, so that the object is unregistered when the user exits the application. Since the unregistration makes sense only if the object has been previously registered and if TestComplete is running, we check both these conditions before calling the RemoveName
method:
C#
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Process[] TCProcessArr = Process.GetProcessesByName("TestComplete");
if (registered && TCProcessArr.Length != 0)
Connect.Manager["RemoveName"].Call(runtimeObjName);
}
Finally, re-compile your application.
Working With Custom Scripting Objects
After a custom scripting object is registered in TestComplete, it is displayed in the Code Completion window and can be used in scripts:
You can get and set the object’s property values, call its methods and check their return values the same way you would with standard scripting objects such as TestedApps
, Log
and others. The only difference is that the processing is performed by your application rather than by TestComplete.
The code snippet below demonstrates how you can work with the sample scripting object we have created earlier in this topic. This object is available in TestComplete from the time you launch the application and click the button on its main form and until the application is closed. Note that, despite the object is a part of a C# application, it can be used in scripts written in any scripting language, not only C#Script:
JavaScript, JScript
function Main()
{
SampleRuntimeObject.Text = "Hello, world!";
SampleRuntimeObject.ShowText();
}
Python
def Main():
SampleRuntimeObject.Text = "Hello, world!"
SampleRuntimeObject.ShowText()
VBScript
Sub Main
SampleRuntimeObject.Text = "Hello, world!"
SampleRuntimeObject.ShowText
End Sub
DelphiScript
procedure Main;
begin
SampleRuntimeObject.Text := 'Hello, world!';
SampleRuntimeObject.ShowText;
end;
C++Script, C#Script
function Main()
{
SampleRuntimeObject["Text"] = "Hello, world!";
SampleRuntimeObject["ShowText"]();
}
See Also
Creating Scripting Objects From Application Objects
Connected Applications - Overview
Creating Connected Applications in C#