When creating reports from a run-log, or package documentation from
a test-suite, QF-Test operates in a two-step process. The first step
creates an XML document which is transformed to an HTML document in
the second step. Both transformations are done using XSLT
stylesheets.
Note The term DOM (for Document Object Model) also applies to XML
documents, not only to HTML web pages. This section is all about XML and XSLT and not
about the DOM of a web SUT.
However, XSLT stylesheets are not very useful when it comes to
parsing plain text. The 'Comment' fields of 'Test',
'Sequence', 'Package' or 'Procedure' nodes often contain some
internal structure that XSLT cannot make use of. Additionally, the
internal structures employed by users may vary, depending on the
conventions used. A typical example is the use of JavaDoc tags to
describe parameters of 'Procedure' nodes. Here's an example
'Comment' for the 'Procedure' qfs.swing.menu.select
from our standard library after the first step of the
transformation:
|
|
<comment>Select an item from a menu.
For example: for the File -> Open action, the component ID of
"File" is the menu, and the ID for "Open" is the item.
@param client The name of the SUT client.
@param menu The id of the menu.
@param item The id of menu item.</comment> |
|
|
| | Example 39.16: Example 'Comment' after first step transformation | |
It is very difficult to make use of the @param tags
with XSLT alone. This is where DOM processors enter the scene.
Between the first and second transformation, QF-Test can optionally run
an additional transformation directly on the DOM tree of the XML
document generated by the first step.
During that extra transformation, QF-Test traverses the DOM tree,
calling the registered DOM processors for each node to give them a
chance to manipulate the DOM.
Note For JDK 1.4 the XML Document Object Model
(DOM) is part of the standard API. For earlier JDK versions it is
provided by XML parser xerces (from the Apache project) which QF-Test
includes. The API documentation for the DOM is available at
http://download.oracle.com/javase/1.4.2/docs/api/org/w3c/dom/package-summary.html.
The interface that must be implemented is
de.qfs.apps.qftest.extensions.DOMProcessor. It is quite trivial:
| |
|
|
| |
Element process(Element node) |
| Returns |
An element node or null. If null is returned, the child nodes of
the node are processed normally. Otherwise, the child nodes are
not processed. If a node other than the original node is
returned, the original node is replaced with the return value.
|
| |
|
| |
In the process method, the processor is free to do
whatever it likes, as long as it constrains itself to the node
passed in and its sub-nodes. The node can be replaced simply by
returning some different element node.
Note To remove an element node from the DOM, the
DOMProcessor must be registered on an ancestor of the
node, its parent node, for example. The current node may not be
removed from the DOM in the process method.
QF-Test provides two example implementations of DOM processors. The
ParagraphProcessor is available in the misc directory for
illustration. It is used internally to break comments which contain empty lines into
paragraphs.
Also to be found in the misc directory is the
DocTagProcessor which is used to transform JavaDoc tags like
@param or @author to an XML DOM sub-tree. After processing,
the above example would look as follows:
|
|
<comment>Select an item from a menu.
For example: for the File -> Open action, the component ID of
"File" is the menu, and the ID for "Open" is the item.</comment>
<param name="client">The name of the SUT client.</param>
<param name="menu">The id of the menu.</param>
<param name="item">The id of menu item.</param> |
|
|
| | Example 39.17: Example comment after DOM processing | |
Transforming the above into useful HTML during the second stage
transformation is now straightforward.
Before a DOM processor can be used, it must be registered for the
kind of node(s) it applies to. This is done through the
DOMProcessorRegistry.
There is one DOMProcessorRegistry instance object per kind of
transformation, each identified by a string. Currently these identifiers are
"report" for report generation and "testdoc" and
"pkgdoc" for test-set and package documentation. To get hold of a
registry instance, use the static instance method:
| |
|
|
| |
DOMProcessorRegistry instance(String identifier) |
| Parameters |
identifier | The identifier for the kind of
transformation. |
| |
|
| |
The rest of the methods consist of the typical set of
register/unregister variants:
| |
|
|
| |
void registerDOMProcessor(DOMProcessor processor)
|
| Parameters |
processor | The processor to register. |
| |
void registerDOMProcessor(String node, DOMProcessor processor)
|
| Parameters |
name | The type of the node. |
processor | The processor to register. |
| |
void unregisterDOMProcessor(DOMProcessor processor)
|
| Parameters |
processor | The processor to unregister. |
| |
void unregisterDOMProcessor(String node, DOMProcessor processor)
|
| Parameters |
name | The type of the node. |
processor | The processor to unregister. |
| |
void unregisterDOMProcessors()
|
| |
|
| |
Exceptions raised during DOM processing by the
process method of a DOMProcessor are
caught and duly reported, the transformation is stopped in that
case.