TestComplete 3 FAQ. Accessing Application
Internals
This page contains answers to frequently asked questions about TestComplete 3. For answers to questions about TestComplete ver. 4 - 6, see TestComplete 6 FAQ.
Q.: What should I do to make sure that my application is an open application?
A.: Please try replacing this line:
[VBScript]
set p = Sys.Process("MyProcess")
with this one:
[VBScript]
set p = Sys.WaitProcess("MyProcess", 5000, True)
Please read the "Sys.WaitProcess" help topic for more details.
Q.: What is PRegister for? How can I use it?
A.: There are two ways to get access to objects' methods and properties of Delphi and C++Builder applications: The first is to compile the application with debugger information. The second is to use wrapper files generated by PRegister. (In both cases you have to add TCClient.pas to your project).
In the first case, TestComplete works with the application through the Debug Info Agent™. The Agent uses the debug information to access published, public, protected and private methods, properties and fields of application objects. That is, almost all internal elements become available to scripts. The price for such deep access is a larger executable size (debug information increases it in several times) and slower execution speed when you call methods and properties of application objects for the first time.
If you only need to have access to published and public elements, you can use wrapper files rather than the Debug Info Agent™. Wrapper files free you from compiling the application with debugger information. You can use them to see and test specific elements, but not the whole application. Also, wrapper files do not slow down the script when you call methods and properties of application objects for the first time.
To expose published and public methods and properties, you need to link in a wrapper file for each unit that you want public elements to become visible, for example --
uses Windows, Classes, Buttons_p;
(Here Button_p is a wrapper for the Button unit. By default, the names of wrapper files are finished with _p)
Wrapper files for VCL are installed in the <TestComplete>\Clients\Delphi\PRegister folder. If you want to access public elements in your own source or even in a third-party component, you should generate wrapper files for the sources using the PRegister utility that is installed with TestComplete. For a detailed overview of wrapper files, see the "Adding Public Information to Delphi and C++Builder Open Applications" help topic.
Q.: To make my application "Open" I added the TCClients unit in it and compiled the application with debug information. However, TestComplete does not see some methods and properties. Why?
A.: If you compiled the application in the described way, TestComplete uses the Debug Info Agent™ to access methods, properties and fields of the application objects. The Agent only sees methods that are mentioned in debug information. If the compiler has removed a method or a property from the debugger information, this method (property) becomes unavailable to TestComplete. Typically, the compiler can remove methods (properties) that are not called in the application code. To solve the problem, call the method (property) somewhere in your code. For detailed information about "invisible" methods and properties, see the "Debug Info Restrictions" help topic.
If you test a Delphi or C++Builder Open Application, the possible cause of the problem is that the Build with runtime packages option is enabled. If it is, disable it and then recompile the application.
Q.: When the application under test (the Open Application with debug info) has a lot of visual controls it takes too much time to start the script execution for the first time. What causes this delay?
A.: The delay is caused by reading debug info. If you want to only access published and public properties and methods, you can make the application "Open" using the wrapper files generated by PRegister. See the "Adding Public Information to Delphi and C++Builder Applications" help topic for more information.
Q.: How can I get data from a control? Is it possible to capture data in grid controls?
A.: Getting data from a control depends on the control type. To get data from simple controls, you can use methods and properties provided by TestComplete. For instance, if you want to get text from a third-party combo box or edit box, you can use the wText property of the Win32ComboBox or Win32Edit controls.
If you test complex controls, like Grids, you can use one of the following ways:
- If you test an "ordinary" non-Open Application, you can create a COM object that will retrieve data from the control and then pass it to TestComplete or save it to a file.
- You can compile a Self-Testing Application. Scripts embedded into a Self-Testing application act as the application code. Thus, they can access the control's data the same way the application does.
- For Open Applications there are two possible methods:
- The first is to write a public method that will retrieve all contents, reformat it into a standard data type (string, array, etc) for the test script to get and check. Depending on your need, you can also create a method that will do the checking itself, and then return the results. Once the method is done, it can be inherited, and so on. You can forget you ever "fixed" your source so scripts have access to the control's data. Note that this method is available for any kind of Open Application - Delphi, C++Builder, VC++, VB, Java or .NET.
- The second method (available for VC++, Delphi and C++Builder applications) is to compile the Open Application with debug information and write a script routine that will access the control's data. The following code illustrates retrieving data from MS DataGrid. TestComplete help also includes examples of retrieving data from VCL's TDBGrid, MS Flex Grid and some other controls.
[VBScript]
Sub TestDataGrid
Set p = Sys.Process("MyProject")
Set w = p.Form1
Set w = w.DataGrid1
' Finds indexes of the Title and Notes columns
ColIdx1 = -1
ColIdx2 = -1
For j = 0 To w.Columns.Count - 1
If w.Columns.Item(j).Caption = "Title" Then
ColIdx1 = j
End If
If w.Columns.Item(j).Caption = "Notes" Then
ColIdx2 = j
End If
Next
If ColIdx1 = -1 Then
Log.Warning "Column 'Title' was not found."
End If
If ColIdx2 = -1 Then
Log.Warning "Column 'Notes' was not found."
End If
If ColIdx1 > -1 And ColIdx2 > -1 Then
' Browses through the DataGrid rows and copies
' the contents of the Title and Notes columns
' to the test log
For i = 0 To w.DataSource.RecordSet.RecordCount - 1
w.Row = i
s1 = w.Columns.Item(ColIdx1).Text
s2 = w.Columns.Item(ColIdx2).Text
Log.Message s1, s2
Next
End If
End Sub
To learn more, see Working With Grids in TestComplete.
Q.: My program uses custom controls. Can TestComplete test them?
A.: Yes, TestComplete works with custom controls by simulating mouse clicks and key presses on any window. To work with Win32 controls, TestComplete uses special program objects - Win32Toolbar, Win32Menu, and so on. It is recommended to map the class names of custom controls to these objects. This allows you to call specific methods and properties for custom controls. For instance, you will be able to select items in a custom combo box by item names, select toolbar items by position of an item on the toolbar, and so on. To map controls, use the Options | Engine Options | Object Mapping dialog. If the Win32 methods don't work for a control, it means that either the control does not process Windows messages properly, or the control was mapped to the wrong Win32 object.
If you need deeper access to controls from scripts, e.g. you need to access specific properties of custom controls, you should compile the application as an Open Application. Without this, the controls will be "closed" for TestComplete, so you'll only be able to test them via the UI. For more information on how to make the application "Open", see the "Open Applications" help topic.
Q.: How can I access nonstandard objects from scripts?
A.: Your component is not a window object, so it is impossible to get access to its properties if you are performing black-box testing. In this case, there are two ways to solve the problem:
- Compile your tested application as an Open Application.
- Create an auxiliary COM object in the tested application. It will perform actions that you cannot perform using the black-box testing approach. You can refer to your COM object using Sys.OleObject.
Q.: How do I know which properties an object has?
A.: The Object Browser panel displays object properties and methods available to script routines. The Object Browser sees everything a script sees, and a script sees everything the Browser sees. For the script, you need the right syntax, for the Browser, you need to follow the tree branches and use the ellipsis ([...]) buttons. If the Browser is used correctly, it will show you all accessible properties of any object. If you press F5, it will also show you their current value.
In TestComplete Enterprise you can also use the built-in routine IsSupported(Obj, PropertyName) that lets you check if the object Obj contains the specified property.
Q.: How can I explore window classes with the Object Browser?
A.: All windows have the window class attribute (WndClass property). For example, windows that are Win32 tree view controls can have the following class names: TreeView, TTreeView, and so on. Object mapping allows you to force TestComplete to consider different window classes as one Windows control. That is, if we have the TreeView or TTreeView class, we can refer to an object (call its methods and properties) as a standard tree view control via Object Mapping.
Here is an example that demonstrates how Object Mapping works:
- Launch Notepad and find the Sys.Process('notepad').Window('Notepad', 'Untitled - Notepad', 1).Window('Edit', '', 1) object in the Object Browser. You will see that the object has the wText property.
- Select the Options | Engine Options | Object Mapping menu item. Uncheck the "Edit" class mapping for the edit control.
- Return to the Object Browser and see the object properties of Window('Edit', '', 1). You will see that the wText property has disappeared (Press F5 if you do not see any changes).
This means that TestComplete does not consider windows of the "Edit" class as edit controls.
Often, applications under test include controls that implement the behavior of standard Win32 controls, but they have non-standard window classes. The purpose of the Object Mapping feature is to enable TestComplete to consider these controls as standard Win32 controls.
Q.: Is it possible to explore properties of OLE objects in TestComplete?
A.: Yes. Use the OleObject property of the Sys object. Select it in the Object Browser panel, press the Params button and specify the class ID or program ID of the desired OLE object (For example, you may type Word.Application). TestComplete will try to connect to the specified object. If the object does not exist, TestComplete will create it. Once TestComplete has connected to the object, it will display the ellipsis button in the Property value column. Press this button to see available methods and properties.
Q.: How can I look inside my program at the objects that are not part of a visual form? Can the script access global variables of my app?
A.: To get access to internal application elements, TestComplete requires your application to be compiled as an Open Application (see TestComplete on-line help). According to the Object Model described in the help, TestComplete can access any form (or VCL TDataModule objects) and their child controls in your Open Application.
If you want to access an object that doesn't belong to a form, you must create a read/write property that will return this object and add this property to a form of your application, for instance, to the main form. Now you can call this property in your script code. In a similar manner you can provide access to global variables.
Q.: TestComplete does not recognize some controls, like labels, on my form. Why?
A.: Its possible that you are testing a non-Open Application. When you test a "closed" application, TestComplete needs to "know" which window it should address with mouse clicks and key presses. Some controls like TLabel and TImage in Delphi and C++Builder, or Label and Image in Visual Basic, are non-window controls. They are drawn on the canvas of the form.
To check whether the control is windowed or not, open the Object Browser. All windowed controls in it are displayed as children of the form. The non-windowed controls are not displayed.
To simulate mouse clicks over non-windowed controls, search for them using their images and perform clicks on the found area (see the "Images Comparison and Finding" help topic).
If your form implements the IAccessible interface, try using the MSAA plug-in. It gives TestComplete the ability to see all of the elements of IAccessible forms. After you install the plug-in in TestComplete, switch to the Object Browser panel to see if the form elements are available.
The problem with non-windowed controls completely vanishes if you compile your application as an "Open" one.
Q: I have a toolbar in my application and TestComplete does not press the correct button. What can I do?
A.: It depends on the toolbar system you use. Some systems change the window index (the third parameter in the Windows method), so if the toolbar window does not have a caption, TestComplete may confuse it with another window. There are two ways to be sure you press the correct button:
The first is to search for the button's image within the toolbar
window using the Regions.Find method and simulate a mouse click
within the found area.
The second is to compile the application as an Open Application and call the "click" method of the object using the keyword native. Of course, this way requires the toolbar or buttons to have the "click" method.
When my TSpeedButtons are disabled, TestComplete claims that they are enabled. Why?
A.: The cause of the problem is that the TSpeedButton control is not a windowed control. When you examine its Enabled property, you see the Enabled property of the window that owns your SpeedButton. This is a "TestComplete" property. To solve the problem, use SpeedButton.native.Enabled. It accesses the "VCL" Enabled property of the control. Please see the "Onscreen Objects" and "The keyword "native" help topics.
Q.: I need to get text stored in the TMaskEdit control. MaskEdit looks like a Win32 Edit control, however, it seems that in these controls the wText property is not available. How do I get the text?
A.: Add the TMaskEdit class to the Object Mapping / Edit section (Options | Engine Options | Object Mapping). Once you have performed this, the wText property will be available for the problematic editors.
