Qt单元测试(QTestLib)

摘要:
其中tst_Qttesttest是与测试项目相对应的可执行文件名。毫秒延迟,如果没有模拟键盘或鼠标,则从该参数的值替换。MS类似于事件延迟,但它只影响键盘而不是鼠标的模拟。
 版权声明:若无来源注明,Techie亮博客文章均为原创。 转载请以链接形式标明本文标题和地址:
本文标题:Qt单元测试(QTestLib)     本文地址:http://techieliang.com/2017/12/483/

1. 创建

QTestLib框架提供了一个简单易用的单元测试框架,需要在工程文件中添加Qt+=testlib,或在新建项目是选择“其他项目-qt单元测试”,详细帮助请看qt4.8官方文档Qt5官方文档

2. 基本操作

  1. class Untitled2Test : public QObject {
  2. Q_OBJECT
  3. public:
  4. Untitled2Test();
  5. private Q_SLOTS:
  6. void initTestCase();
  7. void cleanupTestCase();
  8. void testCase1();
  9. };
  10. Untitled2Test::Untitled2Test() {
  11. }
  12. void Untitled2Test::initTestCase() {
  13. }
  14. void Untitled2Test::cleanupTestCase() {
  15. }
  16. void Untitled2Test::testCase1() {
  17. QVERIFY2(true, "Failure");
  18. }
  19. QTEST_APPLESS_MAIN(Untitled2Test)
  20. #include "tst_untitled2test.moc"

注意:
1、每一个测试类(Case)中的每一项测试条目必须在Qt槽中,否则无法调用“private Q_SLOTS:”“private slots:”均可
2、最后两行必须有,单元测试不具有Main函数,使用此函数实现自动添加并调用所有槽

1、initTestCase() will be called before the first testfunction is executed.

initTestCase()会在第一个测试函数执行前调用。

2、cleanupTestCase() will be called after the last testfunction was executed.

cleanupTestCase()会在最后一个测试函数执行后调用。

3、init() will be called before each testfunction is executed.

init()会在每一个测试函数执行前调用。

4、cleanup() will be called after every testfunction.

cleanup()会在每一个测试函数执行后调用。

3. 高级操作

3.1. 命令行操作-可以输出调试结果到文本

打开cmd,通过cd命令将目录指向到项目的debug目录下的debug,在此文件内应该可以直接看到测试项目的可执行exe文件,此时出入tst_qttesttest -xml -vs -lightxml -o testres.txt指令即可导出测试结果保存到texstres.txt文件中。

其中tst_qttesttest为测试项目对应的可执行文件名。

还可以使用以下命令行参数:

    • -help
      输出可能的命令行参数,并提供一些有益的帮助。
    • 的功能
      输出在测试中所有测试功能。
    • -O?文件名
      ??写输出到指定的文件,而不是标准输出
    • 无声的
      沉默输出,只显示警告,失败和最小的状态消息
    • -V1
      详细输出,输出的进入和退出测试功能的信息。
    • -V2
      扩展的详细输出;还输出每个QCOMPARE()和QVERIFY()
    • -VS
      输出每个被发出的信号
    • -XML
      输出XML格式的结果,而不是纯文本
    • lightxml
      输出结果作为XML标签流
    • -eventdelay?毫秒
      延迟,如果没有模拟键盘或鼠标(指定QTest :: keyClick(),QTest ::mouseClick()等),从这个参数的值(以毫秒为单位)取代。
    • keydelay?MS
      类似eventdelay,但只影响模拟键盘而不是鼠标模拟。
    • mousedelay?MS
      类似eventdelay,但只影响鼠标模拟,而不是键盘模拟。
    • -KeyEvent的详细
      输出更详细的输出模拟键盘
    • – maxwarnings
      numberBR设置输出最大数量的警告。无限,默认为0到2000。

3.2. GUI测试

Qtestlib单元测试提供GUI操作函数,可对控件发送消息后检测执行结果,比如QTest::keyClick(),QTest::mouseClick()等等,详情请见帮助文档

