How to run multiple QTest classes?

I have a subproject in which I put all my QTest tags and create a standalone test application that runs tests (i.e., run it from Qt Creator). I have several test classes that I can execute with qExec() . However, I do not know what the correct way to execute multiple test classes is.

I am currently doing it this way (MVCE):

tests.pro

 QT -= gui QT += core \ testlib CONFIG += console CONFIG -= app_bundle TEMPLATE = app TARGET = testrunner HEADERS += test_foo.h SOURCES += main.cpp 

main.cpp

 #include <QtTest> #include <QCoreApplication> #include "test_foo.h" int main(int argc, char** argv) { QCoreApplication app(argc, argv); TestFooClass testFoo; TestBarClass testBar; // NOTE THIS LINE IN PARTICULAR. return QTest::qExec(&testFoo, argc, argv) || QTest::qExec(&testBar, argc, argv); } 

test_foo.h

 #include <QtTest> class TestFooClass: public QObject { Q_OBJECT private slots: void test_func_foo() {}; }; class TestBarClass: public QObject { Q_OBJECT private slots: void test_func_bar() {}; }; 

However, the documentation for qExec() says this is the wrong way:

For stand-alone test applications, this function cannot be called more than once, since the command line parameters for registering test output in files and executing individual test functions will behave incorrectly.

Another significant drawback is that there is no single summary for all test classes , only for individual classes. This is a problem when I have dozens of classes, each of which has dozens of tests. To check if all the tests passed, I have to scroll up to see all the β€œResults” of what passed / failed for each class, for example:

 ********* Start testing of TestFooClass ********* PASS : TestFooClass::initTestCase() PASS : TestFooClass::test_func_foo() PASS : TestFooClass::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted ********* Finished testing of TestFooClass ********* ********* Start testing of TestBarClass ********* PASS : TestBarClass::initTestCase() PASS : TestBarClass::test_func_bar() PASS : TestBarClass::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted ********* Finished testing of TestBarClass ********* 

I am also surprised that my qExec() || qExec() qExec() || qExec() works, given that the documentation says that if the qExec() test fails, it returns a non-zero value, which should mean that all of the following qExec() calls will not be executed, but this does not seem to be the case.

What is the correct way to run multiple test classes? And so I can immediately see if any of the hundreds of unit tests I failed.

+7
c ++ unit-testing qt qtestlib
source share
1 answer

I once found a nice solution using a simple Qt project ( no TEMPLATE = subdirs ) that uses a macro to create the main function and automatically register all test classes (the macro too) with just a simple auxiliary header file.

Here is a test class example (only the corresponding header file):

 #ifndef FOOTESTS_H #define FOOTESTS_H #include "AutoTest.h" class FooTests : public QObject { Q_OBJECT private slots: void initTestCase(); void test1(); void test2(); void cleanupTestCase(); }; DECLARE_TEST(FooTests) #endif // FOOTESTS_H 

and the main one, which consumes each test class created in this way:

 #include "AutoTest.h" TEST_MAIN 

Code AutoTest.h :

 #ifndef AUTOTEST_H #define AUTOTEST_H #include <QTest> #include <QList> #include <QString> #include <QSharedPointer> namespace AutoTest { typedef QList<QObject*> TestList; inline TestList& testList() { static TestList list; return list; } inline bool findObject(QObject* object) { TestList& list = testList(); if (list.contains(object)) { return true; } foreach (QObject* test, list) { if (test->objectName() == object->objectName()) { return true; } } return false; } inline void addTest(QObject* object) { TestList& list = testList(); if (!findObject(object)) { list.append(object); } } inline int run(int argc, char *argv[]) { int ret = 0; foreach (QObject* test, testList()) { ret += QTest::qExec(test, argc, argv); } return ret; } } template <class T> class Test { public: QSharedPointer<T> child; Test(const QString& name) : child(new T) { child->setObjectName(name); AutoTest::addTest(child.data()); } }; #define DECLARE_TEST(className) static Test<className> t(#className); #define TEST_MAIN \ int main(int argc, char *argv[]) \ { \ return AutoTest::run(argc, argv); \ } #endif // AUTOTEST_H 

All loans are transferred to Rob Caldecott .

+4
source share

All Articles