C++ 如何运行多个QTest类?

C++ 如何运行多个QTest类?,c++,qt,unit-testing,qtestlib,C++,Qt,Unit Testing,Qtestlib,我有一个子项目,我将所有的QTest单元测试放在其中,并构建一个运行测试的独立测试应用程序(即,我从Qt Creator中运行它)。我可以使用qExec()执行多个测试类。但是,我不知道执行多个测试类的正确方法是什么 目前我是这样做的(MVCE): tests.pro main.cpp 考虑到says if a test failedqExec()返回一个非零值,这意味着下面所有的qExec()调用都不会发生,我的qExec()也很惊讶 运行多个测试类的正确方法是什么?这样我就可以一目了然地看到

我有一个子项目,我将所有的
QTest
单元测试放在其中,并构建一个运行测试的独立测试应用程序(即,我从Qt Creator中运行它)。我可以使用
qExec()
执行多个测试类。但是,我不知道执行多个测试类的正确方法是什么

目前我是这样做的(MVCE):

tests.pro main.cpp 考虑到says if a test failed
qExec()
返回一个非零值,这意味着下面所有的
qExec()
调用都不会发生,我的
qExec()
也很惊讶

运行多个测试类的正确方法是什么?这样我就可以一目了然地看到我所做的数百个单元测试中是否有任何一个失败了。

我曾经发现一个很好的方法,它使用一个普通的Qt项目(no
TEMPLATE=subdirs
),该项目使用宏方法来创建主函数并自动注册所有测试类(也是宏)只有一个简单的助手头文件

下面是一个示例测试类(仅相关头文件):

还有main,它使用以这种方式创建的每个测试类:

#include "AutoTest.h"

TEST_MAIN
自动测试.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
\ifndef自动测试
#定义自动测试
#包括
#包括
#包括
#包括
命名空间自动测试
{
typedef-QList测试列表;
内联TestList&TestList()
{
静态测试列表;
退货清单;
}
内联布尔findObject(QObject*object)
{
TestList&list=TestList();
if(list.contains(object))
{
返回true;
}
foreach(QObject*测试,列表)
{
如果(测试->对象名()==对象->对象名())
{
返回true;
}
}
返回false;
}
内联void addTest(QObject*object)
{
TestList&list=TestList();
如果(!findObject(对象))
{
列表。追加(对象);
}
}
内联int运行(int-argc,char*argv[])
{
int-ret=0;
foreach(QObject*test,testList())
{
ret+=QTest::qExec(测试,argc,argv);
}
返回ret;
}
}
模板
课堂测试
{
公众:
QSharedPointer子代;
测试(常量字符串和名称):子级(新T)
{
child->setObjectName(名称);
自动测试::addTest(child.data());
}
};
#定义DECLARE_TEST(className)静态测试t(#className);
#定义测试单元MAIN\
int main(int argc,char*argv[])\
{ \
返回自动测试::运行(argc、argv)\
}
#endif//自动测试

所有学分归。

您在这个问题上有什么进展吗?到目前为止,我能找到的最好的解决方案是:@sigy解决方案要么是1)qt中的人告诉我正确的方法是每个测试类有一个测试项目(你可以把它们放在
模板=子目录中)。然后testrunner将测试结果合并。2) 使用GoogleTest,它在很多方面都很优秀。我不得不添加
QApplication应用程序(argc,argv)
TEST_MAIN
makro(如原始的makro行263),因此目标不显示命令行帮助。最好将宏DECLARE_TEST(FooTests)放入cpp文件中,而不是头文件中,以防止创建类的两个实例,尽管AutoTest.h中有防止双重注册的保护。如果有FootTests的cpp实现,则标头将包含在两个不同的cpp文件中(始终有一个自动生成的moc文件)。QTest::qExec的文档说明:“此函数不应调用多次”。
#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() {};
};
********* 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 *********
#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
#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