|Writing a Procedure [30-45 min]|
In this and the following chapter we begin to explore some of the more advanced concepts of QF-Test by using a hands-on approach that will give you a good overview. We'll introduce (among other things) the important and useful concept of procedures within QF-Test. Along the way you'll pick up other insights that should prove helpful for developing your own test-suites.
As a start you'll create a simple procedure that will select a checkbox within the SUT client.
|Getting Started with a New Suite|
At this stage in the tutorial, you are ready to create your own test-suite which you will use to build upon in successive steps. From the QF-Test menu, select the »File«-»New Test-suite...« option.
NoteAs you've indubitably seen throughout this tutorial, shortcut keys are available for most menu options. The shortcut keys are a quick way to perform useful operations with a simple tap on the keyboard. The »File«-»New Test-suite...« menu option, for example, can also be done with the [Control-N] shortcut. You'll see shortcuts listed beside most menu options in QF-Test, but many other shortcuts are available that are not immediately obvious from the GUI. For a complete list, refer to the Keyboard shortcuts section of the user manual. You can also find a little helper there for attaching to your keyboard which shows the function key assignment of QF-Test.
A test-suite, of course, needs an SUT client to test with. The Options demo, which you are most likely familiar with from earlier chapters of the tutorial, is a very simple application ideally suited for our needs as an SUT. Our next step is to establish this application as an SUT client for your new test-suite.
To get the Options demo setup as the SUT for the test-suite, you'll
need to create a Setup node which will launch the application and
establish the link between the application and QF-Test. For this step,
you can simply copy the logic from
Options.qft and use it
in your new test-suite. To do this, open up
(refer to chapter 1 if you're not familiar with
this test-suite) and expand the "Test-set: Options" node. The first
visible node will be the "Setup: Start the application" node. Click on this
node and copy it with »Edit«-»Copy«.
Now return to your new test-suite. You'll need to expand the "Test-case" node so that an insertion is possible, then you can paste the copied node in with »Edit«-»Paste«.
A Cleanup node is usually associated with a Setup node and is used to
undo the steps performed by the Setup. In this case, we want the
Cleanup node that will stop the SUT application. From the
Options.qft suite, copy the "Cleanup:
Stop the application" node and paste it into your new test-suite right
after your Setup node.
There's one other step you need to do before this section is complete:
copy the windows and components from
Options.qft to your
new suite. The reason for this step may not be immediately apparent to
you at this stage, but we will get into a more detailed discussion of
components in a later section. For now it suffices to say that the
component descriptions stored under the "Windows and components"
section of a test-suite are the way that QF-Test recognizes elements such
as menus and buttons in an SUT. Simply expand the "Windows and
components" node of
Options.qft, select the nodes you see
there and then use the »Copy« and »Paste« functions to copy them into the same node of your new
test-suite. If you get confused, you can refer to the diagram below to
see how things should look.
||Figure 4.1: Skeleton for new Test-suite|
At this point, you've created a working skeleton for your test-suite that we'll populate in later sections with various procedures and tests.
For now, you can get the SUT running by selecting the the Setup node and clicking the replay button. Once the SUT is up and running, bring up it's window and select the "Miscellaneous" node in the "Preferences" tree. This will bring up several miscellaneous options for the demo, among which is a checkbox labeled simply "A BooleanOption" as such:
||Figure 4.2: Checkbox within the Miscellaneous Options of the SUT|
This is the checkbox that you will be manipulating with your new procedure in the next few sections.
|Create the Procedure|
Being a programming construct, a procedure is typically defined as a method used to accomplish a repetitive task - such as opening a window or checking if a certain key was pressed. For this part of the tutorial you will be creating a procedure that selects a checkbox within the SUT.
First, expand the Procedures node within your new test-suite.
NoteQF-Test gives you good visual clues as to whether a node is collapsed or expanded. For example, the Procedures icon changes from (collapsed) to (expanded).
Now click on the Procedures node so that is selected, and select the »Insert«-»Procedure nodes«-»Procedure« menu option.
A new dialog window should appear, allowing you to enter the description of the new procedure. Give it the name "selectCheckbox" and hit the OK button. Here's how the test-suite should look after adding your first procedure:
||Figure 4.3: Adding a Procedure|
NoteProperties of a node within QF-Test (such as the name of the procedure) can be changed simply by clicking on the node and then editing these properties in the details window, or by right-clicking on the node and selecting »Edit...«. In either case, you'll need to hit the OK button to confirm any changes you've made.
|Add a Check Node|
We're now ready to start adding some real substance to the procedure. But first consider how you might proceed in setting the checkbox. One of the first steps we'll need to perform is checking the state of the checkbox before we attempt to set it. In case it is already checked, there is nothing to do but leave it this way. Otherwise (it is unchecked), we can go ahead and set it.
Such checks are done in QF-Test with so-called "check-nodes," which allow you to perform various types of queries about the state of elements within the SUT. The one we'll start with is called the "Check boolean: selected" check-node. As its name implies, it simply queries the state of a component to see if it is selected or not.
You've hopefully already had some experience with check-nodes from the previous chapter in this tutorial. If not, it might be helpful to refer back to section 2.5 now. To add the "Check boolean: selected" node, you will now perform similar steps.
First bring up the SUT window and select the "Miscellaneous" node in the "Preferences" tree as we showed in figure 4.2. This will allow you to easily get to the correct component once you start recording. Now return to your test-suite and click the record-check button and then return to the window of the SUT. As before, when you move the mouse over the various components, they invert their color, which indicates selection. Select the "BooleanOption" checkbox which we identified earlier and right-click it. The pop-up menu which appears contains, in addition to the various types of checks we saw in the previous example, an option for "selected state," as shown in the figure below.
||Figure 4.4: Recording the "Check boolean: selected" Node|
Choose the "selected state" option, return to your test-suite and stop recording with the stop button.
QF-Test will place the recorded sequence within the "Extras" node of your test-suite, which will be immediately visible after you stop recording. If you expand the recorded sequence, you'll see that our "Check boolean: selected" node is there. This node must now be transferred from its current location to your procedure. You can transfer either just the node itself, or the entire recorded sequence. Since there is only one child-node inside sequence, the difference is purely aesthetic.
Do this using the »Copy« or »Cut« function and then the »Paste« function to place it inside your procedure. Make sure to expand the "selectCheckbox" procedure node before pasting the copied node, otherwise it will not be properly placed within the procedure, as shown in the figure below.
||Figure 4.5: A 'Check boolean: selected' Node within the Procedure|
NoteQF-Test provides a feature which allows you to directly insert a recorded sequence at a selected location, thus saving the work with cutting and pasting. Select the »Edit«-»Options« menu option. From within this window select the "Record" node to bring up the recording options, then tick the checkbox "Insert recording at current selection."
Now give it a try! Select your procedure and click the replay button. Not much happens at this point, but the lower status bar indicates the procedure completed successfully. The first step is complete.
Before we continue, it might be helpful to give you some brief background information about checks and components which may not be immediately evident from the exposure you've had to them in the tutorial thus far.
A component is simply an element of the SUT, such as a button, a menu, or (as in our case) a checkbox. Each component should have a unique 'QF-Test ID', which is registered within your test-suite, so that QF-Test can find the component when executing the test-suite.
If you click on the "Check boolean: selected" node which you recorded in the previous section, you will see its properties appear in the details window on the right. Among these properties is a field called 'QF-Test component ID' which should be filled in with the identity of the checkbox we identified in figure 4.2. You'll see that this component has been given the QF-Test ID of "CheckBox-boolean2".
This QF-Test ID is in and of itself just a name, a handy way for you and QF-Test to reference the same component. These QF-Test IDs are defined within the "Windows and components" section of your test-suite whenever you record something from the SUT. If you expand all the nodes within this section, as shown in the figure below, you'll eventually find the component we recorded for "Check boolean: selected".
||Figure 4.6: The Checkbox omponent within the component tree|
NoteAn easy way to locate a component is to use QF-Test's locate-component feature. Bring up the popup menu by right-clicking the "Check boolean: selected" node and select "Locate component" or simply select the node and press [Control-W]. This will take you right to the 'Component' node for the check. Pressing [Control-Backspace] will take you back to the check node.
Go ahead an click on the node with the "CheckBox-boolean2" QF-Test ID. You'll see a bit about how QF-Test internally identifies components.
Component recognition within QF-Test is a complex subject, and we will not dwell on it further than the overview just given. For more details about components, please refer to the QF-Test user manual.
|The Try/Catch Mechanism|
But what happens if our checkbox component is not checked? Uncheck the checkbox now and replay the procedure. You should see a message like this come up when the procedure completes:
||Figure 4.7: 'Check boolean: selected' Error|
The error occurred because your "Check boolean: selected" node was expecting the checkbox to be checked.
Click on the your "Check boolean: selected" node again so that you can view its properties in the details window. Within these details, you'll see fields marked "error level of message" and a checkbox to "Throw exception on failure". Using these properties, you can modify the action that QF-Test will take when a check fails. Let's change these settings and observe the results after replaying your procedure.
Ultimately, we want this check to throw an exception when it fails. This will provide an opportunity introduce the very useful try/catch mechanism. Set the "Throw exception on failure" checkbox in the properties as seen below:
||Figure 4.8: Throw Exception on Failure|
The try/catch mechanism is a common technique used by most programming languages to handle exceptions (i.e. unexpected conditions) when they occur. The concept is simple: 'try' to perform some action; if an exception occurs during the action, then 'catch' it and perform some other sequence of operations. If you're not familiar with this construct, don't worry - it will be come clear enough once you see it in action.
Insert a "Try" node right at the beginning of your procedure. To do this, click on the procedure node (the insertion point always is right after the node that is selected), then select the »Insert«-»Control structures«-»Try« menu option. A dialog will appear for you to enter the properties of the node. For this node, you're not required to fill in any of the fields, however, for readability, it is sometimes helpful to enter a name. We wrote "checkbox selected".
Expand the "Try" node so that you can insert nodes inside of it. All actions taken within this "Try" block can potentially be caught by a "Catch" node if an exception arises (which will be explained shortly). Thus, we now want to insert the action that we want to "Try" - which is our "Check boolean: selected" node. This node should still be in your procedure, but probably not in the right spot. Use the »Cut« and »Paste« functions to insert this check-node immediately after your "Try" node.
A "Try" node is useless without "Catch", so this is the next step. Insert a "Catch" node after your check-node (but still within the overall "Try" block) with »Insert«-»Control structures«-»Catch«. Again, a dialog window will appear for you to fill in the properties of the node. For the "Catch" node, you do need to define what type of exception should be caught. The first field is labeled "exception class," which contains a list of all possible exceptions. Select "CheckFailedException".
||Figure 4.9: Selecting an Exception to Catch|
The try/catch mechanism is meant to be a deterministic construct. That is, the exception (or exceptions) to be caught relate directly to the actions undertaken in the "Try" block. In our case, our "Try" block will contain a check-node to "Check boolean: selected," so the exception to be caught is the "CheckFailedException". This, of course, may not be immediately evident to you when implementing the try/catch mechanism. If you're not certain about what kind of exception it is that is being thrown that you need to catch, the run-log can prove useful. Try replaying your procedure again. Don't worry that the try/catch nodes are not complete. Of importance is that the "Check boolean: selected" node is still present and has its "Throw exception on failure" property set. Afterwards, open the »Run« menu and select the most recent run log (the most recent is always in position "1"). Scan through the run log and expand the nodes. You should then eventually see the logged item containing the thrown exception, as follows:
||Figure 4.10: CheckFailedException in the Run-Log|
NoteFor more information about exceptions and a complete list of possible exceptions, see the user manual.
At this stage your procedure should now look something like this:
||Figure 4.11: Procedure with Try/Catch|
NoteLet QF-Test help you out if you have questions about a certain node: just right-click on a node you would like help with and pick the "What's this?" option from the pop-up menu - QF-Test will take you right to its description in the user manual.
|Complete the Selection Logic|
Your try/catch nodes are in place, the only step left is to complete the actions that will take place if the "CheckFailedException" is thrown and caught. Recall that the exception will be thrown if the check fails, i.e., if the checkbox is not set. Thus the action we will want to take if the exception is caught is to set the checkbox.
Here's where we get to record another sequence from the SUT. Click the button and bring up the SUT window. The only thing we want to record is a click on the "BooleanOption" checkbox. So click on the checkbox now and change the state from set to unset, or vice-versa (it doesn't matter, we just want to record the state change). Now return to your test-suite and click the button. After stopping recording, QF-Test will place the recorded sequence inside the "Extras" section of your test-suite. If you take a look now inside the recorded sequence, you'll see a "Mouse click" node. If you take a look at the node's properties, you'll see several familiar items such as the QF-Test component ID of the checkbox.
NoteYou're not required to make changes to the properties of this node, but adding a comment within it can sometime be helpful. Comments have no affect on the test, they aid only in the readability of the test-suite.
As we did previously when using a recorded node, you'll need to move this "Mouse click" node from "Extras" to your procedure using the »Copy«/»Cut« and »Paste« functions. Expand the "Catch" node within your procedure and insert the new node after it. Your procedure should now look as follows:
||Figure 4.12: Procedure with Completed Try/Catch Mechanism|
Your procedure is now a complete, functional unit. Click on the procedure node and try running it a few times using the replay button, in between changing the state of the checkbox within the SUT so that you can see the two different logic paths being executed. Using the Step-In function of the debugger (see chapter 3) to step through your procedure is an excellent way to see exactly how the try/catch mechanism is functioning.
Just a small remark: A library which contains a set of such useful utility procedures like "selectCheckbox" is part of your QF-Test distribution. This standard library is discussed in detail in chapter 7. However, we would like to spend a bit more time on improving our procedure first.
|Making the Procedure More Usable|
We're going to make one last improvement to the procedure before wrapping up this chapter of the tutorial, something which may have already occurred to you. The problem with this procedure is that it works for only one specific checkbox. What if the SUT had more than one checkbox that we want to set? Would we write separate procedures for each individual checkbox?
The solution comes to us by way of variables. A variable can be used to substitute the 'QF-Test component ID' attribute of the checkbox so that the procedure can be used for any checkbox within the SUT.
Variable syntax in QF-Test, as with any computer program, is quite
specific. A variable is defined simply with a name. However, when
referring to a variable, the required syntax is:
$(name) - you'll
learn more about this in the following sections.
Let's replace references in the procedure to the specific checkbox
with a variable now. Call the variable
$(id) for example. Note that
there are two references to the checkbox component, one in the "Check
boolean: selected" node, the other in the "Mouse click" node. To make the
replacement, simply bring up the node's properties and locate the
'QF-Test component ID' field. Replace the text
$(id). The procedure should now look as follows:
||Figure 4.13: Variable Replacing Fixed Component|
|Calling the Procedure|
If you attempt to replay the procedure now, you'll get an error indicating that "The variable 'id' was not bound". This is QF-Test's way of letting you know that there is no value set for the variable.
So how do you set a value for the variable? For the example we are using, the most common and useful way is to 'call' the procedure with a specific value for the variable. In technical terms this is referred to as 'passing an argument (or parameter)' to a procedure.
Let's insert a call to the procedure now. We'll return to the main "Test-set" node of your test-suite. Collapse the "Setup" node so that you can insert a node after it. Then we first need a "Test-case" node by »Insert«-»Test and sequence nodes«-»Test-case« for which you can assign an arbitrary name. After expanding the "Test-case" we can create the procedure call either by »Insert«-»Procedure nodes«-»Procedure call« menu option or by pressing [Ctrl-A]. As usual, a dialog window will appear for you to fill in properties of the node. For this procedure-call node, you'll need to fill in a few things. First enter the name of the procedure in the first filled, which is the "selectCheckbox" procedure.
NoteThe third and possibly simplest way is to use drag and drop. When dragging the "selectCheckbox" procedure node from the procedures up into the "Test-case", the node is automatically converted into a "Procedure call" (as "Procedure" nodes are not allowed here). You will get the same effect when copying the procedure node e.g. by [Ctrl-C] and paste it into the "Test-case" by [Ctrl-V].
Next we want to add the variable that will be passed as an argument to the procedure. This
is accomplished with the "Variables" table that appears after the procedure name in the
properties window. Click on the first icon for this table
to add a new row. You'll see a new dialog window appear called "Edit table row" which
allows you to make a new entry. Within this window, enter
id as name and
CheckBox-boolean2 as value. When you're done,
the completed properties for the procedure call should look like this:
||Figure 4.14: Properties of a Procedure Call|
NoteAside from the icons which serve as functions for adding, editing and removing elements in the variable list for the procedure call, you'll notice another icon in the above image: the small yellow and red button located after the "Procedure name" field. This icon is used to bring up a very helpful list of procedures located within your test-suite, in case you cannot immediately recall what the procedure is named. In the last that appears, locate the the "selectCheckbox" procedure and hit OK. QF-Test will automatically fill in the name for you in the properties.
Once the properties for the procedure call are completed, click OK to complete the node. You can now select the new node and click the replay button. You'll see that the call now passes the QF-Test ID of our checkbox to the procedure so that "selectCheckbox" can work properly. If the SUT had multiple checkboxes, you could now add several calls to "selectCheckbox," each with a different QF-Test component ID as the argument to the procedure!
In case you attempt to run the complete test-suite you will be prompted with an error
message (Components not found) indicating that the target component
Checkbox-boolean2 could not be determined. This issue will be handled in
Chapter 7.3 so you could skip this section, but we can also tackle the problem here for
practicing purpose and better understanding. You might want to have a look into the
run-log, especially the included screenshot will prove helpful.
As you can see, the problem happens due to the fact that there is no such component on the start window of the Option demo. First of all we need to record a sequence that expands the "Miscellaneous" item. You should be able to manage that easily (open the SUT, click the "Start recording" button, click on the "Miscellaneous" node and click "Stop recording"). Now where do we insert this sequence in our test-suite? Intuitively you might be inclined to place it above the procedure calls, but then a test run would come up with the very same error message. A look at the run log shows you why - because each sequence between "Setup: Start the application" and "Cleanup: Stop the application" will include a new start AND a stop of the SUT.
So in order to achieve that desired state of the SUT for all test cases, you are bound to include this sequence in the Setup itself. Alternatively you could create a new sequence to include the recorded mouse-click and the procedure call (in case only this procedure is meant to start in the given state).
|Last update: 10/27/2017
Copyright © 2002-2017 Quality First Software GmbH