| Version 3.4.7 |
| The Standard Library [30-45 min] |
We complete the concept of modularization in this chapter by presenting a standard library of utility functions. Some of the utilities you'll already be familiar with, like operations for dealing with checkboxes. Other utilities will be new. The following sections will cover in detail each of these operations.
There are several things to be learned from this chapter. Most importantly, you'll see a workable utility library (in fact, the library evolved from a very similar library used for regression tests of QF-Test at Quality First Software GmbH). In the process of analyzing the operations contained within, you will hopefully obtain ideas of how to better modularize your own test-suites and simplify the overall testing process.
The procedures within this library should work with any standard
Java/Swing or Eclipse/SWT application; that is, they were designed
independently of any specific SUT. Thus, they should fit the needs of
your SUT quite nicely.
The library is contained in the file qfs.qft and is included
as part of the QF-Test distribution.
To make use of qfs.qft click on the "Test-suite" root node
of your test-suite. Within the properties of this node you'll see a
table for "Include files". Please add qfs.qft to this list.
A path information is not necessary as the include
directory of QF-Test is contained in the library path (see also
Reference part of the manual).
Now you can select procedures of this library at any procedure-call.
In addition to the description provided in this tutorial you can find HTML documentation of
the standard library in a javadoc-like format. The file named qfs_pkgdoc.html is located in the
directory qftest-3.4.7/include/qfs_pkgdoc.
| The SUT For Testing |
As we've already noted, the standard library to be introduced is not SUT-specific. However, for purposes of demonstration within this tutorial we will use an application specifically tailored for use with the standard library.
Bring up the test-suite StdLibDemo.qft, which - like the
suite Options.qft you should be familiar from earlier
chapters - is located in directory
qftest-3.4.7/doc/tutorial from your QF-Test
installation. You should see the following:
|
| ![]() |
||
|
| Figure 8.1: The Test-suite StdLibDemo.qft | ||
Start the SUT application by executing the Setup node (as seen). In a few moments, the window of the SUT should appear. If not, it is probably hidden beneath the test-suite.
|
| ![]() |
||
|
| Figure 8.2: The SUT for Testing the Standard Library | ||
| The Standard Library |
Locate and load the test-suite file qfs.qft, which is
located in the qftest-3.4.7/include directory
of your QF-Test installation.
Here we see a brief overview of the packages available:
|
| ![]() |
||
|
| Figure 8.3: The Standard Library | ||
The suite primarily contains procedures for dealing with Java/Swing and Eclipse/SWT components. The "swing" and the "swt" package contain nearly the same procedures to deal with several components. The structure of both packages is the same, so the following description will cover the Java/Swing as well as the Eclipse/SWT procedures. There are also a couple of other usefule packages included, which are also documented below.
Within all of the procedures of this library, you'll notice that the
variable $(client) is referenced. This is a standard mechanism that
you'll often see repeated in many test-suites for creating
independence from a specific SUT. Here, the library assumes that the
test-suite which uses the library will set a value for $(client) prior
to using any procedures. For example, here we see the properties of
the "Test-suite" root node of the suite StdLibDemo.qft, in
which we set down the value of $(client) as a suite variable. Thus,
any nodes executed within the scope of this test-suite (such as the
procedure calls to qfs.qft) will have access to the
variable.
|
| ![]() |
||
|
| Figure 8.4: Setting the $(client) Variable | ||
You could alternatively set the value of $(client) per call to a
procedure within qfs.qft. Such a scheme might be useful
when you have more than one SUT. Just to hammer this point down,
please note that qfs.qft cannot have any default value
set for the $(client) variable as this would undesirably couple it to
a specific SUT. It is up to you to set a value of the $(client)
variable for the standard library to use!
One further note before we continue: you may have noticed from the
figure above that we've included qfs.qft within the
demonstration test-suite without any direct reference to the directory
in which the file is located. This is because the
include directory of your QF-Test distribution has been
added to QF-Test as an implicit library path for all of your
test-suites. This means that any test-suite file located within this
directory can be included within your own test-suite. For further
library paths, look at the global options for QF-Test under »Edit«-»Options«-»General«-»Library.«
A complete description of all packages and procedures including parameters and return values is given in the library's HTML documentation, also accessible from the QF-Test »Help« menu. The latest version is even available online at http://www.qfs.de/include/qfs_pkgdoc/qfs_pkgdoc.html.
| Selected Packages and Procedures |
We will now have a closer look at a number of selected packages and procedures from the standard library.
Please note, that following examples are mainly based on the qfs.swing
procedures. The procedure of qfs.swt can be used in the same way.
Procedures, which are Java/Swing or Eclipse/SWT specific will also be handled
at the end of this chapter.
| The Checkbox Package |
We begin by looking at the swing.checkbox and swt.checkbox package,
which are a good starting point as the procedures here should look very
familiar if you developed the utils.qft library suite in
chapter 7.
The procedures available within this package are:
For each of these procedures, you pass the ID of a checkbox component as
a variable argument. The library handles verification of whether or not
the checkbox state was properly set as expected. To see example usage of
these procedures, look in the "Checkbox Tests" node of
StdLibDemo.qft.
|
| ![]() |
||
|
| Figure 8.5: Example Usage of the qfs.swing.checkbox
Package | ||
Usage of the other procedures in this package follows the general model seen here.
| The Combobox/Combo Packages |
The packages swing.combobox bzw. swt.combo
contain procedures to select a value in a combobox.
The procedures available within this package are:
setSelectedItem() for Swing and select() for
SWT.
| The General Packages |
The packages swing.general bzw. swt.general
contain useful procedures to work with components.
The procedures available within this package are:
| The List Packages |
The packages swing.list bzw. swt.list
contain useful procedures to work with lists.
The procedures available within this package are:
| The Menu Package |
The swing.menu and swt.menu packages allow you to easily select
items and checkbox items from menus or sub-menus. The procedures visible after expanding
the package node are:
For each of these procedures, you must pass the component ID of the menus as well as the item and/or sub-item to select or check; the usage varies slightly depending on the nature of the procedure. Take a look at the example usage "Menu Tests" node. For example, a call to "setSubCheckItem" looks as such:
|
| ![]() |
||
|
| Figure 8.6: Example Call to qfs.swing.menu.setSubCheckItem
| ||
Here we see the variable arguments needed to implement the procedure call. These arguments are organized as:
menu -> item -> subCheckItem (checkItemValue)
which represent the following implementation within the SUT:
Options -> Tree -> Enable (true)
Clearer may be the actual process as seen within the SUT:
|
| ![]() |
||
|
| Figure 8.7: Selecting a Sub-Menu Check Item within the SUT | ||
| The Popup Menu Package |
Popup menus are similar to regular menus in that they contain items, sub-menus and checkbox menu items. The primary difference is the means by which a popup menu is invoked, which is by right-clicking a component that has been configured to display a popup menu.
The packages swing.popupmenu and the swt.popupmenu contain the same
procedures as swing.menu and swt.menu; only the implementation is
different. For each procedure, your test-suite must first take care of
opening the popup menu before calling any procedure from the
swing.popupmenu or the swt.popupmenu package, as a popup menu is
component-specific. Consider the following example as shown within the
SUT:
|
| ![]() |
||
|
| Figure 8.8: Selecting a Sub-Menu Item within a Popup Menu | ||
We implemented this example through the following test in
StdLibDemo.qft. The first node brings up the popup menu, and
then the call to the procedure is made, followed by a check of the results.
|
| ![]() |
||
|
| Figure 8.9: Example Call to popupmenu.setSubItem
| ||
| The SWT/Sash Package |
The package swt.sash contains procedures for working with components of
the class org.eclipse.swt.widgets.Sash.
| The Table Package |
The packages swing.table and swt.table provide utility procedures for tables.
The trick in the implementation is the "Fetch Geometry" node to get the current column width. From this position the resize action is performed by dragging the mouse appropriately to the left or to the right.
| The Table/Selection Package |
The packages swing.table.selection and swt.table.selection provide procedures to do selections on certain table cells.
The trick in the implementation is the "Fetch Geometry" node to get the current column width. From this position the resize action is performed by dragging the mouse appropriately to the left or to the right.
| The Tabbedpane/CTabfolder Package |
The packages swing.tabbedpane and
swt.ctabfolder provide utility procedures
for tabbed-panels or tab-folders.
| The Text Package |
The packages swing.text and swt.text provide utility procedures
for text fields and text areas, the need for which you may have
already come across while developing test-suites.
Note These procedures are now almost redundant, because "Text input" nodes can clear the target component as needed. However, the procedures might still come in handy now and then.
For each of these procedures, simply pass the ID of the text
field/area component. Here we see a test within
StdLibDemo.qft that uses makes use of the text area
component within the SUT. In this test, we first clear the text area
and input two lines of text. Then the text area is verified to confirm
that it contains the expected test. Following this, we clear the text
area again and verify that it is empty.
|
| ![]() |
||
|
| Figure 8.10: Example Usage of text.clearArea
| ||
| The Tree Package |
We've provided some simple access procedures for manipulating trees
within the packages swing.tree and swt.tree. These include:
For any of these procedures, you simply pass the component ID of the node you wish to manipulate. For example, here we see a call to the procedure to expand a tree node:
|
| ![]() |
||
|
| Figure 8.11: Example Usage of tree.expand
| ||
Note that in this example, we use a component of a tree node which we
recorded earlier. If you look in the "Windows and components" node of
the StdLibDemo.qft test-suite, you'll see the individual
tree-item components we recorded:
|
| ![]() |
||
|
| Figure 8.12: Tree Component Items | ||
| The Cleanup Package |
The packages swing.cleanup and swt.cleanup are
useful for generic cleanup of the SUT environment after an unexpected
exception occurs. Imagine, for example, that an exception is thrown
while attempting to manipulate a menu in the SUT. The exception will
cause the execution path within your test-suite to be re-directed to an
exception handler, or an "implicit" exception handler. This means that
the normal flow of execution, which would have properly closed the open
menu, has now been interrupted. Without proper action, that menu could
be left open and thus block other events directed to the SUT.
Here is the list of available procedures within this package:
The first procedures should be relatively clear in meaning and
purpose. The procedure implicitExceptionHandler in fact
encompasses the usage of the other procedures within this package,
which makes it a good default handler for your own test-suite should
unexpected exceptions arise.
The concept of implicit exception handling is an important one and we'll dedicate the rest of this section to discussing it. If you look within the properties of any Test node, you'll see a checkbox called "implicitly catch exceptions:"
|
| ![]() |
||
|
| Figure 8.13: A Test Configured to Implicitly Catch Exceptions | ||
With this feature enabled within a Test, an exception that occurs and is not caught explicitly within a Catch node will instead be redirected to the Cleanup node of the Test node. Without an implicit catch an uncaught exception will cause execution of the test-suite to be halted.
Rules for the scope of implicit exception handling are simple: if an exception is thrown and not caught, then QF-Test looks for the next parent Test node which has been configured to implicitly catch exceptions. It is therefore possible to configure a hierarchy of implicit-catch handling.
Note If a Test node implicitly handles an exception, its final state will be set to "Exception" to reflect this. The error will be duly reported to make sure the exception does not accidently go unnoticed.
Within StdLibDemo.qft we see an example of a Test which is
configured to implicitly catch exceptions and in which several
unexpected exceptions occur. The test is essentially nonsense, but it
is useful for our purposes as it demonstrates this feature quite
nicely. Here we produce the errors by leaving open modal dialogs and
menus, then attempting to click on the main SUT window, thus causing
an exception to be thrown due to being blocked by the modal dialog or
menu.
|
| ![]() |
||
|
| Figure 8.14: Implicit Error Examples | ||
Try running the test yourself. Before starting please temporarily deactivate the option
»Edit«-»Options«-»Debugger«-»Break on uncaught exception«. Otherwise the debugger will open independent of the
"Implicitly catch exceptions" status. What is interesting to see is the behavior when the
"Implicitly catch exceptions" flag is not checked, or by simply disabling the call to
implicitExceptionHandler. As with any such material, real understanding often
comes from first-hand experience coupled with the background information provided here. We
encourage you to try out this and the other tests in the test-suite to view the behavior
for yourself.
| The Swing/Filechooser Utility Package |
The package qfs.swing.filechooser presents a slight
variation on the utility procedures we've seen in this library up to
now. This package is intended not only to assist in manipulating any
file chooser dialog (the JFileChooser swing component, to be specific),
but also to help in recording and identifying components of this dialog
window. We'll first list the procedures and then get into more detail:
The the first procedure (selectFile) is fairly straight-forward. You simply provide the file name that will be input to the "file name" text field (or whatever it may happen to be called) of the dialog. Your test-suite must first handle opening the dialog. For example:
|
| |||
|
| Figure 8.15: Example Usage of
qfs.swing.filechooser.selectFile | ||
However, using selectFile will not
work until your test-suite enables the name resolver! We come to that next.
The procedure enableNameResolver installs and enables an
extension to QF-Test called the JFileChooserResolver. This name resolver
will help you tremendously in dealing with the short-comings of the
Java JFileChooser dialog. It is a standard NameResolver
as explained the chapter named "Name resolver hooks" in the technical reference
manual.
The interesting thing with JFileChooser is that components within the
standard dialogs (and indeed the dialog window itself) have not been
named with the Java setName operation. This can lead to
some confusion in developing test-suites, as the same components
appear to show up in different dialog windows. For example, the "File
Name" text field will be seen in both a "Save" and an "Open" file
chooser dialog.
For QF-Test this is not a problem. It has powerful algorithms for recording and recognizing components and therefore should not confuse an unnamed and non-unique component that appears in multiple windows. The confusion will arise for the test-suite developer mostly in terms of managing the components. Take a look at the component list recorded for the two "Open" and "Save" file chooser dialogs for the demo application:
|
| ![]() |
||
|
| Figure 8.16: Recorded JFileChooser Dialogs and Components | ||
As you can see, QF-Test correctly identified the components and gave each a unique identifier, such as "textFile_Name:2" - which represents the second of the same component of this type that was seen. Imagine now that you have many other kinds of JFileChooser dialogs, each with its own list of components that must be separately maintained. Writing test-suites under this type of environment can quickly become unwieldy.
Enter the name resolver. This is a feature which enables QF-Test to
assign names to unnamed components of a JFileChooser dialog as if
they had been named within the original Java source code using
setName! The result is that the JFileChooser and its
components can be generically treated. That is, you'll need just one
list of components for any number of JFileChooser dialogs that may be
manipulated within your test-suite. Here we see an example usage:
|
| ![]() |
||
|
| Figure 8.17: Using the Name Resolver | ||
We see in the implementation of selectFile that the generic
components are referenced:
|
| ![]() |
||
|
| Figure 8.18: Implementation of selectFile with Generic
Components | ||
Indeed for your own test-suite, you should not even need to maintain any
components for any JFileChooser dialogs, if you are going to use the
name resolver. The generic components are stored within qfs.qft:
|
| ![]() |
||
|
| Figure 8.19: Generic FileChooser Components in qfs.qft
| ||
Note that within our demonstration test-suite
StdLibDemo.qft, the name resolver is enabled and disabled
during the setup and cleanup. This is really just overkill and only done
for demonstration purposes. You should only need to enable the name
resolver once in your test-suite and leave it be. There's also no direct
need to disable the name resolver after it has been enabled.
| The Swing/Optionpane Utility Package |
The package qfs.swing.optionpane contains name resolver utility procedures
similar to those described in the last chapter. JOptionPane is the swing component used to
create those little message boxes informing the user about program errors, warnings or the
need for confirmation.
The need for a name resolver for this component results from the fact that neither the dialog nor its subcomponents, like confirmation buttons and message text labels, are named. So QF-Test needs to identify them on base of their titles or label texts, which results in creating various component nodes for each instance of JOptionPane. This may lead to a great number of those elements and is for reasons of clearness and maintainability not desirable.
Now let's have a look at the interface procedures. They are very simple:
The procedure enableNameResolver installs and enables an extension to QF-Test
called the JOptionPaneResolver. This name resolver provides convenient handling of
JOptionPane dialogs. It is a standard NameResolver as explained in the technical reference manual.
It is typically sufficient to install the NameResolver once at the beginning of the test-run, e.g. directly after the Wait for client to connect node. De-installing commonly may not be necessary.
As mentioned above predefined generic components are provided within qfs.qft
which dispenses with the need of maintaining your own ones. The following figure shows
them:
|
| ![]() |
||
|
| Figure 8.20: Generic OptionPane Components in qfs.qft
| ||
You can see from the figure, that there are 5 types of option pane dialogs supported:
As an example the plain dialog component node has been opened to show its content. There are predefined nodes inside for the different possible buttons (standard and custom buttons) and labels, usually containing the message text.
In our demo test-suite StdLibDemo.qft you can find a little test for this
name resolver inside the "OptionPane" test node which exercises the two "About" Dialogs
available in the "Help" menu of the demo. You see both a test with and without the name
resolver. Please have a look at the components under "Windows and components" used for
this test. Without the name resolver installed two slightly different components need to
be maintained. When using the name resolver only one of the predefined components from
qfs.qft is needed.
Note The implementation of the name resolver described in this chapter
should be able to map most common occurrences of JOptionPane components to the predefined
components in qfs.qft. However, there may be instances of JOptionPanes with
custom components inside, resulting in separate recording of component representations.
| The SWT/FileDialog Package |
The package qfs.swt.filedialog is intended to assist in manipulating any
file dialog (the org.eclipse.swt.widgets.FileDialog SWT component).
Here is the list of available procedures within this package:
| The SWT/ColorDialog Package |
The package qfs.swt.colordialog is intended to assist in manipulating any
color dialog (the org.eclipse.swt.widgets.ColorDialog SWT component).
Here is the list of available procedures within this package:
| The SWT/DirectoryDialog Package |
The package qfs.swt.directorydialog is similar to the FileDialog package.
It is intended to assist in manipulating any directory dialog (the org.eclipse.swt.widgets.DirectoryDialog SWT component).
Here is the list of available procedures within this package:
| The SWT/Instrument Package |
The package qfs.swt.instrument provides procedures to
instrument your Eclipse/SWT application correctly.
Here is the list of available procedures within this package:
| The AWT/Menu Package |
The qfs.awt.menu package contains procedures to work with
AWT menus. AWT menus are the only AWT components, which are not
supported by QF-Test out of the box.
Here is the list of available procedures within this package:
| The Run-log Package |
The qfs.run-log package contains procedures, which writes specified messages into the run-log. This package has been introduced to give testers without scripting-knowledge the opportunity to write messages into the run-log.
Here is the list of available procedures within this package:
| The Run-log.Screenshots Package |
The qfs.run-log.screenshots package contains procedures,
which write images into the run-log and some helper methods.
Here is the list of available procedures within this package:
| The Shellutils Package |
The qfs.shellutils package contains procedures to support most common shell-commands.
Here is the list of available procedures within this package:
| The Utils Package |
The qfs.utils package contains procedures, which covers common helper-functionality during test-development.
Here is the list of available procedures within this package:
| The Database Package |
The qfs.database package contains procedures to execute
SQL commands on a database.
Please note, that the class of the database-driver must be in QF-Test's plugin directory or in the CLASSPATH before QF-Test startup.
To get more information about the connection-mechanism to your database, please ask your developers or see www.connectionstrings.com.
Here is the list of available procedures within this package:
| The Check Package |
The qfs.check package contains procedures to do checks.
Here is the list of available procedures within this package:
| The Databinder Package |
The qfs.databinder package contains procedures for execution within a "Data
driver" node which bind data for iteration.
Here is the list of available procedures within this package:
| The Web Package |
The qfs.web package contains procedures to support web-testing.
Here is the list of available procedures within this package:
| Last update: 04/23/2012 Copyright © 2002-2012 Quality First Software GmbH |