[ 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.6, 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.6. src/libs/tests/assert/testassertequals.h
[ . . . . ] #include <QtTest> class TestAssertEquals:public QObject { Q_OBJECT private slots: void test (); }; [ . . . . ]
<include src="src/libs/tests/assert/testassertequals.h" href="src/libs/tests/assert/testassertequals.h" id="testclass-h" mode="cpp"/>
This test tries to verify all the various expression types.
Example 8.7 is the part of the implementation that deals with bool
expressions.
Example 8.7. 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);
<include src="src/libs/tests/assert/testassertequals.cpp" mode="cpp" href="src/libs/tests/assert/testassertequals.cpp" id="testclass-cpp1" segid="testbools"/>
Example 8.8 is the part of the implementation that deals with QString expressions.
Example 8.8. src/libs/tests/assert/testassertequals.cpp
[ . . . . ] qDebug() << "Testing QStrings"; QString string1 = "apples"; QString string2 = "oranges"; QString string3 = "apples"; QCOMPARE ("apples", "apples"); QCOMPARE (string1, QString("apples")); QCOMPARE (QString("oranges"), string2); QCOMPARE (string1, string3); QVERIFY (string2 != string3);
<include src="src/libs/tests/assert/testassertequals.cpp" mode="cpp" href="src/libs/tests/assert/testassertequals.cpp" id="testclass-cpp2" segid="testQstrings"/>
Example 8.9 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.9 .
To enable the test to continue, we have preceded the deliberate failure with a QEXPECT_FAIL()
macro.
Example 8.9. 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());
<include src="src/libs/tests/assert/testassertequals.cpp" mode="cpp" href="src/libs/tests/assert/testassertequals.cpp" id="testclass-cpp3" segid="testQDates"/>
Example 8.10 deals with expressions containing int
, long
, and double
items.
We have inserted two QVERIFY()
failures in Example 8.10.
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.10. 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)
<include src="src/libs/tests/assert/testassertequals.cpp" mode="cpp" href="src/libs/tests/assert/testassertequals.cpp" id="testclass-cpp4" segid="testnums"/>
Example 8.11 shows the output of this test.
Note that you do not see the output of the last qDebug()
message.
Example 8.11. 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 *********
<include src="src/libs/tests/assert/testassert.txt" href="src/libs/tests/assert/testassert.txt" id="testoutput" mode="text"/>
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |