Как запустить несколько классов QTest?

У меня есть подпроект, куда я положил все своиQTest модульные тесты и создание автономного тестового приложения, которое запускает тесты (т.е. я запускаю его из Qt Creator). У меня есть несколько тестовых классов, которые я могу выполнить сqExec(), Однако я не знаю, как правильно выполнять несколько тестовых классов.

В настоящее время я делаю это таким образом (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() {};
};

Тем не менеедокументация дляqExec() говорит, что это неправильный путь:

Для автономных тестовых приложений эту функцию не следует вызывать более одного раза, поскольку параметры командной строки для записи результатов теста в файлы и выполнения отдельных функций теста будут работать неправильно.

Другим важным недостатком является то, что естьнет единого резюме для всех тестовых классовТолько для индивидуальных занятий. Это проблема, когда у меня есть десятки классов, в каждом из которых есть десятки тестов. Чтобы проверить, все ли тесты пройдены, мне нужно прокрутить вверх, чтобы увидеть все «итоги» того, что было пройдено / не пройдено в каждом классе, например:

********* 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 *********

Я тоже удивленqExec() || qExec() работает, учитывая, чтодокументация говорит, что если тест не пройденqExec() возвращает ненулевое значение, которое должно означать все следующиеqExec() звонки не будут происходить, но, похоже, это не так.

Как правильно запустить несколько тестовых классов? И так, чтобы я мог сразу увидеть, провалился ли какой-либо из сотен модульных тестов, которые у меня были.

 sigy20 окт. 2016 г., 12:07
Достигли ли вы прогресса в этой проблеме? Лучшее, что я смог найти, этоответ на аналогичный вопрос.
 DBedrenko20 окт. 2016 г., 14:10
@sigy Решения либо 1) Ребята из #qt сказали мне, что правильный способ - это иметь 1 тестовый проект на тестовый класс (вы можете поместить их вTEMPLATE = subdirs). Затем testrunner объединяет результаты теста. 2) Используйте GoogleTest, который превосходит во многих отношениях.

Ответы на вопрос(1)

решение используя простой проект Qt (нет TEMPLATE = subdirs) который используетмакро подход для создания основной функции и автоматической регистрации всех тестовых классов (макростоже) только с простым вспомогательным заголовочным файлом.

Вот пример тестового класса (только соответствующий заголовочный файл):

#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

и основной, который потребляет каждый тестовый класс, созданный таким образом:

#include "AutoTest.h"

TEST_MAIN

Код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

Все кредиты идут вРоб Калдекотт.

 x29a04 янв. 2018 г., 18:58
Я должен был добавитьQApplication app(argc, argv); кTEST_MAIN Макро (как в оригиналеQTEST_MAIN Макро строка 263), поэтому цель не показывает справку командной строки

Ваш ответ на вопрос