Java Extension API for Custom Widgets
Package com.froglogic.squish.extensionSquish can work with all the standard AWT/SWT widgets out of the box. However, some custom widgets may represent their child components in a non-standard way, that is, not as AWT/SWT components. For example, a canvas might use normal Java objects to represent the items it displays. Or a Gantt diagram component might render its own contents, taking its data from a model. Squish's Java extension API makes it possible to extend Squish so that non-standard components in AWT and SWT applications can expose their APIs so that they become accessible to Squish and can therefore be accessed in test scripts just like any other component.
In order to tell Squish what functionality to expose, we introduce the concept of an Inspectable class. An Inspectable class is one that can respond to Squish's queries about objects of a particular type. For example, an Inspectable could handle canvas item types, and provide an API that can give Squish the canvas's bounds or its parent, or that returns all of its child items. The precise APIs are listed in the Inspectable interface; see Java Extension API Reference.
Once the Inspectables are registered, whenever Squish encounters an object, Squish queries each Inspectable to see if the Inspectable can handle the object (i.e., objects of the object's type). If one of the Inspectables reports that it recognizes the type as one it can handle, Squish uses that Inspectable's interface to interact with the object. This allows Squish to treat the object just like any of the standard AWT/SWT types that it supports out of the box—for example, Squish can query the Inspectable to see if the object has received a mouse click.
All the Inspectables for the types you want to Squish to be able to handle are placed together in a "wrapper" library. A clean way to do this is to put all the Inspectables classes in their own jar, although it is also possible to add them to the application's existing jar. The canvastest example shows how to put the Inspectables into their own jar.
Using the Java Extension API and a suitable wrapper, it is possible to support non-AWT/SWT components alongside standard AWT/SWT components so that Squish can:
- Identify both AWT/SWT and non-AWT/SWT components in test scripts.
- Use verification points on both AWT/SWT and non-AWT/SWT components.
- Show both AWT/SWT and non-AWT/SWT components in the overall Spy hierarchy.
- Pick both AWT/SWT and non-AWT/SWT components using the object picker.
See also, Wrapping custom classes
Java Extension API Classes
Class Color | |
Interface Inspectable — This interface needs to be implemented for custom Java support in Squish. | |
Class InspectableAdapter — Adapter class for writing extensions. | |
Interface InspectableFactory — A Factory that delivers an Inspectable for custom Objects that it manages. | |
Class InspectableRegistry — This class allows registration of factories of extensions that implement Inspectable. | |
Interface ItemExtension — This interface must be implemented when the Inspectable handles objects that have textual items, written in the test scripts using waitForObjectItem. | |
Interface ObjectQuery | |
Class Point — Toolkit independent Point class. | |
Class Rect — Toolkit independent Rectangle class. | |
Interface TableExtension — This interface can be implemented by an Inspectable, where its inspectable object has rows and columns. | |
Interface TargetExtension — This interface can be implemented when the inspectable object is part of another object. | |
Interface ViewportExtension — This interface can be implemented when the inspectable object has scrolling capabilities. |
Custom canvas Example
To show how a wrapper to extend an existing AWT application works, we will use the canvastest example which is shipped together with Squish for Java. You can find the source code in <SQUISHDIR>/examples/java/canvastest
. (We could just as easily have extended an SWT application using exactly the same approach.)
The application's source files are CanvasTest.java
, MyCanvas.java
, MyCanvasItem.java
, MyCanvasGroup.java
, MyCanvasShape.java
, MyRectCanvasItem.java
, MyCircleCanvasItem.java
, and together they comprise an AWT application that provides a simple canvas with multiple items.
We want test scripts that test the canvastest application to be able to query the application's MyCanvas
objects—to retrieve a MyCanvas
, to get a MyCanvas
's parent object, to get the canvas's bounding rectangle, and to get the MyCanvasItem
item at a particular point, or all of the canvas's MyCanvasItem
items. In addition, we want to be able to query MyCanvasItem
objects, to get their bounding rectangles, and so on. To do all this we must create suitable Inspectable Java classes that Squish can query to get interfaces through which it can query the application's canvas and canvas items as if they were standard AWT/SWT objects.
We have put the Inspectable classes in the MyCanvasFactory.java
file in the same directory as the application's other Java files. The Squish Java extension API classes are contained in the file <SQUISHDIR>/lib/squishjava.jar
, and so this file must be in the class path to be able to compile MyCanvasFactory.java
.
See Java Extension API Reference for information about the extension API.
Once the Inspectable classes have been created, Squish must be informed that they exist so that it can make use of them. All that is required to do this is to tell Squish which application the wrapper should be used for and where the wrapper is located. This is done by setting a configuration on the squishserver:
squishserver --config setConfig CanvasTest.jar \ $SQUISHDIR/examples/canvastest/Extension.ini
Here we have used a Unix-style path and assumed that the environment variable SQUISHDIR
has Squish's installation directory. It doesn't matter what the path used actually is (so long as it is an absolute path, and the correct one for the Extension.ini
file).
The Extension.ini
file must list the directory where the extension is located. A relative path is possible and should be relative to the working directory of the application. Here's the canvastest's Extension.ini
file's contents:
[general] JavaExtensionDir="."
If you are using Windows you should either use forward slashes or escape the backslash by writing the directory to the ini file.
To demonstrate testing the AUT with the wrapper we have provided a very basic test suite in <SQUISHDIR>/examples/java/suite_canvastest_js
.
Sometimes the application provided objects aren't suitable because they don't provide parent/child relationship. In that case, a helper class can be used. This class must be added to the extension.jar.
For example, take a popularity component, that draws five stars and the coloring shows the percentage. In such a case, a helper class with the component and index represents one star. The component children are five of such helper class instances. For each instance, the component is the parent.
Thus the Inspectable for the component creates helper objects in getChildren and getChildAt when at a star. An additional Inspectable for the helper objects makes them visible to Squish. Add public getter functions for any properties that you may need, e.g. a getIndex and getFill.
Make sure that helper classes override the java Object equals and hashCode methods, such that equals returns true when the fields are equal and hashCode is a value distinguishing the equality. In above example, the following code is required:
public boolean equals(Object obj) { if ( obj == null || !( obj instanceof StarHelper)) return false; StarHelper other = (StarHelper)obj; return other.index == index && other.component.equals( component); } public int hashCode() { return component.hashCode() + index + /*some random number*/ 43; }
Creating the .jar File
The manifest file must contain an Extension
entry that has as its value the class which has the public static void init(InspectableRegistry registry)
method. This function is the entry point for the extension and should register the factory class in the registry
.
For applications that load their classes with one or more class loaders that differ from the system class loader, an entry LoadAtClass
must be added. All RCP fall in this category.
The value of this entry is the class that will trigger the extension registration, as soon as that class gets loaded by a class loader. This may require some trial and error, because all the fields of the factory classes that get registered must already be known to the class loader.
For this example, LoadAtClass
is set to the Canvas
class. Here the manifest file for the extension jar.
Extension: MyCanvasFactory LoadAtClass: MyCanvas
© 2024 The Qt Company Ltd.
Documentation contributions included herein are the copyrights of
their respective owners.
The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property
of their respective owners.