使用Qt'进行测试;s QTestLib模块
我开始用Qt的单元测试系统编写一些测试 你通常是如何组织考试的?它是每个模块类一个测试类,还是用一个测试类测试整个模块?Qt文档建议遵循前一种策略 我想为一个模块编写测试。模块只提供一个将由模块用户使用的类,但是在其他类中抽象了很多逻辑,除了测试公共类之外,我还想测试这些逻辑 问题在于,Qt建议的运行测试的方法涉及使用Qt'进行测试;s QTestLib模块,qt,unit-testing,qttest,Qt,Unit Testing,Qttest,我开始用Qt的单元测试系统编写一些测试 你通常是如何组织考试的?它是每个模块类一个测试类,还是用一个测试类测试整个模块?Qt文档建议遵循前一种策略 我想为一个模块编写测试。模块只提供一个将由模块用户使用的类,但是在其他类中抽象了很多逻辑,除了测试公共类之外,我还想测试这些逻辑 问题在于,Qt建议的运行测试的方法涉及QTEST\u MAIN宏: QTEST_MAIN(TestClass) #include "test_class.moc" 最终一个测试程序只能测试一个测试类。为模块中的每个类创建
QTEST\u 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强制使用有点奇怪的测试结构,通常不如googletest/Mock框架。对于一个项目,我被迫使用QTest(客户需求),以下是我如何使用它:
PS:按您的方式运行测试,即调用多个QTest::qExec会导致-o命令行开关出现问题-您只会得到上一个测试类的结果。在我们使用QTest的设置中,我们做了一些事情使其更好
- 定义QObject的子类,该子类用作任何新单元测试类的基类李>
- 在该类的构造函数中,我们将测试实例添加到静态测试列表中,并在析构函数中删除它李>
- 然后,我们有一个静态函数,它循环测试并使用
运行它们。(我们累积每次返回的值,并从函数中返回。)QTest::qExec()
调用此函数,并将结果作为成功/失败返回李>main()
- 最后,在特定测试本身的编译单元中,我们通常包括该类的静态实例李>
main()
之前实例化,因此它将被添加到要在main运行时进行测试的类列表中。该框架要求您只需正确继承类,并实例化一个静态实例(如果您总是希望它运行的话)
我们偶尔也会创建其他可选的测试,这些测试是基于命令行开关添加的。通常我会组织测试,测试中的每个类都有一个测试可执行文件 最终一个测试程序是 能够只测试一个测试 班级 这是一件好事。它将您的测试彼此隔离,防止一个测试中的崩溃之类的事情阻塞所有其他测试。这种崩溃可能是由测试中的几个类中的一个公共组件引起的。然后,故障模式将提示您问题的根本根源。基本上,如果您的测试彼此独立,您就可以获得更好的故障诊断信息 使设置多个可执行文件和单独运行每个测试变得容易。使用测试运行程序生成所有测试进程 更新:
MyTestClass1 t1; t1.run();
MyTestClass2 t2; t2.run();
//etc...
我在这件事上有些改变了主意。一旦你有了一个包含大量测试的大程序,链接数百个测试可执行文件就会变得非常缓慢。我的新偏好是将库的所有测试放入可执行文件中,并使用传递给测试可执行文件的命令行参数选择要调用的测试
这将可执行文件的数量从数百个减少到几十个,但保留了单独运行测试的优势。与@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
嗨,卡莱布,还在挣扎。您是否有愿意分享的示例代码?谢谢。两年来,我在几个测试项目中使用了这种方法,但现在我遇到了以下静态初始化顺序问题:
static MyTestSuite1实例
可以在m_套件
之前初始化。因此,最好让m_套件是一个返回对静态成员的引用的函数:std::vector&QTestSuite::mSuites(){static std::vector INST;return INST;}
注意,如果您编写这样的测试,Qt Creator的自动测试插件在查找宏“QTEST_MAIN”时将无法找到并运行它们(我自己刚刚发现)“QTEST_APPLESS_MAIN”和“QTEST_GUILESS_MAIN”。见详情。
#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;
}
#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"
qmake -project "CONFIG += qtestlib"