Qt Test limitations and workarounds
Pros and cons
Why use Qt Test for unit testing and TDD (test-driven development)?
- small testing framework (about 6K lines of source code);
- seamless integration with QtCreator development environment;
- full support of Qt framework including classes/types and signal/slots;
- simple to start and use.
However, there are some drawbacks, too.
- designed as "single testing class per test project"; Qt developers use test project hierarchy themselves with
SUBDIRS
;
TEMPLATE = subdirs
SUBDIRS += \
test_of_unit1 \
test_of_unit2 \
...
- no mocks;
- checking functions/macros doesn't support some standard types i.e. wide strings and literals;
- Qt dependency: a test executable requires some DLL to run (
QtTest
andQtCore
at least, static linking is allowed in commercial version only).
Some of these limitation may be removed using the following workarounds.
Multiple Qt testing classes in a single project
Create test project and add new testing classes as it described in the Qt manuals.
Remove any declarations like QTEST_MAIN(MyTest1)
from testing class files.
You need to add the main C++ source file to the project, i.e. bootstrap.cpp
. Include test class files to bootstrap.cpp
and write the main function as following:
#include <QtTest>
// Testing classes
#include "MyTest1.h"
#include "MyTest2.h"
int main(int argc, char *argv[])
{
int status = 0;
QTest::setMainSourcePath(__FILE__, QT_TESTCASE_BUILDDIR);
{
MyTest1 tc;
status |= QTest::qExec(&tc, argc, argv);
}
{
MyTest2 tc;
status |= QTest::qExec(&tc, argc, argv);
}
return status;
}
From now QtCreator test explorer shows all test results.
Testing strings
QCOMPARE
doesn't seem to test wide-character literals L"Abc"
, std::wstring
and even std::string
values correctly, there is no additional information showing when a check is failed. Fortunately, you can add some simple macros to compare strings.
#define QSCOMPARE(string1, string2) {\
QByteArray ba1 = QString::fromStdString(string1).toLocal8Bit(); \
QByteArray ba2 = QString::fromStdString(string2).toLocal8Bit(); \
const char *ps1 = ba1.data(), *ps2 = ba2.data(); \
QTest::compare_helper(static_cast<bool>(string1 == string2), \
"Compared strings are not the same", \
QTest::toString(ps1), QTest::toString(ps2), \
#string1, #string2, \
__FILE__, __LINE__); \
}
//
#define QWSCOMPARE(wstring1, wstring2) {\
QByteArray ba1 = QString::fromStdWString(wstring1).toUtf8(); \
QByteArray ba2 = QString::fromStdWString(wstring2).toUtf8(); \
const char *ps1 = ba1.data(), *ps2 = ba2.data(); \
QTest::compare_helper(static_cast<bool>(wstring1 == wstring2), \
"Compared wide strings are not the same", \
QTest::toString(ps1), QTest::toString(ps2), \
#wstring1, #wstring2, \
__FILE__, __LINE__); \
}
Afterword
Being testing QtTest framework when migrating from Microsoft CppUnit one, I have realized quickly these limitations. However, my project isn't based on Qt framework so I didn't have big advantages of using QtTest even after workarounds have been found. Finally I have been starting use GoogleTest framework. On the other hand QtTest is still a good choice when you develop Qt-based applications.
blog comments powered by Disqus