TDD(Test Driven Development),即测试驱动开发。是指在具体开发之前先编写测试样例。这样做的好处有:
- 一开始就从被使用的角度考虑,能避免开发半天发现方向错误甚至开发用不到的功能。
- 先编写出测试,方便接口各方达成共识(交叉评审),并在开发中相互协同测试,避免各方开发方向出现偏差。
- 基于QTest开发的测试代码能在开发后一键测试,并且在代码进行修改时(功能变更或出现联调Bug)能一次运行所有测试,避免了重复的测试工作并保证修改后的代码达到预期行为(每次修改完后测试一下给你一种飘柔般的自信hhhh)。
那具体怎么做呢?
首先本实例基于coding编写测试样例。
-
先定义好函数、类的原型。
-
编写测试用例。测试用例应当尽可能覆盖所有边界条件,所有功能子块。用例写得好,Debug时可以立即确定bug的产生位置、原因。
-
交由另一人进行用例评审,最好是和你负责的功能块相关的人。这样能进一步确认彼此对于接口的理解,避免开发方向出现偏差。
-
根据测试用例编写测试代码。
测试项目应当和项目分离,保证代码的纯洁性。
首先,新建一个测试项目。
然后配置.pro文件,也就是QtProject文件。
添加INCLUDEPATH += 待测试项目的目录地址(导入.h文件)
。如果采用分离式编译,则SOURCES += 所有待测试文件的地址(导入.cpp文件)
,QT += testlib
,导入QTest单元。
个人习惯是为每一个类创建一个测试类,选择添加文件时选择Head文件,然后将名字改成.hpp(.h+.cpp)。表示定义和实现不分离。
Testxxx.hpp表示对xxx类的测试代码。测试框架如下:
包含<QtTest/QTest>头文件,然后包含要测试的类的头文件。因为.pro中导入了头文件地址,所以不需要绝对地址。然后整个代码框架就如上图,测试类继承自QObject
,然后每个测试样例写成一个测试函数void Case(void)
。每个测试函数名最好定义成测试方向相关的,如TestGPS
,测试GPS,这个例子由于类比较简单就定义为Casex
了。
如果你的函数命名为initTestCase
,这个函数就会首先执行,如果命名为cleanupTestCase
,就会在最后执行。对应于一些类的初始化行为和扫尾工作。
接下来,最常用的QCOMPARE(x,y)
,比较x和y是否相等,如果x,y是类的话,需要实现一下bool operator==(const Class&)const
,定义相等。还有QVERIFY(Expression)
,测试表达式是否为真。剩下的还有模拟键盘鼠标事件、限时的QCOMPARE
进行压力测试等等,可以在QT的帮助文档里的QTest
部分找到。
然后添加一个main
函数,包含要运行的测试文件,并添加上QTEST_MAIN(测试类)
即可。这个宏会自动拓展main
函数并配置相关信息。个人习惯是将某个子项目的测试项目放一起,然后通过main.cpp
来控制执行哪一个测试单元。
然后点击帮助/关于插件
,勾选Auto Test
,然后重启QtCreator,就会出现一个Test Results
。然后点击Test Results
的绿色箭头,就可以运行所有的测试样例,可以很清晰的看到测试的情况,下图是所有测试都通过了。
下图是6号样例出错了,并且出错的地方在右侧会以红点标出。
这样一个测是代码就构建好了。最后,如果要测试某个类的私有方法,在测试文件中加上#define private public
即可。