[ fromfile: unittest.xml id: testframework ]
The most common way to write testing code is to organize it in a unit-based framework. Qt 4 introduced the QTestLib framework of helper-macros and test runners to facilitate the writing of unit tests for applications and libraries that use Qt. All public methods in this framework are in the QTest namespace. The next examples use this framework.
A Test Class is a class derived from QObject, with
some private slots for one or more test functions.
A test case is a sequence of test functions to be executed.
Each test case must be in its own project with a source module that contains a QTEST_MAIN()
macro.
QTEST_MAIN()
specifies which class is the entry point of this test.
It expands to a main()
function that creates an instance and executes its private
slots in order of declaration.
Additional methods for initialization and cleanup can be supplied, initTestCase()
and
cleanupTestCase()
respectively, which get called at the begining and end of the test
case.
To demonstrate the use of QTestLib, we write a test for QCOMPARE
and QVERIFY
, two macros that are used to make assertions inside Qt test cases.
These macros can be used only in test classes, whereas Q_ASSERT
can be used anywhere.
On failures of assertions, they provide more information than Q_ASSERT
.
Any project that uses the QTestLib module must enable it in the .pro file with this line:
CONFIG += qtestlib
The first step, as shown in Example 8.5, is to define a QObject derived class that contains
the test functions.
It is necessary to include the QtTest header and to declare the test
functions as private slots
.
Example 8.5. src/libs/tests/assert/testassertequals.h
This test tries to verify all the various expression types.
Example 8.6 is the part of the
implementation that deals with bool
expressions.
Example 8.6. src/libs/tests/assert/testassertequals.cpp
[ . . . . ] void TestAssertEquals::test () { qDebug() << "Testing bools"; bool boolvalue = true; QVERIFY (1); QVERIFY (true); QVERIFY (boolvalue); qDebug () << QString ("We are in file: %1 Line: %2"). arg (__FILE__).arg (__LINE__); QCOMPARE (boolvalue, true);
Example 8.7 is the part of the implementation that deals with QString expressions.
Example 8.7. src/libs/tests/assert/testassertequals.cpp
Example 8.8 deals with QDate and QVariant expressions.
Normally, the test()
function stops at the first failure, which occurs when QVERIFY(condition)
encounters a
false condition or QCOMPARE(actual, expected)
encounters a mismatch between actual and expected.
So, we have deliberately included a QCOMPARE()
failure in Example
8.8 .
To enable the test to continue, we have preceded the deliberate failure with a QEXPECT_FAIL()
macro.
Example 8.8. src/libs/tests/assert/testassertequals.cpp
[ . . . . ] qDebug() << "Testing QDates"; QString datestr ("2010-11-21"); QDate dateobj = QDate::fromString (datestr, Qt::ISODate); QVERIFY (dateobj.isValid ()); QVariant variant (dateobj); QString message(QString ("comparing datestr: %1 dateobj: %2 variant: %3") .arg (datestr).arg (dateobj.toString ()).arg (variant.toString ())); qDebug() << message; QCOMPARE (variant, QVariant(dateobj)); QCOMPARE (QVariant(dateobj), variant); QCOMPARE (variant.toString(), datestr); QCOMPARE (datestr, variant.toString()); QEXPECT_FAIL("","Keep going!", Continue); QCOMPARE (datestr, dateobj.toString());
Example 8.9 deals with expressions
containing int
, long
, and double
items.
We have inserted two QVERIFY()
failures in Example
8.9.
We precede the first with a QEXPECT_FAIL()
macro.
We allow the second failure to stop the test.
Note the QTEST_MAIN
macro below the function definition, which generates code for an
appropriate main() function.
Example 8.9. src/libs/tests/assert/testassertequals.cpp
[ . . . . ] qDebug() << "Testing ints and doubles"; int i = 4; QCOMPARE (4, i); uint u (LONG_MAX + 1), v (u / 2); QCOMPARE (u, v * 2); double d (2. / 3.), e (d / 2); QVERIFY (d != e); QVERIFY (d == e*2); double f(1./3.); QEXPECT_FAIL("","Keep going!", Continue); QVERIFY (f * 3 == 2); qDebug() << "Testing pointers"; void *nullpointer = 0; void *nonnullpointer = &d; QVERIFY (nullpointer != 0); qDebug() << "There is one more item left in the test."; QVERIFY (nonnullpointer != 0); } // Generate a main program QTEST_MAIN(TestAssertEquals)
Example 8.10 shows the output of this test.
Note that you do not see the output of the last qDebug()
message.
Example 8.10. src/libs/tests/assert/testassert.txt
********* Start testing of TestAssertEquals *********
Config: Using QTest library 4.6.2, Qt 4.6.2
PASS : TestAssertEquals::initTestCase()
QDEBUG : TestAssertEquals::test() Testing bools
QDEBUG : TestAssertEquals::test() "We are in file:
testassertequals.cpp Line: 15"
QDEBUG : TestAssertEquals::test() Testing QStrings
QDEBUG : TestAssertEquals::test() Testing QDates
QDEBUG : TestAssertEquals::test() "comparing datestr: 2010-11-21
dateobj: Sun Nov 21 2010 variant: 2010-11-21"
XFAIL : TestAssertEquals::test() Keep going!
Loc: [testassertequals.cpp(46)]
QDEBUG : TestAssertEquals::test() Testing ints and doubles
XFAIL : TestAssertEquals::test() Keep going!
Loc: [testassertequals.cpp(59)]
QDEBUG : TestAssertEquals::test() Testing pointers
FAIL! : TestAssertEquals::test() 'nullpointer != 0' returned FALSE.
()
Loc: [testassertequals.cpp(63)]
PASS : TestAssertEquals::cleanupTestCase()
Totals: 2 passed, 1 failed, 0 skipped
********* Finished testing of TestAssertEquals *********
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |