The most common use case for Squish tests is full automation—Squish is used to record a test (or we write a test manually), and then plays the test back and reports the results. But in some situations we might want to create a semi-automatic test that requires the tester to provide some input. For example, when testing some software with a hardware device we might want to ask the user who is running the test if the device's state has been changed in the expected way.
For example, imagine that we want to write tests for some printer-related software. The tests exercise the software, and one of the results should be that the printer prints a page with the text “This is a test”.
Since Squish can't verify a physical occurrence such as a page coming out of the printer with some specific text on it, any test that has such a requirement must rely on the tester to inform Squish whether the test passed or failed. The following example shows how this can be done.
![]() | Toolkit-Specific |
|---|---|
The examples in this section use the Qt and Java AWT/Swing toolkits, and so it is necessary that a Qt or Java AWT/Swing application is set as the AUT for the examples to run successfully. Furthermore, the examples depend on specific features of the toolkits themselves, so it is not possible to do similar things with other toolkits at this time. (Internally, froglogic is researching the possibility of providing a generic toolkit-agnostic message box facility to support querying for user input.) |
messageBox = QMessageBox()
if qVersion() >= "4.2.0":
messageBox.setWindowTitle("Squish - Confirm Printing")
messageBox.setText("Did the printer correctly print the test page?")
messageBox.addButton(QMessageBox.Yes)
messageBox.addButton(QMessageBox.No)
which = getattr(messageBox, "exec")() # Can't write messageBox.exec() since 'exec' is reserved
if which == QMessageBox.Yes:
test.passes("Print Test", "Test page was correctly printed.")
else:
test.fail("Print Test",
"Test page was incorrectly printed or not printed at all.")
var messageBox = new QMessageBox();
if (qVersion() >= "4.2.0")
messageBox.setWindowTitle("Squish - Confirm Printing");
messageBox.setText("Did the printer correctly print the test page?");
messageBox.addButton(QMessageBox.Yes);
messageBox.addButton(QMessageBox.No);
var which = messageBox.exec();
if (which == QMessageBox.Yes)
test.pass("Print Test", "Test page was correctly printed.");
else
test.fail("Print Test",
"Test page was incorrectly printed or not printed at all.");
my $messageBox = QMessageBox->new();
if (qVersion() ge "4.2.0") {
$messageBox->setWindowTitle("Squish - Confirm Printing");
}
$messageBox->setText("Did the printer correctly print the test page?");
$messageBox->addButton(QMessageBox::Yes);
my $yesId = 16384;
$messageBox->addButton(QMessageBox::No);
my $which = $messageBox->exec();
if ($which == $yesId) {
test::pass("Print Test", "Test page was correctly printed.");
} else {
test::fail("Print Test",
"Test page was incorrectly printed or not printed at all.");
}
set messageBox [construct QMessageBox]
if {[invoke qVersion] >= "4.2.0"} {
invoke $messageBox setWindowTitle "Squish - Confirm Printing"
}
invoke $messageBox setText "Did the printer correctly print the test page?"
invoke $messageBox addButton [enum QMessageBox Yes]
invoke $messageBox addButton [enum QMessageBox No]
set which [invoke $messageBox exec]
if {$which == [enum QMessageBox Yes]} {
test pass "Print Test" "Test page was correctly printed."
} else {
test fail "Print Test" \
"Test page was incorrectly printed or not printed at all."
}
Here we have created a QMessageBox, set its values
appropriately to our needs and then call its exec method to
pop it up. We then retrieve the user's response (a click of the Yes or
No button), and call a suitable Squish test function.
(Note that the window title is only available from Qt 4.2, so we
only use the QMessageBox.setWindowTitle method if the
version of Qt is high enough.)
We are not limited to using simple button-based dialogs if the
underlying GUI toolkit supports more. For example, the Qt toolkit has a
QInputDialog class that can be used to get integers or
floating-point values, or a string from a predefined list of strings.
pages = QInputDialog.getInteger(0, "Squish - Page Count",
"How many pages were printed?")
if pages == 0:
test.fail("Page Count", "No pages printed.")
else:
test.passes("Page Count", "%d pages printed." % pages)
var pages = QInputDialog.getInteger(0, "Squish - Page Count",
"How many pages were printed?");
if (pages == 0)
test.fail("Page Count", "No pages printed.");
else
test.pass("Page Count", pages + " pages printed.");
my $pages = QInputDialog::getInteger(0, "Squish - Page Count",
"How many pages were printed?");
if ($pages == 0) {
test::fail("Page Count", "No pages printed.");
} else {
test::pass("Page Count", "$pages pages printed.");
}
set pages [invoke QInputDialog getInteger 0 "Squish - Page Count" \
"How many pages were printed?"]
if {$pages == 0} {
test fail "Page Count" "No pages printed."
} else {
test pass "Page Count" "$pages pages printed."
}
Here we ask the user to enter the number of pages. The static
QInputDialog.getInteger function's first argument is the
parent window for which we pass 0 as a safe default. The second argument
is the dialog's window title, and the third argument the dialog's body
text.
This section again shows that using Squish's powerful script bindings to classes like QMessageBox and QInputDialog (or to the DOM/HTML, Tk, XView, or other APIs, depending on which Squish edition is being used), can be used in test scripts so that testers can be asked for input when necessary. However, asking for tester input is something to be avoided where possible, since fully automated tests are much faster and more convenient.
AnyClass = jtable.getClass()
OptionPaneClass = AnyClass.forName("javax.swing.JOptionPane")
optionPane = OptionPaneClass.newInstance()
reply = optionPane.showConfirmDialog(0, "Were 3 addresses printed?",
"Print check", optionPane.YES_NO_OPTION)
if reply == optionPane.YES_OPTION:
test.passes("Printed successfully")
else:
test.fail("Printing failed")
var AnyClass = jtable.getClass();
var OptionPaneClass = AnyClass.forName("javax.swing.JOptionPane");
var optionPane = OptionPaneClass.newInstance();
var reply = optionPane.showConfirmDialog(0,
"Were 3 addresses printed?", "Print check",
optionPane.YES_NO_OPTION);
if (reply == optionPane.YES_OPTION)
test.pass("Printed successfully");
else
test.fail("Printing failed");
set AnyClass [invoke $jtable getClass]
set OptionPaneClass [invoke $AnyClass forName \
"javax.swing.JOptionPane"]
set optionPane [invoke $OptionPaneClass newInstance]
set reply [invoke $optionPane showConfirmDialog \
0 "Were 3 addresses printed?" "Print check" \
[property get $optionPane YES_NO_OPTION]]
if {$reply == [property get $optionPane YES_OPTION]} {
test pass "Printed successfully"
} else {
test fail "Printing failed"
}
We want to prompt the user to tell us whether or not printing was
successful, and for that we need to use a confirmation dialog. The first
three lines of the code take a Java object (any
object will do) to get that object's class object. We then use the
forName method to retrieve the class object for the class
of object we want, and then use that class object's
newInstance method to get an instance that we can then use.
(See Wrapping custom Java™ classes (Section 15.3.7).)
In this case we get an optionPane instance and call its
showConfirmDialog method; naturally we could use any of the
other dialog methods if we wished.