Manual | Tutorial | Standard Library | Release Notes
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
Version 4.5.0 |
| Example for WebCarConfigurator |
As this approach is quite difficult to understand just via reading,
we describe a sample implementation using the WebCarConfigurator in this
section. You can find the WebCarConfigurator test-suite at
qftest-4.5.0/demo/carconfigWeb/carconfigWeb_en.qft
.
| ![]() |
||
| Figure 46.3: WebCarConfigurator |
As stated in the previous section we need to figure out which attribute provides the required information. This information will then be used to point to a generic class of QF-Test.
| Simple class mapping |
To begin with the example, we resolve the recognition of the '-5%' button in the right bottom corner. The figure below shows our goal. On the left we find the current recording without simplification steps, on the right we see the desired recording.
|
|
||||||
| Figure 46.4: Simplification due to simple class mapping |
First you should record a simple text check or a mouse click to that
button. Then jump to the recorded components via »Locate component«. There you can see that you got a
component of the class DIV
and an empty name.
The other attributes don't provide anything useful.
Please note especially QF-Test didn't record the actual text of '-5%' in any
attribute. This means QF-Test has no good information for recognizing that
component. There is just the geometry and the structure information. Now let's
make this component more readable to us and the component
recognition more robust.
| ![]() |
||
| Figure 46.5: Recording of '-5%' button in WebCarConfigurator |
When analyzing the recorded component more in detail we
discover that there is an extra feature class
with
the value button
. Now we can assume that a button in our project
will have that particular attribute. Especially after verifying the assumption
for further buttons.
So, please insert a procedure call to
qfs.web.ajax.installCustomWebResolver
from the
standard library qfs.qft
below the Extras node.
As we detected the class
attribute contains the
class information for QF-Test. Having detected this, we can set the parameter
genericClasses
to button=Button
.
The expression button=Button
means
that any component of the class button
will be assigned a
generic class called Button
.
This will make QF-Test record the default features for
buttons when we re-record the components.
Run the procedure
qfs.web.ajax.installCustomWebResolver
and re-record the
component. You will get the following recording:
| ![]() |
||
| Figure 46.6: Recording with genericClasses in WebCarConfigurator |
As you can see you got a click on component
button-5_
. When you jump to the recorded component
you can see the class Button
has been assigned the '-5%' for the feature as well and
and we even got the extra feature
qfs:label
with that text. This
component will now be treated as button by QF-Test. Of course, you should
advise the development team to assign a dedicated ID to that
button as well.
This simple assignment of one value can be sufficient for lots of cases, especially
for buttons, menu-items or checkboxes. If your web-page doesn't contain that information
in the attribute class
, but in the attribute role
, then you need
to fill the parameter attributesToGenericClasses
with the value role=button=Button
instead of genericClasses
.
In some cases the information about the specific class will not be part of the leaf component, but
in a parent component. The next section shows how to cope with this challenge.
| Advanced class mapping |
After the simple case in the previous section we will take a look at a more complex scenario now. Let's analyze how the textfields showing the selected price information are treated, e.g. the final price textfield. Like in the previous section we need to record some mouse clicks or text checks on those textfields. Then we need to navigate to the recorded components and analyze them. The figure below shows the current situation and our goal again.
|
|
||||||
| Figure 46.7: Simplification due to advanced class mapping |
We got some SPAN
nodes recorded. Here we have no
class
attribute, but an
id
attribute assigned. So, we can
conclude that the id
is very
specific to the particular field.
When you select its parent component, which
is a TD
node, you will find a
class
attribute with the value textfield
,
which corresponds to the actual component class. When you select
that component QF-Test also highlights the entire textfield on the web-page.
So we can assume that a component with the value textfield
for the class
attribute represents a textfield from a business perspective.
| ![]() |
||
| Figure 46.8: Recording of SPAN textfields |
So, now let's extend the parameters of our procedure call of
qfs.web.ajax.installCustomWebResolver
.
We need to map the textfield
value as generic class
TextField
.
Therefore, we extend the parameter genericClasses
to
textfield=TextField,button=Button
. As you can see the
genericClasses
parameter holds a comma-separated
list.
When you delete the
previously recorded component, re-run the procedure
qfs.web.ajax.installCustomWebResolver
,
reload the web page and re-record the
component you will get the following recording:
| ![]() |
||
| Figure 46.9: Recording TextFields in WebCarConfigurator |
The textfields will be recorded as expected and we even get rid of one level in the
component hierarchy. In addition, the textfields have QF-Test specific attributes
like the extra feature qfs:label
assigned.
Note
This example uses the parameter genericClasses
like the previous one.
You can edit the values of the parameter using the 'Edit row' button of the table and
insert line-breaks after every comma to increase readability.
The next section show a translation for components which contain data and how to access that data afterwards. Such components represent data-tables, trees or lists and are handled as complex components by QF-Test.
| Mapping of complex components like data-tables |
The previously described approach will work for most standard components as buttons or checkboxes. But besides those components there are also complex components in our GUI. Those components represent data and we would like to address their content by the sub-item syntax provided by QF-Test. Those components could be tables, trees or lists. For those components we need to map the dedicated class as well as the sub-item class.
|
|
||||||
| Figure 46.10: Simplification for complex components |
Our example is the table showing the cars of the WebCarConfigurator. Again, we need to record some clicks on the shown cars and analyze the recording. The standard recording looks like this:
| ![]() |
||
| Figure 46.11: Recording of table in WebCarConfigurator |
The click was recorded on a TD
component, which
is the child of a TR
component, which is part of a
TABLE
component. The recorded
TD
component contains an extra feature
class
with the value dataCell
. The
TR
component has the value dataRow
,
and the TABLE
has the value dataTable
for that attribute.
When we select the nodes and observe the component highlighting in the SUT we notice the following:
A TD
node represents a cell, a
TR
node represents a row of a table and a
TABLE
node represents an entire table. Exactly those
nodes need to be investigated now in order to create a good
mapping to generic classes. QF-Test requires those three classes
to resolve a table, see
Mapping of complex components for details.
Let's start with the TABLE
node. This node has a
class
attribute with the value
dataTable
. This seems to be a clear sign that any
dataTable
represents a table. So we select the call
to the qfs.web.ajax.installCustomWebResolver
again
and we extend the parameter genericClasses
to
dataTable=Table,textfield=TextField,button=Button
.
The next step is the row of the table. After selecting the
TR
node we can see that there is another
class
attribute with the value
dataRow
. This seems to be a clean-cut case.
Now we need to add that value to the procedure call
of qfs.web.ajax.installCustomWebResolver
again
and we extend the parameter genericClasses
to
dataRow=TableRow,dataTable=Table,textfield=TextField,
button=Button
.
Last but not least we need to analyze the TD
node.
Suprisingly, we find another class
attribute, this time
with the value dataCell
. So, let's add this to our
procedure call as before. Now genericClasses
looks
dataCell=TableCell,dataRow=TableRow,dataTable=Table,
textfield=TextField,button=Button
.
Note that you are allowed to enter line breaks after each comma
to ensure a better readability.
We will now delete the previously recorded
components, run the
qfs.web.ajax.installCustomWebResolver
, re-load the
web-page and re-record a click again.
As result we get a click with the typical QF-Test item syntax on a
component like VehicleTable@Model&0
(or any other
row, depending what you clicked on). In the recorded
components area you will just see the Table
object and no
child component anymore
as they are now treated by QF-Test as items of a table.
| ![]() |
||
| Figure 46.12: Recording of resolved table item in WebCarConfigurator |
After resolving such a complex component we can proceed to the next section for the next steps.
| Next steps |
As shown in the previous sections our first task for testing web-projects is to figure out how QF-Test recognizes the components and to create a corresponding dictionary. This task looks rather difficult at the first glance, but its result will drastically reduce the maintenance work due to component changes or hierarchy changes in later stages of your project. This is because QF-Test uses the relevant properties of your HTML components only, and not any information available.
chapter 54 shows a full list of all generic classes for standard components and complex components like lists or trees. We recommend that you map only those components which are really required and not every existing component. It's rather simple to extend the mechanism later.
Repeating the steps of the previous example
we would now continue to map other components like menu items or tabs.
As the mapping would be too much for this manual we provided a full sample
in the demo test-suite
qftest-4.5.0/demo/carconfigWeb/carconfigWeb_de.qft
in the test-case
CarConfiguratorWeb Demo.Usage of CustomWebResolver.Create Vehicle with CustomWebResolver
.
In order to use the created dictionary at every start of your web application you should
move the procedure call to qfs.web.ajax.installCustomWebResolver
into
your Setup node directly after launching the browser.
In case you created the Setup node via the Quickstart Wizard of QF-Test you will find
a template call of the procedure in the sequence
Install CustomWebResolver
. That call can be parametrized accordingly.
| Final steps |
Besides the pure translation of web-page specifics into QF-Test classes, it's also
possible to ignore certain components during recording.
This is done via the parameters ignoreTags
and ignoreByAttributes
.
However, you should do it only after you mapped most of the business components.
Finally, we would like to show the differences in the recording of the component tree as it was originally and after implementing the custom web resolver as in the demo test-case of the demo test-suite. The figure below shows the recording without any resolvers on the left and the simplified tree on the left.
|
|
||||||
| Figure 46.13: Simplification of WebCarConfigurator demo |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | Last update: 02/13/2019 Copyright © 1999-2019 Quality First Software GmbH |