Unit Testing with Qt Script

Qt comes with a nice tool for unit testing, called QTestLib. Inspired by QTestLib, I set out to create something similar that makes it easy to write tests in Qt Script. I've dubbed it QSTestLib. Hopefully you'll find it useful for testing scripting APIs that your application exports.

Grab QSTestLib here. The documentation is in qstestlib.qs (yes, QSTestLib itself is implemented in Qt Script :-) ). There's also an example test included (mytest.qs) that illustrates the main features.

Let's make a simple test case that contains three test functions:

var myTestCase = {
name: "My Test",

firstTest: function() {
qCompare(2+2, 4);

secondTest: function() {
qVerify("chimp" != "chump");

thirdTest: function() {
qCompare(1+2, 4);

Pass the resulting object to QTest.exec() to execute all the test functions. You will get a report like so:

********* Start testing of My Test *********
PASS : firstTest
PASS : secondTest
FAIL! : thirdTest : Compared values are not the same:
Actual: 3
Expected: 4
Loc: mytestcase.qs(13)
Totals: 2 passed, 1 failed, 0 skipped
********* Finished testing of My Test *********

The other familiar C++ QTestLib functionality (qExpectFail(), qSkip(), etc.) is present in QSTestLib too. Defining data-driven tests with QSTestLib can be done like this:

toUpperCaseTest_data: {
"foo": ["hello", "HELLO"],
"bar": ["wOrLD", "WORLD"],
"baz": ["Champ", "CHAMP"]

toUpperCaseTest: function(actual, expected) {
qCompare(actual.toUpperCase(), expected);

In this case, QSTestLib will call the toUpperCaseTest() function three times, once for each property of the corresponding data object; the value of the data property becomes the arguments passed on to the function. The name of the data property is used to identify each entry during testing (i.e. so you know which particular data set(s) caused test failures). Also, a *_data property can be a function, in which case QSTestLib will call the function and expects it to return the test data, thus capturing the behavior of the C++ QTestLib too.

One more thing worth mentioning is that QSTestLib separates the back-end -- the test logging -- into a separate interface. You can implement this interface to receive notification whenever a test event occurs (e.g. a compare failed, a test passed). The default QSTestLib logger uses the built-in print() function to generate its output, but one could for example generate, oh, let's say, some fancy XML from the test runs instead. To use a custom test logger, set your logger object as the value of the QTest.logger property before calling QTest.exec(). Details on the logger interface are found in the documentation in qstestlib.qs.

Happy unit testing to all!

Blog Topics: