QT自动化测试
1、常用宏
QBENCHMARK 计算运行时间,多次运行测量 QBENCHMARK_ONCE 计算运行时间,单次运行测量 QCOMPARE 比较是否相等 QEXPECT_FAIL 将下一个QCOMPARE或QVERIFY标记为预期测试,如果预期测试没有通过,可以终止剩余当前单元测试【可设置测试终止或继续】 QFAIL 强制抛出错误并打印信息 QFETCH 创建临时变量,从当前数据表中读取数据 QFETCH_GLOBAL 创建全局变量,从全局数据表中读取数据,必须有initTestCase_data【?】 QFINDTESTDATA 从路径获取测试数据【?】 QSKIP 停止测试,但不会将失败添加到失败日志 QTEST 可替代QFETCH+QCOMPARE的便利写法,不需要QFETCH来生成变量 QTEST_MAIN 创建一个main函数,并实例化应用程序对象和测试用例对象,QT_WIDGETS_LIB->QApplication(Qt+=widgets),QT_GUI_LIB->QGuiApplication(Qt+=gui),其他->QCoreApplication QTEST_APPLESS_MAIN 与QTEST_MAIN相似但不实例化QApplication QTEST_GUILESS_MAIN 与QTEST_MAIN相似只实例化QCoreApplication QTRY_COMPARE_WITH_TIMEOUT 与QCOMPARE相似,但重复执行两个值的比较,直到两个值相等或者达到超时时间 QTRY_COMPARE 执行QTRY_COMPARE_WITH_TIMEOUT,并将超时时间设置为5秒 QVERIFY 判断条件是否为true,如果为true则继续执行测试,否则记录失败日志并且不再执行单元测试 QVERIFY2 与QVERIFY相似,但可以自定义失败日志 QTRY_VERIFY_WITH_TIMEOUT 与QVERIFY相似,但但重复执行条件的判断,直到条件为true或者达到超时时间 QTRY_VERIFY 执行QTRY_VERIFY_WITH_TIMEOUT,并将超时时间设置为5秒 QTRY_VERIFY2_WITH_TIMEOUT 与QVERIFY2相似,但但重复执行条件的判断,直到条件为true或者达到超时时间 QTRY_VERIFY2 执行QTRY_VERIFY2_WITH_TIMEOUT,并将超时时间设置为5秒 QVERIFY_EXCEPTION_THROWN 执行表达式,并判断语句抛出的异常是否与预期异常相等 QWARN 主动添加警告日志(线程安全)
2、创建Qt自动化测试工程
2.1、新建工程,可选Qt单元测试和Auto Test Project,在高版本中已经没有Qt单元测试这项了,建议选Auto Test Project,两者差不多,只是生成的默认宏不一样
默认往下,测试框架有Qt Test、GTest、BoostTest、Catch2等常用主流单元测试框架,这里选Qt Test,GTest和Boost都需要安装对应的环境
2.2、框架生成的默认函数
void initTestCase(); void cleanupTestCase();
这两个是框架自动调用的,出此以外还有:
void init(); void cleanup();
test_case1函数是用户可自定义的测试函数
总结一下系统自动调用的函数:
void initTestCase(); //在第一个测试函数执行之前被调用的初始化函数 void cleanupTestCase(); //在最后一个测试函数执行完毕之后调用的清理操作 void init(); //每次执行测试函数之前调用的初始化函数 void cleanup(); //每次执行完测试函数之后调用的清理操作
需要注意的是:测试函数必须声明成槽函数,此类的槽函数会被主动调用执行
3、开始测试
3.1、测试一个DbConvert类
Github:https://github.com/judesmorning/DbConvert
主要有这么一个函数:
3.2、将待测试的类集成到单元测试工程中
注意.pro中也要添加进来
SOURCES += tst_mytest.cpp \ ../converttool.cpp HEADERS += \ ../converttool.h
3.3、常规测试
创建单次测试的函数,主要用于验证Qt单元测试可用到的工具宏:
实现:
void MyTest::test_qtest() { //计算运行时间,多次运行测量 #if 0 QBENCHMARK(m_tool->calc(QString("0"), ConvertTool::CalType_dBm2mW)); #endif //计算运行时间,单次运行测量 #if 0 QBENCHMARK_ONCE(m_tool->calc(QString("0"), ConvertTool::CalType_dBm2mW)); #endif //比较是否相等 #if 0 QCOMPARE(m_tool->calc(QString("0"), ConvertTool::CalType_dBm2mW), QString("1")); #endif //将下1个QCOMPARE或QVERIFY标记为预期测试,如果预期测试没有通过,可以终止剩余当前单元测试【可设置测试终止或继续】 //第1个参数为空只打印第2个参数,否则打印异常位置 //第1个参数为Continue、Abort,表示如果不通过是否继续执行剩余用例 #if 0 QEXPECT_FAIL("", "Will fix in the next release", Continue); QCOMPARE(m_tool->calc(QString("0"), ConvertTool::CalType_dBm2mW), QString("10")); #endif //强制抛出错误并打印信息 #if 0 if (5 != 4) { QFAIL("This test has not been ported to this platform yet."); } #endif //创建临时变量,从当前数据表中读取数据 #if 0 //在data函数中创建 QTest::addColumn<int>("a"); QTest::addColumn<int>("b"); QTest::newRow("positive value") << 100 << 100; //在测试函数中取出 QFETCH(int, a); QFETCH(int, b); QCOMPARE(a, b); #endif //创建全局变量,从全局数据表中读取数据,必须有initTestCase_data #if 0 //QFETCH_GLOBAL? #endif //从路径获取测试数据 #if 0 MyXmlParser parser; QString input = QFINDTESTDATA("testxml/simple1.xml"); QVERIFY(parser.parse(input)); #endif //停止测试,但不会将失败添加到失败日志 #if 0 if (4 != 5) { QSKIP("This test requires the SQLITE database driver"); } #endif //可替代QFETCH+QCOMPARE的便利写法,不需要QFETCH来生成变量 #if 0 QTEST(QString("hello").toUpper(), "myString"); #endif //与QCOMPARE相似,但重复执行两个值的比较,直到两个值相等或者达到超时时间 #if 0 QTRY_COMPARE_WITH_TIMEOUT(1, 1, 5); #endif //执行QTRY_COMPARE_WITH_TIMEOUT,并将超时时间设置为5秒 #if 0 QTRY_COMPARE(1, 1); #endif //判断条件是否为true,如果为true则继续执行测试,否则记录失败日志并且不再执行单元测试 #if 0 QVERIFY(1+1==2); #endif //与QVERIFY相似,但可以自定义失败日志 #if 0 QVERIFY2(1+1==2, "A breach in basic arithmetic occurred."); #endif //与QVERIFY相似,但重复执行条件的判断,直到条件为true或者达到超时时间 #if 0 QTRY_VERIFY_WITH_TIMEOUT(1+1==2, 5); #endif //执行QTRY_VERIFY_WITH_TIMEOUT,并将超时时间设置为5秒 #if 0 QTRY_VERIFY(1+1==2); #endif //与QVERIFY2相似,但重复执行条件的判断,直到条件为true或者达到超时时间 #if 0 QTRY_VERIFY2_WITH_TIMEOUT(3>2, "this is log msg", 5); #endif //执行QTRY_VERIFY2_WITH_TIMEOUT,并将超时时间设置为5秒 #if 0 QTRY_VERIFY2(3>2, "this is log msg"); #endif //执行表达式,并判断语句抛出的异常是否与预期异常相等 #if 0 //QVERIFY_EXCEPTION_THROWN #endif //主动添加警告日志,线程安全 #if 0 QWARN("msg"); #endif }
3.4、数据驱动测试
创建一个函数test_calc,并将此函数名后加“_data”作为新的函数,再创建一个待测类指针:
①、
根据前面的说明,我们可以在initTestCase中new出指针,在cleanupTestCase中delete指针
void MyTest::initTestCase() { m_tool = new ConvertTool(nullptr); } void MyTest::cleanupTestCase() { delete m_tool; m_tool = nullptr; }
②、
void MyTest::test_calc_data() { /*创建测试参数*/ QTest::addColumn<QString>("calStr"); //创建第1个入参集合 QTest::addColumn<ConvertTool::CalType>("type"); //创建第2个入参集合 QTest::addColumn<QString>("result"); //创建返回值集合 /*设计用例*/ QTest::newRow("ok_1") << "0" << ConvertTool::CalType_dBm2mW << "1"; QTest::newRow("ok_2") << "10" << ConvertTool::CalType_dBm2mW << "10"; QTest::newRow("ng_1") << "10" << ConvertTool::CalType_dBm2mW << "100"; }
③、
void MyTest::test_calc() { //取出测试数据 QFETCH(QString, calStr); QFETCH(ConvertTool::CalType, type); QFETCH(QString, result); //测试 QCOMPARE(m_tool->calc(calStr, type), result); }
即test_calc函数会实例化test_calc_data中的测试用例并执行测试
④、
可直接运行程序,在应用程序输出里看结果
为了直观,可在Test Results里运行程序,通过图形的形式展示
在Test Results里,也可将测试结果输出到文档中:
右键最上面的测试行,选择“save output to file",可将结果存成文档:
说明:
1.如果待测工程很大,建议在待测工程基础上增加一个pri和一个自动化测试的类,屏蔽main函数
长风破浪会有时,直挂云帆济沧海!
可通过下方链接找到博主
https://www.cnblogs.com/judes/p/10875138.html