QTest从入门到精通(1)

如何快速使用上QTest进行单元测试

按图索骥

1. 目录结构

image

2. 新建项目选择其他项目->AutoTestProject

image

3. 工程配置

image

4. 在主工程中新建,选择主工程

image

5. 生成的单元测试

image

6. 代码结构

image

认识生成模版

单元测试配置文件QTest_unittest.pro

QT += testlib #将 Qt 测试库添加到项目中,以便使用 Qt 的测试功能。
QT -= gui #从项目中移除 GUI 相关模块,因为这是一个控制台应用程序,不需要图形界面。

#qt:确保项目使用 Qt 框架。
#console:将应用程序设置为控制台程序。
#warn_on:在编译时启用警告信息。
#depend_includepath:将所有依赖项的 INCLUDEPATH 添加到项目中。
#testcase:将项目设置为一个测试用例。

CONFIG += qt console warn_on depend_includepath testcase

CONFIG -= app_bundle #取消应用程序捆绑包设置,避免在 macOS 上创建一个 .app 捆绑包

TEMPLATE = app #指定项目类型为应用程序

SOURCES +=  tst_uitest.cpp #将测试源文件 tst_uitest.cpp 添加到项目中。

tst_uitest.cpp实现

这个示例展示了如何使用 Qt 测试框架创建一个简单的测试用例。Qt 测试框架是用于对 Qt 和 C++ 应用程序进行单元测试的工具。下面是关于这个示例代码及其原理的详细说明:

  1. 包含必要的头文件:包括 QtTest 和 QCoreApplication,它们提供了 Qt 测试框架和应用程序核心组件的类和功能。

  2. 创建一个从 QObject 继承的测试类(例如 qwertyuwerty)。QObject 提供了对象模型特性,如信号-槽处理、对象树以及对象属性等。Q_OBJECT 宏用于启用类的 Qt 元对象特性。

  3. 在测试类中定义构造函数、析构函数以及三个私有槽(private slots)作为测试方法:initTestCase()、cleanupTestCase() 和 test_case1()。

    • initTestCase(): 在运行整个测试套件之前执行一些初始化操作。
    • cleanupTestCase(): 在运行完所有测试用例后执行一些清理操作。
    • test_case1(): 是实际测试用例,可以在里面编写测试逻辑。您可以添加更多的测试方法。
  4. 实现这些方法。目前,这些方法为空,您需要为它们提供具体实现。

  5. 使用 QTEST_MAIN(qwertyuwerty) 宏生成 main() 函数。这个宏会创建一个名为 main() 的函数,该函数负责运行测试类(qwertyuwerty)及其中的测试槽(即测试用例)。它会将测试结果输出到控制台。

  6. 包含 "tst_qwertyuwerty.moc" 文件,以便 Qt 元对象编译器(MOC)处理。这个文件是由 MOC 自动生成的,用于处理 QObject 派生类中的信号、槽和属性等元对象特性。在这种情况下,它主要负责处理测试方法的信号-槽调用。

要执行这个测试用例,您需要使用 Qt Creator 创建一个新的 Qt Test 项目,并将这段代码添加到项目源文件中。然后编译并运行项目。测试框架会自动运行所有定义的测试槽,并报告成功或失败的测试数量。
Note: 要增加新的测试方法,需要在private slots: 下增加,这样才会执行时被系统默认调用

宏QTEST_MAIN

定义如下

#define QTEST_MAIN_IMPL(TestObject) \
    TESTLIB_SELFCOVERAGE_START(#TestObject) \
    QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \
    QGuiApplication app(argc, argv); \
    app.setAttribute(Qt::AA_Use96Dpi, true); \
    TestObject tc; \
    QTEST_SET_MAIN_SOURCE_PATH \
    return QTest::qExec(&tc, argc, argv);

#define QTEST_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
    QTEST_MAIN_IMPL(TestObject) \
}

重点关注一下QTest::qExec(&tc, argc, argv);

宏QTEST_GUILESS_MAIN

字面意思就是没有集成GUI

#define QTEST_GUILESS_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
    TESTLIB_SELFCOVERAGE_START(#TestObject) \
    QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \
    QCoreApplication app(argc, argv); \
    app.setAttribute(Qt::AA_Use96Dpi, true); \
    TestObject tc; \
    QTEST_SET_MAIN_SOURCE_PATH \
    return QTest::qExec(&tc, argc, argv); \
}

宏QTEST_APPLESS_MAIN

终端程序

#define QTEST_APPLESS_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
    TESTLIB_SELFCOVERAGE_START(TestObject) \
    TestObject tc; \
    QTEST_SET_MAIN_SOURCE_PATH \
    return QTest::qExec(&tc, argc, argv); \
}

上面三个宏最要的是功能就是现实了main函数

编写代码

将测试类引入

#include "calculator.h"
#include "CalculatorTest.h"
#include <QDebug>
void CalculatorTest::initTestCase()
{
    qDebug() << "initTestCase";
}

void CalculatorTest::cleanupTestCase()
{
    qDebug() << "cleanupTestCase";
}

void CalculatorTest::testAdd()
{
    Calculator cls;
    QCOMPARE(cls.add (3,4),7);
}

优化

使用了上面的宏定义就只能有一个测试类了,显然不符合正常的测试开发流程,我们需要多个测试类对不同的测试场景覆盖

所以修改代码如下

1. 创建main,cpp,定义main函数

image

2. 将测试类分开为.h,.cpp文件,引入头文件

调用代码就会自动执行测试代码,从前面的宏定义也能看到

	MyTest test;
    QTest::qExec(&test, argc, argv);

    CalculatorTest suite1;
    QTest::qExec(&suite1, argc, argv);

    WindowTest witest;
    QTest::qExec(&witest, argc, argv);

这样就可以实现多个测试类同时运行,如果先单独测试一个类,可以写在最前面然后return 0 ,不过还有更加简单的方法,下面介绍
image

运行测试用例

运行单元测试插件即可
image
我们可以直观的看到运行结果,用例是否成功

引用

QTest

posted @ 2023-03-29 14:55  严_青  阅读(2876)  评论(7编辑  收藏  举报