|Creating a Generalized Procedure [30-45 min]|
In this chapter we'll show you how you can make the procedure you wrote in the last chapter even more useful. With the introduction of packages, you'll see how you can build your own utility library to serve general-purpose functions.
|Creating a Package|
As you begin to write more procedures, you'll soon find that - like important documents strewn haphazardly about your table - things become cluttered and disorderly. Like a file-folder that helps you organize your documents into different categories, a package in QF-Test helps you group together your procedures. Our definition of a package is thus simply a grouping of procedures and/or other packages. We tend to think of packages as containing similar elements. However, you can organize your packages however you see fit.
In the last chapter you wrote a checkbox utility procedure called "selectCheckbox," which allowed you to check a checkbox in the SUT. We could, however, envision other such utilities for a checkbox. What if you want to uncheck a checkbox or query whether a checkbox is greyed-out/disabled? There are any number of possibilities, fitting one general category, i.e., checkbox utilities. So let's create a package for these procedures.
Click on the "Procedures" node of your test-suite and select the »Insert«-»Procedure nodes«-»Package« menu option. This will bring up the properties dialog window in which you have to insert only a name for the package. Call it "checkbox".
|Move the Procedure|
You already created one procedure which deals with a checkbox which can now be moved into your new package. Directly use the mouse or the »Cut« and »Paste« functions to move the "selectCheckbox" procedure into the "checkbox" package. A dialog will pop up and ask whether to update all references to this node. Please select "Yes" and let "Show updated references afterwards" activated, which will give an overview of all adapted nodes. In our case it is just one procedure call.
You'll note that the name of your procedure is somewhat redundant now that it is inside the "checkbox" package. Let's change the name of the procedure from "selectCheckbox" to just "select". This is but one small advantage of package organization: anything inside of the "checkbox" package can be assumed to deal with a checkbox. Again you will be asked whether references are to be adjusted, which of course is helpful.
Here's how your test-suite should look like now:
||Figure 5.1: The Checkbox Package|
|Create the Deselect Procedure|
Our next step will be to expand the package a bit by adding another utility procedure. A sensible choice would be, of course, a "deselect" procedure which will uncheck a checkbox.
Your new "deselect" procedure will work essentially the same as "select" with only some minor changes in the logic. Let's start by just making a copy of "select" and pasting it into the "checkbox" package. Don't be concerned that you'll have two procedures with the same name in the package, you're going to fix that next.
You should now have two identical procedures in the "checkbox" package. Click on one of them to display its properties and change the name to "deselect".
The last step for this section is to change the logic so that "deselect" will now look for the unselected state of the checkbox before acting. To achieve this, you actually only need to make one change. Expand the "deselect" procedure until you locate the "Check boolean: selected" node. Recall that this is the check-node which queries the state of the checkbox. The "select" procedure was set up to throw an exception if the checkbox is not selected. We can reverse that logic now for "deselect" by simply locating the "Expected state" checkbox within the node's properties and unchecking it, as follows:
||Figure 5.2: Check for Unselected State|
Now the check-node is expecting an unselected state of the component and will throw an exception if the component is selected, which is exactly what we want. So that was it! You may want to change some of the labels and or comments within the procedure, for example the name of the "Try" node could be changed to "checkbox deselected". Here's how your new package should be shaping out:
||Figure 5.3: Checkbox Package with two Procedures|
|Call the Procedures|
In the previous chapter (refer to section 4.8) you created a call to the "selectCheckbox" procedure. Please take a look at the call procedure node now as it has been automatically adapted due to the new package structure and new name.
Calls to procedures within packages follow a syntactical rule which
references the procedure's entire hierarchy in an elegant fashion:
package.procedure - thus, your procedure call will now be
to the procedure named "checkbox.select"
NoteAccording to our definition, packages can contain
not only procedures but also other packages. If a procedure is located
within such a nested package structure, then the same rule for calling
the procedure applies as above, with as many
statements before the actual procedure name as needed. For example,
your procedure call could be to something like
menu.file.open, which implies two packages ("menu" and
"file") with the procedure named "open".
Try creating another procedure call now to the "checkbox.deselect" procedure. You should know how to do this fairly simply by now, using techniques from this tutorial.
|Creating an All-Purpose Procedure|
The two procedures you have inside the "checkbox" package now will allow you to select or deselect a checkbox separately. How would it be if we created one simple procedure which combined both functions? In this and the following sections you will create a procedure called "setState," which will set the state of a checkbox to either selected or unselected. This new procedure will include a variable that we'll call "select," which if set to 'true' will cause the procedure to select the checkbox, otherwise ("select" is 'false') the checkbox will be deselected.
Let's start by just creating the new procedure "setState" within the "checkbox" package. If you need some assistance on creating a new procedure, you can refer back to section 4.2.
|Setting a Default|
As we just mentioned, your new procedure will contain the variable "select" aiming to decide what to do with the checkbox. As with the QF-Test ID which you passed to the procedure in your procedure call, a value of "select" (either 'true' or 'false') must also be passed as an argument to "setState".
It is however customary for procedures that make use of such a variable to define a default setting for the variable. This means that passing a value of "select" to the procedure as an argument will be optional. When no value is passed, the variable will simply take on the value of the default.
Click on the "setState" procedure node to view its properties in the details window. You'll notice that included within the properties is an area to define variables. In fact, variables for a procedure are added, edited and deleted in the same way you saw back in section 4.8. In that same fashion, add the variable "select" now and give it the value of 'true.' Here's how the properties of your procedure should look:
||Figure 5.4: Default Value for Procedure Variable|
What you've just done is tell QF-Test that if it does not see a value for "select" defined when the procedure is called (i.e., it was not passed to the procedure by the procedure call), then it uses the default value. If a value is supplied as an argument passed to the procedure, then QF-Test will ignore the default and use the supplied value.
NoteFor those of you familiar with variables, you'll recognize the concept of the "scope" of a variable. A variable could be, for example, defined in one spot and then used erroneously in another if you forget that it is already defined. On this stage of test-suite development you should not run into this kind of problem, but at some point you may wish to read more about variables in the user manual.
|The If/Else Construct|
The variable "select" is intended to help us decide whether to select or deselect a checkbox. We now come to the point where we can use this variable inside of the logical if/else construct.
Using the if/else mechanism is quite easy. To start, a condition is given. If this condition evaluates to a true statement, then the nodes under the if-block are executed. Otherwise (the statement is false), the nodes under the else-block are executed.
Our condition is, of course, the value of the "select" variable. If it's set to 'true' then we select the checkbox, and so on.
Expand and click on the "setState" procedure node so that you can insert a new node as the first element of the procedure. Now select the »Insert«-»Control structures«-»If« menu option. As usual, you'll be presented with a dialog window to fill in the node's properties. For this node, you need to fill in the condition to evaluate the variable "select" precisely as shown below:
||Figure 5.5: Condition Statement for the "If" Node|
Recall that referring to a variable involves using the
syntax. The single and double quotes in the condition are QF-Test's way
of evaluating string literals. Different syntax is required for
different types of conditions, such as mathematical expressions. Refer
to the user manual's sections on variables and the If control
node for further reading.
As we stated, if the condition evaluates to true, then the nodes under the "If" node are executed. So at this point you can insert the logic that will cause the checkbox to be selected. How do you do this? There are several ways: you could, for example, copy the nodes from the "select" procedure to this part of "setState". However, we'll take the easiest route and just make a call to the "checkbox.select" procedure here. You'll find help in section 4.8 on calling a procedure.
Now we come to the "Else" portion of the construct. After the last node in your if-block (you'll have just one, but there could be more), you can insert the "Else" node using the »Insert«-»Control structures«-»Else« menu option. You are not required to fill in any additional information in the properties dialog window that appears for the "Else" node. It is automatically assumed to be the logical antithesis of the corresponding "If" node (or nodes - see the tip below).
Lastly, we complete the construct by adding the node(s) to be executed when the condition from the "If" node is not true. So here we simply insert a call to the "checkbox.deselect" procedure.
The procedure "setState" is now complete! Here's how it should look:
||Figure 5.6: The If/Else Construct|
NoteFor our example the boolean nature of the "select" variable lends itself well to a simple if/else construct. However, for other examples, such as a multi-state condition like the colors of a traffic light, you can implement the more advanced if/elseif/else construct. The concept is the same, you are just permitted now to evaluate multiple conditions. For example, your logic might run like this:
||Figure 5.7: The If/Elseif/Else Construct|
Note that the "Else" portion of the if/else or if/elseif/else construct is optional!
|Calling the All-Purpose Procedure|
Now you can try calling your new "setState" procedure. Just create a procedure call node as you did in section 4.8. You'll of course still need the QF-Test ID for the "id" value as an argument for the procedure call, but now you can also (optionally) add the second variable "select" to the call, as follows:
||Figure 5.8: Procedure Call to setState|
Note Sometimes you may want to create a procedure which returns a value,
getState procedure. For this purpose a Return node can be
used inside the procedure. The returned value may then be assigned to a global or local
variable outside the procedure, using the "Variable for return value" attribute of the
"Procedure call" node, visible in the figure above. For further information please have a
look in the reference manual.
|Documenting the Procedure|
After you have successfully completed the implementation of your procedure, we want to show
a convenient way of how to create documentation for it. For the Java programming
language there is a standard way for documenting source code - it's called
javadoc. Special tags inserted within comments in the source
code are parsed by the
javadoc tool and provided in a well structured HTML
QF-Test offers a similar mechanism to document your packages and procedures. In the following
we will show you how it is done. If you want to get a first glance, how a result may look
like, please have a look at
Now we want to start to prepare our procedure for the documentation. Please open the
"setState" procedure node if it's not still open. As you can see in figure 5.9 the procedure has two parameters. To get them documented we add two
lines in the "Comment" field of the node, starting with
@param followed by the
name of the parameter and an appropriate description.
@param is a special tag
to indicate the relation of the description to the procedure parameters. Also a general
description of the procedure can be added at the beginning of the "Comment" field. Note that
it is possible to use HTML tags for formatting text.
||Figure 5.9: Comments for Package Documentation|
Please add similar comments to your "setState" procedure now, so we can start generating the documentation.
The generation process is very easy. Just open »File«-»Create HTML/XML Pkgdoc...« from the menu.
You may confirm the upcoming dialog containing some document generation options unchanged by pressing the "OK" button. Then your default browser should appear automatically (you may have to switch to it in case it's already open an doesn't pop to the foreground) showing the following.
||Figure 5.10: The Package Documentation|
Here we see three parts in the document. The package overview, procedure overview and the detailed description of the package "checkbox". In the package "checkbox there is the procedure "setState" with its general description text and its parameters.
With the package documentation feature you can easily generate a helpful description of packages and procedures, especially if you want to provide general functionality within a kind of library. Such a library including documentation also comes with QF-Test. It is explained in detail in chapter 7.
Now you can play a little around with the documentation generation. You may e.g. add a general description to the package "checkbox" and try additional tags like @version, @author, @result, @throws. For a full list of tags please have a look at the user manual.
Note You can also use QF-Test to create the package documentation automatically in batch mode. Please see the user manual for details about the relevant command line arguments.
|Saving your Test-suite|
At this point, you are well on your way to advanced development of
test-suites. You may want to take the time now to save the work you've
done thus far on the test-suite. Saving a test-suite can be done
simply with the »File«-»Save« menu option. You can name the test-suite
as you like, but we suggest the name of
utils.qft, as we
will be referring back to and modifying this test-suite in the next
NOTE If you are evaluating QF-Test in the demo-mode, you'll not be able to save the test-suite. For a full-featured evaluation license, we refer you to the Quality First Software GmbH download page.
In the next chapter, we'll begin to explore even more capabilities of
QF-Test by making a modularized library of your
test-suite. This is, however, also a good breakpoint if you wish
to explore features of QF-Test on your own (with the help of the user
manual!) until you are ready to come back to the tutorial.
|Last update: 10/27/2017
Copyright © 2002-2017 Quality First Software GmbH