下面提供鼠标操作相关的枚举类型:

ConstantValueDescription
QTest::MousePress0A mouse button is pressed.
QTest::MouseRelease1A mouse button is released.
QTest::MouseClick2A mouse button is clicked (pressed and released).
QTest::MouseDClick3A mouse button is double clicked (pressed and released twice).
QTest::MouseMove4The mouse pointer has moved.

下面为鼠标相关的操作函数:

  1. void mouseClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  2. void mouseClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  3. void mouseDClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  4. void mouseDClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  5. void mouseMove(QWidget *widget, QPoint pos = QPoint(), int delay = -1)
  6. void mouseMove(QWindow *window, QPoint pos = QPoint(), int delay = -1)
  7. void mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  8. void mousePress(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  9. void mouseRelease(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)
  10. void mouseRelease(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay = -1)

3.3. 结果可视化-AutoTest插件

Qt单元测试(QTestLib)第1张

默认测试结果显示在控制台(应用程序输出标签)以纯文本形式显示,不够直观,可使用AutoTest插件实现可视化效果

通过帮助-关于插件-AutoTest开启即可,启动此插件需要重启Qt Creator,然后再下方会多出TestResults的标签,可直接在此标签点击上方的运行按钮运行所有测试,同时在“工具-Test”也可运行所有测试

此插件可以在运行单元测试后以红、绿色表示明确标记处运行结果,并且以Case为单位显示,可以展开看到具体每一个测试用例的结果。

3.4. 可以用到的测试宏命令

  1. QBENCHMARK
  2. QBENCHMARK_ONCE
  3. QCOMPARE(actual, expected)
  4. QEXPECT_FAIL(dataIndex, comment, mode)
  5. QFAIL(message)
  6. QFETCH(type, name)
  7. QFINDTESTDATA(filename)
  8. QSKIP(description)
  9. QTEST(actual, testElement)
  10. QTEST_APPLESS_MAIN(TestClass)
  11. QTEST_GUILESS_MAIN(TestClass)
  12. QTEST_MAIN(TestClass)
  13. QTRY_COMPARE(actual, expected)
  14. QTRY_COMPARE_WITH_TIMEOUT(actual, expected, timeout)
  15. QTRY_VERIFY2(condition, message)
  16. QTRY_VERIFY(condition)
  17. QTRY_VERIFY2_WITH_TIMEOUT(condition, message, timeout)
  18. QTRY_VERIFY_WITH_TIMEOUT(condition, timeout)
  19. QVERIFY2(condition, message)
  20. QVERIFY(condition)
  21. QVERIFY_EXCEPTION_THROWN(expression, exceptiontype)
  22. QWARN(message)

3.5. 单元测试注意事项

  1. 单元测试类中建议不要出现私有成员,尤其是指针,同时不建议在测试函数中建立被测类的指针,而是直接建立被测类的对象,在测试结束后容易遗忘指针。若需要指针initTestCase中new,在cleanupTestCase中delete。
  2. 若某个测试函数中出现了new,一定记着delete,且务必让delete在第一个断言前出现,因为断言失败函数就回立刻结束,并把当前函数标记为测试失败。若delete在第一个断言之后,而第一个断言失败则不会执行之后的delete。
  3. 若测试类必须有私有成员,必须注意一个测试类中的所有函数公用私有成员,不会在每个测试之前刷新状态。

3.6. 被测类为单例时

若被测类为单例,欲对其内所有函数做单元测试,会出现测试第一个函数可以保证测试环境为初始状态,后续测试回因为单例的原因,导致测试时建立在之前操作后的环境下。欲解决此问题,需要删除单例。

单例类如下:

  1. class SingleModel {
  2. public:
  3. static inline SingleModel* get_instance() {
  4. if (m_instance == nullptr) {
  5. m_instance = new SingleModel();
  6. }
  7. return m_instance;
  8. };
  9. private:
  10. SingleModel();
  11. class SingletonDel {
  12. public:
  13. ~SingletonDel() {
  14. if (m_instance != nullptr) {
  15. delete m_instance;
  16. m_instance = NULL;
  17. }
  18. }
  19. };
  20. static SingleModel* m_instance;
  21. static SingletonDel m_singleton_del;
  22. };

此时使用get_instance可以获得单例的指针,使用delete可以删除单例的空间,但是由于单例实例的指针是静态私有成员的,所以应该将其设置为NULL,否则下次调用get_instance判断非NULL会直接返回之前的已经被删除的空间指针而不进行new操作,导致后续操作错误。

由于m_instance是私有成员,在单元测试时无法进行修改,故做以下设置:

.h文件不变:

  1. #include <QtTest>
  2. class ProjectModelTest: public QObject {
  3. Q_OBJECT
  4. private Q_SLOTS:
  5. void TestXXX();
  6. };

.cpp文件修改:

  1. #define private public
  2. #include "project_model.h"
  3. void ProjectModelTest::TestXXX() {}

注意一定要在include前define,通过将private定义为public,从而实现将源程序的私有成员编程public。同时此处的define在cpp里面,只对此cpp有效,不会影响其余的单元测试。

免责声明:文章转载自《Qt单元测试(QTestLib)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Delphi 使用CreateProcess创建进程并弹出进程PID值 (转)python简介及安装配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python-单元测试 unittest &amp;amp; HTMLTestRunner模块产生的测试报告

 1、单元测试: ——开发程序的人测已经已经写好的代码。 unittest框架,执行的顺序是按照方法名的字母来排序的 setUpClass方法是最开始执行的,只会执行一次 tearDownClass是最后执行的,只会执行一次 setUp方法是在每个测试用例执行前会执行 tearDown方法是在每个用例执行后会执行 import unittest de...

C# 单元测试

学历代表你的过去,能力代表你的现在,学习代表你的将来 十年河东,十年河西,莫欺少年穷 学无止境,精益求精 废话咱也不多说,直接进入正题: 首先说说单元测试的好处: 1. 单元测试保证你的code真的能动   这会让bug减少。当然,单元测试不能取代系统测试和验收测试。但单元测试能补足他们的短处。   2. 你会得到一组低层的regression-te...

.netcore持续集成测试篇之开篇简介及Xunit基本使用

系列目录 为了支持跨平台,微软为.net平台提供了.net core test sdk,这样第三方测试框架诸如Nunit,Xunit等只需要按照sdk提供的api规范进行开发便可以被dotnet cli工具调用,这样就解决了在持续集成过程中第三方框架依赖于windows平台上的各自runner的问题,使得测试框架开发者不需要花费很大功夫就可以快速迁移到.n...

#学习分享#开发基础知识之前端测试(一)

前言:本文用于2018/1/30晚内部分享。主题:前端单元测试 正文: 一、思考 我的目标是,如何浅入本次的主题,让愿意接收陌生信号的“对象”快速简单的get到信号,并且对本次分享产生一个小兴趣。 二、What     本章节主要讲述前端单元测试做什么,vue单元测试做什么。   (1) 基础概念 测试的概念:测试是检测你的应用代码(也叫“生产代码”)...

java单元测试之如何实现异步接口的测试案例

测试是软件发布的重要环节,单元测试在实际开发中是一种常用的测试方法,java单元测试主要用junit,最新是junit5,本人开发一般用junit4。因为单元测试能够在软件模块组合之前尽快发现问题,所以实际开发中投入产出比很高。实际使用难免会遇到异步操作的接口测试,最常用的情景是别人家的SDK封装了异步处理,需要用测试用例来验证SDK的流程,顺便测试参数的...

游戏组件——总结

总结 你的小游戏引擎现在有了三个新命名空间,也有许多辅助类可以用在未来的项目中。新的TextureFont 类在下面几章尤其有用。它不仅仅在显示诸如记分板这样的游戏数据上有用,也在单元测试中被使用;为了告诉用户所有可用的热键,在单元测试中显示帮助文本非常有用;万一你遇到问题,显示测试数据或者Debug数据尤其有用。例如,一个camera类的单元测试能输...