我开始使用QT的单元测试系统编写一些测试。

您通常如何组织测试?这是每个模块类的一个测试类,还是使用单个测试类测试整个模块? QT文档建议遵循以前的战略。

我想为模块编写测试。该模块仅提供一个将要由模块用户使用的类,但是除了测试公共类外,我还想测试其他类中的许多逻辑。

问题是QT提出的运行测试的方法涉及 QTEST_MAIN 宏:

QTEST_MAIN(TestClass)
#include "test_class.moc"

最终,一个测试程序能够仅测试一个测试类。为模块中的每个类创建测试项目有点糟糕。

当然,可以看一下 QTEST_MAIN 宏,重写并运行其他测试类。但是有什么东西可以解决吗?

到目前为止,我手工做:

#include "one.h"
#include "two.h"

int main(int argc, char *argv[]) 
{ 
    QCoreApplication app(argc, argv); 
    TestOne one;
    QTest::qExec(&one, argc, argv);
    TestOne two;
    QTest::qExec(&two, argc, argv);
}
有帮助吗?

解决方案

是的,QTest强制有点奇怪的测试结构,通常不如Google测试/模拟框架。对于一个项目,我被迫使用QTest(客户需求),这就是我的使用方式:

  1. 我将所有测试一起编译为一个子dir模板项目
  2. 为了使创建新测试更容易,我通过使用COMMON.PRI文件共享许多项目配置。
  3. 如果可能的话,我共享对象文件目录以加快汇编
  4. 我使用批处理+awk+sed脚本运行它们。

设置这四个点非常容易,使QTest几乎令人愉快。您在运行上述配置未解决的多个测试方面有一些问题吗?

PS:运行测试以您的操作方式,即调用多个QTest :: QEXEC会导致-O命令行开关问题 - 您将仅获得最后一个测试类的结果。

其他提示

与@cjhuitt发布的答案有关

这是一个示例,可以消除手动调用每个测试对象的需要

我试图避免这样的事情:

MyTestClass1 t1;   t1.run();
MyTestClass2 t2;   t2.run();
//etc...

我的解决方案是让测试对象从基类继承,该基类将自己添加到静态列表中然后,主程序执行该列表中的所有测试对象。这样,任何支持框架代码都不需要更改。唯一改变的是测试课程本身。

这是我的方式:

qtestsuite.h - 测试对象的基类

#ifndef QTESTSUITE_H
#define QTESTSUITE_H

#include <QObject>
#include <vector>

class QTestSuite : public QObject
{
    Q_OBJECT
public:
    static std::vector<QObject*> m_suites;

public:
    explicit QTestSuite();

};

#endif // QTESTSUITE_H

qtestsuite.cpp

#include "qtestsuite.h"
#include <iostream>

std::vector<QObject*> QTestSuite::m_suites;

QTestSuite::QTestSuite() : QObject()
{
    m_suites.push_back(this);
}

testall.cpp - 运行测试

#include "qtestsuite.h"

#include <QtTest/QtTest>
#include <iostream>

int main(int, char**)
{
    int failedSuitesCount = 0;
    std::vector<QObject*>::iterator iSuite;
    for (iSuite = QTestSuite::m_suites.begin(); iSuite != QTestSuite::m_suites.end(); iSuite++)
    {
        int result = QTest::qExec(*iSuite);
        if (result != 0)
        {
            failedSuitesCount++;
        }
    }
    return failedSuitesCount;
}

mytestsuite1.cpp - 一个示例测试对象,创建更多这些

#include "qtestsuite.h"

#include <QtTest/QtTest>

class MyTestSuite1: public QTestSuite
{
     Q_OBJECT
private slots:
    void aTestFunction();
    void anotherTestFunction();
};

void MyTestSuite1::aTestFunction()
{
    QString str = "Hello";
    QVERIFY(str.toUpper() == "this will fail");
}

void MyTestSuite1::anotherTestFunction()
{
    QString str = "Goodbye";
    QVERIFY(str.toUpper() == "GOODBYE");
}

static MyTestSuite1 instance;  //This is where this particular test is instantiated, and thus added to the static list of test suites

#include "mytestsuite1.moc"

另外,要创建.pro文件

qmake -project "CONFIG += qtestlib"

在与Qtest的设置中,我们做了一些事情来使其变得更好。

  • 定义一个子类的子类,该子类用作任何新单元测试类的基类。
  • 在该类的构造函数中,我们将测试的实例添加到测试的静态列表中,在驱动器中,我们将其删除。
  • 然后,我们具有静态功能,可以通过测试循环并使用它们运行 QTest::qExec(). 。 (我们每次累积返回的值,并从我们的函数中返回。)
  • main() 调用此功能,并将结果返回为成功/失败。
  • 最后,在特定测试本身的汇编单元中,我们通常包括该类别的静态实例。

此设置意味着课程将在之前实例化 main() 运行,因此将其添加到主要运行时测试的类列表中。该框架要求您只需要正确继承您的课程,如果您始终希望它运行,则需要实例化静态实例。

我们偶尔还会创建其他可选测试,这些测试是根据命令行开关添加的。

通常,我会通过每类测试进行一个测试,以一项测试进行测试。

最终,一个测试程序能够仅测试一个测试类。

这是一件好事。它彼此隔离您的测试,防止像一次测试中的崩溃之类的事情阻止所有其他测试。这种崩溃可能是由正在测试的几个类中的一个共同组件引起的。然后,失败的模式将使您转向问题的基本起源。基本上,如果您的测试彼此独立,则可以更好地诊断出失败的信息。

使设置多个可执行文件并分别运行每个测试。使用测试跑者催生所有测试过程。

更新:

我对此有所改变。一旦您拥有大量测试的大程序,链接数百个测试可执行文件就会变得非常慢。我的新偏爱是将库的所有测试都放入可执行文件中,并选择使用传递给测试可执行文件的命令行参数调用的测试。

这将可执行文件的数量从数百到数十个减少,但保留了分别运行测试的优势。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top