如何运行多个QTest类?

DBe*_*nko 11 c++ qt unit-testing qtestlib

我有一个子项目,我将所有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
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

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() {};
};
Run Code Online (Sandbox Code Playgroud)

但是文档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 *********
Run Code Online (Sandbox Code Playgroud)

qExec() || qExec()考虑到文档说如果测试失败qExec()返回非零值,这也意味着所有以下qExec()调用都不会发生,我也对我的工作感到惊讶,但似乎并非如此.

运行多个测试类的正确方法是什么?因此,我可以一目了然地看到我已经失败的数百个单元测试中的任何一个.

max*_*xik 6

我曾经使用普通的Qt项目(no)找到了一个不错的解决方案,该项目使用宏方法来创建主要功能,并仅通过简单的帮助程序头文件自动注册所有测试类(,也是如此)。 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
Run Code Online (Sandbox Code Playgroud)

主体消耗了以这种方式创建的每个测试类:

#include "AutoTest.h"

TEST_MAIN
Run Code Online (Sandbox Code Playgroud)

的代码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
Run Code Online (Sandbox Code Playgroud)

所有学分归Rob Caldecott所有。