如何运行多个 QTest 类? [英] How to run multiple QTest classes?

查看:33
本文介绍了如何运行多个 QTest 类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a subproject where I put all my QTest unit tests and build a stand-alone test application that runs the tests (i.e. I run it from within Qt Creator). I have multiple test classes that I can execute with qExec(). However I don't know what is the proper way to execute multiple test classes.

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

Currently I do it in this way (MVCE):

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() 的文档a> 说这是错误的方式:

However the documentation for qExec() says this is the wrong way:

对于独立测试应用程序,不应多次调用此函数,因为用于将测试输出记录到文件和执行单个测试函数的命令行选项将无法正确运行.

For stand-alone test applications, this function should not be called more than once, as command-line options for logging test output to files and executing individual test functions will not behave correctly.

另一个主要缺点是没有针对所有测试类的单一摘要,仅针对个别类.当我有几十个类,每个类都有几十个测试时,这是一个问题.要检查所有测试是否通过,我必须向上滚动以查看每个课程通过/失败的所有总计",例如:

The other major downside is that there is no single summary for all the test classes, only for individual classes. This is a problem when I have dozens of classes that each have dozens of tests. To check if all tests passed I have to scroll up to see all the "Totals" of what passed/failed of each class, e.g.:

********* 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() 工作考虑到 documentation 说如果测试失败 qExec() 返回一个非零值,这应该意味着以下所有 qExec() 调用都不会发生,但情况似乎并非如此.

I'm also surprised my qExec() || qExec() works considering that the documentation says if a test failed qExec() returns a non-zero value, which should mean all the following qExec() calls wouldn't happen, but this seems not to be the case.

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

What is the proper way to run multiple test classes? And so that I can see at a glance if any of the hundreds of unit tests I have have failed.

推荐答案

我曾经发现一个不错的 解决方案 使用普通 Qt 项目(no TEMPLATE = subdirs),它使用宏方法只需一个简单的帮助程序头文件即可创建主函数并自动注册所有测试类(,也是).

I once found a nice solution using a plain Qt project (no TEMPLATE = subdirs) which uses a macro approach for creating the main function and automatic registering of all test classes (macro, too) with only a simple helper header file.

这是一个示例测试类(只有相关的头文件):

Here is a sample test class (only the relevant header file):

#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

和 main,它消耗以这种方式创建的每个测试类:

and the main, which consumes every test class created this way:

#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

所有功劳归于 Rob Caldecott.

这篇关于如何运行多个 QTest 类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