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函数

 

posted @ 2022-08-11 19:34  朱小勇  阅读(1972)  评论(0编辑  收藏  举报