如何运行多个QTest类

How to run multiple QTest classes?

本文关键字:QTest 运行 何运行      更新时间:2023-10-16

我有一个子标记,我将所有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()调用,但这似乎并非如此。

运行多个测试类的正确方法是什么?因此,如果我失败了数百个单位测试中的任何一个。

i曾经使用普通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

和main,它消耗了每个测试类别创建的方法:

#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。