As described in section 5.9, QF-Test is able to dig below the given
structure of GUI elements and work with sub-items that are not GUI components
themselves, like the cells of a table, nodes in a tree or drawings on a canvas. Such
items are implemented via the ItemResolver
mechanism which can be used to
implement your own custom items.
The ItemResolver
interface is more complex than the simple
NameResolver2
or FeatureResolver2
described in the previous
section and cannot be implemented without solid programming skills and a thorough
understanding of the underlying concepts. Also, ItemResolvers
and
Checkers
, described in the next section, are closely related and need to be
implemented together if you want to be able to perform checks for your items.
On the upside the whole mechanism is very powerful and once implemented and registered,
your ItemResolvers
will integrate smoothly with QF-Test so that there is no
distinction between standard and custom items, so don't let yourself be deterred.
You can find demo implementations in the directory
qftest-8.0.1/Jython/Lib
under QF-Test's root directory.
The respective demo files are ktable.py
and gef.py
. Both resolvers are for SWT specific tables,
but the concept is the same for all engines.
Before you start implementing an ItemResolver
you need to determine the
kinds of items that your GUI element might hold. There might be more than one kind,
though the decision is arbitrary. For example, we implemented
items for all standard tables of Swing, SWT and JavaFX
so that an item can either be a table cell or a complete column. The latter is
useful because it makes it possible to implement a check that checks a whole table
column at once.
First you need to decide how to represent your items internally. You can use any kind
of Object
because QF-Test doesn't ever examine your internal representation
itself, it just passes it to the methods of your ItemResolver
. What works
best depends on the API of the GUI element. If it already comes with its own concept
for sub-items it may be best to reuse those classes.
The most important decision to make is how to represent the item to the user of QF-Test.
As described in section 5.9, the user can address an item via a
numerical index or a textual one which can also be matched by a regular expression.
You need to be able to provide a two-way mapping between an item and its index(es),
i.e. you need to be able to answer the following two questions:
-
Given an item, what is its numerical and its textual index?
-
Given a numerical or textual index, which item matches that index best?
The issues involved in naming sub-items are the same as those for setting component
names. Please take a thorough look at subsection 5.4.2.1 and subsection 5.4.2.2 before continuing.
An single numerical or textual index is represented by a SubItemIndex
object. The current item concept supports addressing an item like a table cell via a
primary and a secondary index, but in the future we hope to support indexes to any
depth, so instead of using a path for a tree node it could be addressed with a
mixed-type index in a form like "tree@Root&1%Name:.*". Therefore the complete
index is represented as an array of SubItemIndex
objects, though
currently limited to single or two-element arrays.
Most items have a geometry, i.e. a location and a size. The coordinates for an item
are always calculated relative to the true upper left origin of the element,
regardless of whether it is scrolled, so they are independent of the current scroll
position of the element. For items where geometry is not applicable or cannot be
determined, coordinates can be ignored and the methods getItemLocation
and getItemSize
should simply return [0,0].
The methods of the interface
de.qfs.apps.qftest.extensions.items.ItemResolver
fall into three categories: Retrieving an item, mapping between an item and its index
and retrieving miscellaneous information for - or performing actions on - an item.
|
| | Object getItem(Object element, int x, int y) | |
Parameters | element | The GUI element to get the item for. | x | The X coordinate relative to element. | y | The Y coordinate relative to element. | Returns |
An arbitrary object representing an item or null if there is no item at the given
location.
| | int getItemCount(Object element, Object item) | |
Parameters | element | The GUI element for which to get the item count. | item |
Null to get the number items at the top level of the element. An item to get the
number of its sub-items.
| Returns |
The number of items or -1 if there is no further sub-item level.
| | Object getItemForIndex(Object element, SubItemIndex[] idx) | |
Parameters | element | The GUI element to get the item for. | idx | The sub-item index(es) for the item. | Returns | The item that best matches the given index. | Throws | IndexNotFoundException |
If no item matches the given index. Use the constructor
de.qfs.apps.qftest.shared.exceptions.IndexNotFoundException(SubItemIndex) for this case.
| | SubItemIndex[] getItemIndex(Object element, Object item, int type) | |
Parameters | element | The GUI element to which the item belongs. | item | The item to get the index for. | type |
The type of index to get. Possible values are INTELLIGENT ,
AS_STRING and AS_NUMBER , all defined in the
SubItemIndex class. Unless only one kind of index is supported, a
textual index should be returned for AS_STRING and a numerical index
for AS_NUMBER . If the type is INTELLIGENT you are free
to return whatever best represents the given item, even a mixed index like a
column title and a row index for a table cell.
| Returns |
An array of SutItemIndex objects. Currently only single or
two-element arrays are allowed.
| | int[] getItemLocation(Object element, Object item) | |
Parameters | element | The GUI element to which the item belongs. | item | The item whose location to get. | Returns |
The item's location as a two-element int array [x,y]. The location returned must
always be relative to the upper left corner of the whole element, even if that
corner is not currently visible, for example because it has been scrolled outside
the visible area. For items without geometry simply return [0,0].
| | int[] getItemSize(Object element, Object item) | |
Parameters | element | The GUI element to which the item belongs. | item | The item whose size to get. | Returns |
The item's size as a two-element int array [width,height]. For items without
geometry simply return [0,0].
| | String getItemValue(Object element, Object item) | |
Parameters | element | The GUI element to which the item belongs. | item | The item whose value to get. | Returns |
A string representing the value of the item, i.e. its contents, label, whatever.
| | Boolean repositionMouseEvent(Object element, Object item, int[] pos) | |
Parameters | element | The GUI element to which the item belongs. | item | The target item for the event. | pos |
A two-element int array of the form [x,y] with the coordinates of the event
relative to the item. Its values can be modified in place. You can either set them
to a specific coordinate or to [Integer.MAX_VALUE,Integer.MAX_VALUE] to ignore
coordinates for this event so that it will later be replayed on the center of the
target.
| Returns |
Boolean.TRUE if the position was modified, Boolean.FALSE if it was left unchanged.
Null to signal that this resolver does not handle the element.
| Throws | BadItemException |
If element and item types don't match up (should never happen).
| | Boolean scrollItemVisible(Object element, Object item, int x, int y) | |
Parameters | element | The GUI element to which the item belongs. | item | The item that must be made visible. | x |
The X-coordinate of the position relative to the item that must always become
visible.
| y |
The Y-coordinate of the position relative to the item that must always become
visible.
| Returns |
Boolean.TRUE if the scroll position of the element change, Boolean.FALSE if the
position is unchanged scrolled or if the element cannot be scrolled. Null to
signal that QF-Test should use its default mechanism and try to scroll the item
itself.
| | void setIndexesResolved(int num) | |
Parameters | num |
The number of indexes resolved.
| |
|
|
|
As explained in the previous section, a
de.qfs.apps.qftest.shared.data.SubItemIndex
represents a (partial) index
for a sub-item of a complex GUI element. This class defines some constants with the
following meanings:
- STRING
- This is a textual index
- NUMBER
- This is a numerical index
- REGEXP
- This is a regular expression to match a textual index
- INTELLIGENT
- When retrieving an index, use whichever type best suits the item
- AS_STRING
- Retrieve a textual index
- AS_NUMBER
- Retrieve a numerical index
It also provides the following methods:
|
| | SubItemIndex SubItemIndex(String index) | |
Parameters | index | The textual index. | |
| SubItemIndex SubItemIndex(int index) | |
Parameters | index | The numerical index. | |
| int asNumber() | |
Returns | The numerical index. | Throws | IndexFormatException |
If the index is not of type NUMBER or cannot be parsed as an integer.
| | String getIndex() | |
Returns | The index converted to a String. | | String getType() | |
Returns |
The type of the index, one of STRING , NUMBER or
REGEXP .
| | boolean matches(String name) | |
Parameters | name | The name to match. | Returns |
True if the index is not numerical and matches the given name.
| Throws | IndexFormatException |
If the index contains a malformed regular expression.
| |
|
|
Once implemented and instantiated, your ItemResolver
must be registered
with the ItemRegistry
. The class
de.qfs.apps.qftest.extensions.items.ItemRegistry
has the following
interface:
|
| | static ItemRegistry instance() | |
Returns | The singleton ItemRegistry instance. | | void registerItemNameResolver2(Object element, ItemNameResolver2 resolver) | |
Parameters | element |
The GUI element to register for. The resolver does not prevent garbage collection
and will be removed automatically when the element becomes unreachable.
| resolver | The ItemNameResolver2 to register. | |
| void registerItemNameResolver2(String clazz, ItemNameResolver2 resolver) | |
Parameters | clazz | The class of GUI element to register for. | resolver | The ItemNameResolver2 to register. | |
| void registerItemResolver(Object element, ItemResolver resolver) | |
Parameters | element |
The GUI element to register for. The resolver does not prevent garbage collection
and will be removed automatically when the element becomes unreachable.
| resolver | The ItemResolver to register. | |
| void registerItemResolver(String clazz, ItemResolver resolver) | |
Parameters | clazz | The class of GUI element to register for. | resolver | The ItemResolver to register. | |
| void registerItemValueResolver2(Object element, ItemValueResolver2 resolver) | |
Parameters | element |
The GUI element to register for. The resolver does not prevent garbage collection
and will be removed automatically when the element becomes unreachable.
| resolver | The ItemValueResolver2 to register. | |
| void registerItemValueResolver2(String clazz, ItemValueResolver2 resolver) | |
Parameters | clazz | The class of GUI element to register for. | resolver | The ItemValueResolver2 to register. | |
| void unregisterItemNameResolver2(Object element, ItemNameResolver2 resolver) | |
Parameters | element |
The GUI element to unregister for.
| resolver | The ItemNameResolver2 to unregister. | |
| void unregisterItemNameResolver2(String clazz, ItemNameResolver2 resolver) | |
Parameters | clazz | The class of GUI element to unregister for. | resolver | The ItemNameResolver2 to unregister. | |
| void unregisterItemResolver(Object element, ItemResolver resolver) | |
Parameters | element |
The GUI element to unregister for.
| resolver | The ItemResolver to unregister. | |
| void unregisterItemResolver(String clazz, ItemResolver resolver) | |
Parameters | clazz | The class of GUI element to unregister for. | resolver | The ItemResolver to unregister. | |
| void unregisterItemValueResolver2(Object element, ItemValueResolver2 resolver) | |
Parameters | element |
The GUI element to unregister for.
| resolver | The ItemValueResolver2 to unregister. | |
| void unregisterItemValueResolver2(String clazz, ItemValueResolver2 resolver) | |
Parameters | clazz | The class of GUI element to unregister for. | resolver | The ItemValueResolver2 to unregister. | |
|
|
|
For the implementation of the ItemNameResolver2
,
ItemValueResolver2
and Checker
interfaces it is important to
know which kind of Object is used for the internal representation of an item. This
internal representation will be passed to the methods getItemName
,
getItemValue
, getCheckData
and
getCheckDataAndItem
.
JavaFX
The following table lists the complex GUI elements
and the default internal item representation used by QF-Test standard
ItemResolvers
for JavaFX.
| GUI element class | Item type |
---|
Accordion | Integer index | ChoiceBox | Integer index | ComboBox | Integer index | ListView | Integer index | TabPane | Integer index | TableView | int array [column,row] with row < 0 to represent a whole column | TableHeaderRow | Integer column index | TextArea | Integer line | TreeView | TreeItem object |
|
| | Table 53.1: Internal item representations for JavaFX GUI elements | |
Swing
The following table lists the complex GUI elements
and the default internal item representation used by QF-Test standard
ItemResolvers
for Swing.
| GUI element class | Item type |
---|
JComboBox | Integer index | JList | Integer index | JTabbedPane | Integer index | JTable | int array [column,row] with row < 0 to represent a whole column | JTableHeader | Integer column index | JTextArea | Integer line | JTree | TreePath path |
|
| | Table 53.2: Internal item representations for Swing GUI elements | |
SWT
The following table lists the complex GUI elements
and the default internal item representation used by QF-Test standard
ItemResolvers
for SWT.
| GUI element class | Item type |
---|
CCombo | Integer index | Combo | Integer index | CTabFolder | Integer index | List | Integer index | StyledText | Integer line | TabFolder | Integer index | Table | int array [column,row] or just Integer column to
represent a whole column
| Text | Integer line | Tree | Object array [Integer column,TreeItem
row] or just Integer column to represent a whole column
|
|
| | Table 53.3: Internal item representations for SWT GUI elements | |
Web
The following table lists the complex GUI elements
and the default internal item representation used by QF-Test standard
ItemResolvers
for Web.
| GUI element class | Item type |
---|
SELECT node | OPTION node | TEXTAREA node | Integer line |
|
| | Table 53.4: Internal item representations for DOM nodes | |