QTEST_MAIN перенаправляет в QTEST_MAIN_IMPL:
#define QTEST_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
QTEST_MAIN_IMPL(TestObject) \
}
Этот QTEST_MAIN_IMPL отличается в зависимости от того, какое QApplication вам нужно (Widgets, Gui или Core). Для виджетов это выглядит так:
#define QTEST_MAIN_IMPL(TestObject) \
TESTLIB_SELFCOVERAGE_START(#TestObject) \
QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \
QApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
QTEST_DISABLE_KEYPAD_NAVIGATION \
TestObject tc; \
QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv);
QTest :: qExe c определено qtestcase. cpp:
int QTest::qExec(QObject *testObject, int argc, char **argv)
{
qInit(testObject, argc, argv);
int ret = qRun();
qCleanup();
return ret;
}
В qInit (), установлен currentTestObject.
В qRun () создан экземпляр TestMethods , и в его конструкторе мы находим этот l oop:
const QMetaObject *metaObject = o->metaObject();
const int count = metaObject->methodCount();
m_methods.reserve(count);
for (int i = 0; i < count; ++i) {
const QMetaMethod me = metaObject->method(i);
if (isValidSlot(me))
m_methods.push_back(me);
}
isValidSlot () реализован следующим образом:
static bool isValidSlot(const QMetaMethod &sl)
{
if (sl.access() != QMetaMethod::Private || sl.parameterCount() != 0
|| sl.returnType() != QMetaType::Void || sl.methodType() != QMetaMethod::Slot)
return false;
const QByteArray name = sl.name();
return !(name.isEmpty() || name.endsWith("_data")
|| name == "initTestCase" || name == "cleanupTestCase"
|| name == "init" || name == "cleanup");
}
Наконец, TestMethods :: invokeMethod () is Вызванный, который явно проверяет сначала initTestCase
и запускает его:
QTestResult::setCurrentTestFunction("initTestCase");
if (m_initTestCaseDataMethod.isValid())
m_initTestCaseDataMethod.invoke(testObject, Qt::DirectConnection);
Аналогично, он проверяет cleanupTestCase
в конце.