Thursday 30 June 2011

What is the use of QVERIFY macro?

The QVERIFY(bool) macro is part of the QtTest module, used to verify whether a given
expression is true. If you want to associate a specific error message when the expression is
false, you can use the QVERIFY2(bool,string) macro, which prints the string when a problem
occurs.
As soon as a test macro fails, the current test case is aborted, so you don’t have to worry
about future macros failing as a result of the first problem. If you need to clean anything up,
do so in the special cleanup slot.
The first test checks that an unspecified date is invalid and a valid date is valid. So Febru-
ary 29 is valid in 1980 (a leap year), but is invalid in 1979.
Listing 16-3. Testing that the isValid method works as expected
void DateTest::testValid()
{
QDate date;
QVERIFY( !date.isValid() );
date = QDate( 1979, 5, 16 );
QVERIFY( date.isValid() );
475
476
CHAPTER 16 ■ UNIT TESTING
date = QDate( 1980, 2, 29 );
QVERIFY( date.isValid() );
date = QDate( 1979, 2, 29 );
QVERIFY( !date.isValid() );
}
It is possible to use QVERIFY to check values as well. For example, QVERIFY(x==4) checks
to see whether x equals 4. The alternative is to write QCOMPARE(x,4) instead. This uses the
QCOMPARE macro to see whether the actual value, x, equals the expected value, 4. The benefit is
that the message returned when a test fails tells you the actual and expected values.
Listing 16-4 shows the QCOMPARE macro in action. The slot shown, testAddMonths, starts by
setting a date. It then adds one month to the given date and ensures that the month part of the
date is updated correctly. It then adds 12 months to the date and sees that the year part of the
data also works.
Listing 16-4. Adding months and checking the results
void DateTest::testAddMonth()
{
QDate date( 1973, 8, 16 );
QCOMPARE( date.year(), 1973 );
QCOMPARE( date.month(), 8 );
QCOMPARE( date.day(), 16 );
QDate next = date.addMonths( 1 );
QCOMPARE( next.year(), 1973 );
QCOMPARE( next.month(), 9 );
QCOMPARE( next.day(), 16 );
next = date.addMonths( 12 );
QCOMPARE( next.year(), 1974 );
QCOMPARE( next.month(), 8 );
QCOMPARE( next.day(), 16 );
}
The testAddDays and testAddYears slots looks very much like the testAddMonths slot. The
year testing slot simply adds a number of years. This is the only test case because the number
of years added affects only the year returned. The test for adding days, however, has three
cases: adding one day (affects only the day property), adding 31 days (affects the month prop-
erty), and adding 366 days (affects the year property).
Putting It Together
The DateTest class is kept in the datetest.cpp and datetest.h files. To create an application,
you must add a main function, which is kept in the main.cpp file shown in Listing 16-5.
The QtTest header that is included first contains all the macros from the QtTest module
(including QVERIFY, QCOMPARE, and so on). The next line includes the class implementing the
actual test. The QTEST_MAIN macro then creates a main function that runs the test cases.
CHAPTER 16 ■ UNIT TESTING
Listing 16-5. The main function is implemented using the QTEST_MAIN macro.
#include <QtTest>
#include "datetest.h"
QTEST_MAIN( DateTest )
This is all referenced from a project file, which has been autogenerated through a call to
qmake –project "CONFIG+=qtestlib console". The qtestlib reference adds a reference to the
QtTest module, while console is required for Windows users. Without it, no messages are
shown. The resulting file is shown in Listing 16-6.
Listing 16-6. The project file puts it all together
######################################################################
# Automatically generated by qmake (2.01a) ti 23. jan 18:26:56 2007
######################################################################
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += datetest.h
SOURCES += datetest.cpp main.cpp
CONFIG += qtestlib console
When all files are in place, it’s then just a matter of building and executing the test.
Running the Tests
The result of building a unit test is an ordinary application. If you run that application without
any command-line arguments, it will produce something like Listing 16-7. The output shows
the version of Qt and the version of the qtestlib used, which is followed by the result of each
test case. In this case, all get a PASS, and the summary at the end shows that all tests have
passed.
■ If you want colored output, set the environment variable QTEST_COLORED to 1.
Tip
Listing 16-7. Running the test without any arguments
********* Start testing of DateTest *********
Config: Using QTest library 4.2.2, Qt 4.2.2
PASS
: DateTest::initTestCase()
PASS
: DateTest::testAddDay()
477
478
CHAPTER 16 ■ UNIT TESTING
PASS
: DateTest::testAddMonth()
PASS
: DateTest::testAddYear()
PASS
: DateTest::testValid()
PASS
: DateTest::cleanupTestCase()
Totals: 6 passed, 0 failed, 0 skipped
********* Finished testing of DateTest *********
Sometimes a test case hangs. When this occurs, it is handy to use the –v1 command-line
argument when executing the test application. When this flag is given, the output tells you
when each test is entered and passed, so you can tell where the test hangs. A snippet of an
output is shown in Listing 16-8.
Listing 16-8. Running the test with the –v1 flag
********* Start testing of DateTest *********
Config: Using QTest library 4.2.2, Qt 4.2.2
INFO
: DateTest::initTestCase() entering
PASS
: DateTest::initTestCase()
INFO
: DateTest::testAddDay() entering
PASS
: DateTest::testAddDay()
INFO
: DateTest::testAddMonth() entering
PASS
: DateTest::testAddMonth()
INFO
: DateTest::testAddYear() entering
...
If you still have a problem locating a hang or just want to make sure that all tests are
run, you can use the –v2 argument, which makes the test output when each test is entered
and passed (just as when using -v1), but it also shows when each testing macro is reached.
Listing 16-9 shows how this looks. Each macro has a line that tells you where it is located—it
reads something like this: filename.ext (line) : failure location.
Listing 16-9. Running the test with the –v2 flag
********* Start testing of DateTest *********
Config: Using QTest library 4.2.2, Qt 4.2.2
INFO
: DateTest::initTestCase() entering
PASS
: DateTest::initTestCase()
INFO
: DateTest::testAddDay() entering
INFO
: DateTest::testAddDay() COMPARE()
datetest.cpp(10) : failure location
INFO
: DateTest::testAddDay() COMPARE()
datetest.cpp(11) : failure location
INFO
: DateTest::testAddDay() COMPARE()
datetest.cpp(12) : failure location
INFO
: DateTest::testAddDay() COMPARE()
...
CHAPTER 16 ■ UNIT TESTING
When a test fails, the current test case is stopped immediately. The macro causing the fail-
ure will report what went wrong and where it is located, just as for the –v2 flag. An example of
a failure can be seen in Listing 16-10. The output is from a test being executed without any
command-line arguments.
If a test case fails, the others still run, so you can obtain a complete accounting of the test
status.
Listing 16-10. A test fails.
********* Start testing of DateTest *********
Config: Using QTest library 4.2.2, Qt 4.2.2
PASS
: DateTest::initTestCase()
PASS
: DateTest::testAddDay()
FAIL! : DateTest::testAddMonth() Compared values are not the same
Actual (next.day()): 16
Expected (15): 15
datetest.cpp(43) : failure location
PASS
: DateTest::testAddYear()
PASS
: DateTest::testValid()
PASS
: DateTest::cleanupTestCase()
Totals: 5 passed, 1 failed, 0 skipped
********* Finished testing of DateTest *********
The reason for the failure was that the expected value in the QCOMPARE macro was changed
on line 43 in datetest.cpp.
If you want to limit the tests to just one test case, you can pass the name of the slot as a
command-line argument. For example, running datetest testValid runs only the testValid
test case.



No comments:

Post a Comment