The QTEST_MAIN macro creates a main function so you can only have one per application. The standard approach is to have a different executable for each unit test. This is easy to do with CMake, but more annoying with qmake. An alternative is to write your own main function that does multiple unit tests.
The code below could prove useful if you take the second path :
// header
class Test {
public:
static Test* get();
int runAll(int argc, char **argv);
private:
Test();
~Test();
QList<QObject*> m_testObjects;
};
template <class T>
class TestRegistar {
public:
inline TestRegistar(const char *name) {
T *test = new T;
test->setObjectName(name);
Test::get()->addTestObject(test);
}
};
#define TEST(T) \
static ::TestRegistar<T> _test_registar_##T(""#T);
// header
class Test {
public:
static Test* get();
int runAll(int argc, char **argv);
void addTestObject(QObject *o);
private:
Test();
~Test();
QList<QObject*> m_testObjects;
};
template <class T>
class TestRegistar {
public:
inline TestRegistar(const char *name) {
T *test = new T;
test->setObjectName(name);
Test::get()->addTestObject(test);
}
};
#define TEST(T) \
static ::TestRegistar<T> _test_registar_##T(""#T);
To copy to clipboard, switch view to plain text mode
//source
Test* Test::get() {
static Test inst;
return &inst;
}
/*!
\brief Run all unit tests
The following arguments are recognized :
<ul>
<li>--restrict : only run tests to which an option is passed
<li>@<testname>[:<option>] : pass an argument to a single test.
The test will be run with --restrict on even if the option is empty
</ul>
All other arguments are forwarded to all unit tests. Arguments passed to test
can be any of those supported by regular QtTest-based unit tests.
*/
int Test::runAll(int argc, char **argv) {
bool restrict = false;
QHash<QString, QStringList> specific;
for (int i = 0; i < argc; ++i) {
if (i && *argv[i] == '@') {
int idx = s.indexOf(':');
if (idx != -1)
specific[s.mid(1, idx - 1)] << s.mid(idx + 1);
else
specific[s.mid(1)] = specific.value(s.mid(1));
} else if (!qstrcmp(argv[i], "--restrict")) {
restrict = true;
} else {
common << s;
}
}
int ret = 0;
foreach
(QObject *o, m_testObjects
) { if (restrict && !specific.contains(o->objectName()))
continue;
args << specific.value(o->objectName());
if ((ret = QTest::qExec(o, args)))
break;
}
return ret;
}
void Test
::addTestObject(QObject *o
) { m_testObjects << o;
}
Test::Test() {
}
Test::~Test() {
qDeleteAll(m_testObjects);
}
//source
Test* Test::get() {
static Test inst;
return &inst;
}
/*!
\brief Run all unit tests
The following arguments are recognized :
<ul>
<li>--restrict : only run tests to which an option is passed
<li>@<testname>[:<option>] : pass an argument to a single test.
The test will be run with --restrict on even if the option is empty
</ul>
All other arguments are forwarded to all unit tests. Arguments passed to test
can be any of those supported by regular QtTest-based unit tests.
*/
int Test::runAll(int argc, char **argv) {
bool restrict = false;
QStringList common;
QHash<QString, QStringList> specific;
for (int i = 0; i < argc; ++i) {
QString s = QString::fromLocal8Bit(argv[i]);
if (i && *argv[i] == '@') {
int idx = s.indexOf(':');
if (idx != -1)
specific[s.mid(1, idx - 1)] << s.mid(idx + 1);
else
specific[s.mid(1)] = specific.value(s.mid(1));
} else if (!qstrcmp(argv[i], "--restrict")) {
restrict = true;
} else {
common << s;
}
}
int ret = 0;
foreach (QObject *o, m_testObjects) {
if (restrict && !specific.contains(o->objectName()))
continue;
QStringList args = common;
args << specific.value(o->objectName());
if ((ret = QTest::qExec(o, args)))
break;
}
return ret;
}
void Test::addTestObject(QObject *o) {
m_testObjects << o;
}
Test::Test() {
}
Test::~Test() {
qDeleteAll(m_testObjects);
}
To copy to clipboard, switch view to plain text mode
With that, you can register multiple unit test classes with the TEST macro and invoke them all from anywhere you fancy (but most likely from a main()) via "Test::get()->runAll(argc, argv)"
Bookmarks