[转帖]单元测试简介
关键词: 转帖 单元 测试 简介
多个测试用例用拷贝当前用例的方式新建,通常只须对输入数据和预期输出做简单修改即可
要人工找出所有的测试用例(所有的等价类)通常是很困难的,但使用VU,只需要为容易想到的典型的输入建立测试用例就行了,其他用例可以在测试用例设计器的帮助下轻松找出来
特殊情况下可以切换到代码模式直接编辑代码
复杂的输入输出也能轻松应对
用.操作符直接访问成员变量或调用成员函数
预期输出可以判断多个数据
只需要人工建立典型的测试用例,VU会统计白盒覆盖状况,对于未覆盖的语句、条件、分支或路径,可以用测试用例设计器来建立相应的测试用例
为未覆盖的代码、条件、分支或路径设计测试用例
根据上面的修改提示,对近似测试用例作简单修改,即可获得需要的测试用例
即使是很复杂的程序,只要对代码有基本的理解,也能轻松找出隐藏得很深的遗漏测试用例
一
般情况下,达到100%的语句、条件、分支、路径覆盖都是很容易的,不可覆盖的分支可以在逻辑结构图上删除。非常复杂的代码,在删除不可覆盖的分支后,路
径的数量通常不会很多,仍然能够达到100%的路径覆盖,必要时还可以在逻辑结构图中屏蔽安全的分支结构以减少路径数量
传
统的单元测试方式下,达到100%的语句、条件、分支、路径覆盖是很困难的,但使用VU,达到了这种覆盖仍然认为测试不完整,因为,如果缺少处理某些特殊
输入的代码,任何覆盖率都不能发现,所以,VU还提供了自动边界测试来检查对特殊输入的处理,运行测试时只要打开边界测试开关就行了
这个示例中,只有2个人工设定的测试用例,现在显示有27个用例,其中25个是自动生成的边界测试用例
由于VU自动生成测试代码,人工只需要设计典型的容易想到的测试用例,所以单元测试本身费时很少。另一方面,VU还帮助程序员大量提高开发效率
编写程序的主要时间消耗并不在敲键盘,而在于编程思路和调试,使用VU,恰恰能在这两方面提高工作效率
编写一小段程序,即可执行测试,看看程序的行为。这里显示各种输入与输出,还可以用TEST_TRACE()宏输出任何变量或表达式的中间结果
这里显示当前输入时所执行的代码行
这里显示当前输入时程序的执行路径
输入输出数据、代码执行状况、路径图,三位一体,完整地描述了程序的行为,帮助验证编程思路,随时发现不正确的程序逻辑,大幅度提高编程的生产效率,同时也使编程工作变得轻松一些
多数代码错误,都可以通过浏览这些测试数据快速发现,而不需要单步调试。如果需要调试,在VU的支持下调试也会有更高的效率
打开调试开关
只要用调试方式运行测试工程,即可进入调试,程序会自动中断
在VU的支持下调试,会自动选择输入数据,并可以切换输入(即切换到其他用例),支持无限制的后退,提高调试效率
使用VU,可以轻松完成100%语句、条件、分支、路径覆盖,宏观上,还统计整体的测试状况。待测文件列表可以统计项目中含有未测试函数的所有文件,从整体上保证测试的完整性
还提供测试报表,详细地记录测试结果
这里以VC6.0为例,其他开发环境也基本上是一样的,有问题请参考帮助系统
启动VU。启动开发环境,打开示例的测试工程,目录为:VU安装目录\u24320开发环境名称
设置开发环境选项:由于测试代码是由VU生成和维护的,选上这里后,当VU生成测试代码时,开发环境就会自动载入而不会报警。C++
Builder 6.0 没有类似选项。
切换到目录页,添加搜索路径,将VU目录下的Include目录加入搜索路径
把示例的产品工程也加入搜索路径,因为测试工程要编译产品工程的文件。
编译并运行测试工程,即可执行测试
测试完成,主窗口自动弹出,显示测试结果
随便选择另一个函数试一下
编译并运行测试工程
测试结束,显示测试结果
我们用 VU目录/Projects/
下的代码来进行演示,您可以使用这些代码进行对照练习。如果您的VU目录下没有Projects文件夹,请升级到最新版本
请用您的开发环境建立一个工程(产品工程),把示例代码拷贝到产品工程目录下,并加入工程中。如果您的产品工程不使用预编译头文件(如C++
Builder),请使用code_nph目录下的示例代码,否则请使用code目录下的示例代码
这里用VC6.0进行演示,这是新建的产品工程的目录。不同的开发环境,建立和配置测试工程的方法大同小异,请参考帮助系统《建立和配置测试工程》部分
几个示例的产品类已加入到产品工程。这里的产品工程是一个MFC工程,您也可以使用非MFC工程
现在建立测试工程
测试工程只要符合下列条件就可以了:
能编译要测试的产品代码文件
编译链接结果是可执行文件
测试工程的名称建议为:Test+产品工程名,但不要用xxxTester,因为这是测试文件的命名格式
由于产品工程是MFC工程,测试工程也应该是MFC工程,这样才能编译产品代码文件
后面就没有其他要求了,尽可能简单就是了
配置测试工程,建议直接对照帮助中的说明进行,有问题时再参考本节的演示
启动开发环境,打开测试工程。这里以VC6.0为例,其他开发环境的配置也大同小异
设置开发环境的一些选项
这里选上,当VU生成测试代码时会自动载入。VC7/VC8的该选项位置请参考帮助系统,C++
Builder 6 无此选项
添加搜索路径
VU目录/include/
产品工程目录
测试工程设置
添加编译条件_VUNIT,如果产品工程和测试工程不是MFC工程,还要另外添加编译条件_NMFC,对于C++Builder6.0,非VCL工程则要另外添加编译条件_NVCL
这是测试执行代码,把它加在测试工程的入口中,执行这行代码后,测试结束,测试工程就可以自动退出了,也可以把return
FALSE; 改为exit(0);
VuxRunTest()在以下文件中定义:
VU目录/include/VuxRun.h
在这里包含这个文件
使用了预编译头文件的产品工程和测试工程,在预编译头文件中包含
VUnit.h 文件(包括产品工程和测试工程),不使用预编译头文件的工程,当在产品文件中添加了测试支持代码时,如果产生编译错误,在该头文件中包含
VUnit.h
在产品工程的同样位置也加上这一行
启动VU,这里使用的是个人版。配置测试工程,个人版和企业版都是一样的
设置产品工程和测试工程的目录
选择产品工程录
选择测试工程目录,注意不要选错,否则测试将不会运行
报表文件路径可以使用缺省
设置选项
看一下开发环境对不对?
如果不使用预编译头文件,要把这里清空
配置已全部完成,编译并运行测试工程,如果通过编译,弹出这个提示,表示配置正确,否则请参考帮助中编译错误方面的说明
为了便于说明,演示时产品工程和测试工程分别使用一个IDE实例,实际工作中可按照习惯处理,但使用IDE插件时,两者必须用同一个IDE实例
生成测试文件前,最好完成两项前期准备:
把产品文件加入测试工程并试编译;
在产品文件中加入测试支持代码。
单元测试是"隔离"的测试,只有能"隔离"的代码才能测试。对于VU来说,能"隔离"的意思,就是把产品文件加入测试工程后能通过编译。在生成测试文件前
将产品文件加入测试工程并编译,这样比较容易解决编译错误,因为这时的编译错误是一般的编译错误,通常与VU无关
现在我们想测试CMyClass类
把产品文件加入测试工程
试编译
果然有编译(链接)错误
这种错误是所引用的源文件未加入测试工程引起的
CMyClass类引用了这两个文件,把它们也加入测试工程
编译通过
为了访问私有成员和输出成员数据,还需要在产品文件中添加测试支持代码,具体来说,测试支持代码的功能是:可以测试私有或保护函数,并使测试用例可以访问
任何私有或保护的成员变量和成员函数;测试时可以输出成员变量的值,并且被测试类的对象在任何地方使用时(例如作为参数时),VU都可以输出它的值
测试支持代码只在测试工程中被编译,对产品工程包括调试版没有任何影响
测试支持代码由工具生成,人工拷贝到产品文件的指定位置中
填写类名
如果基类也添加了测试支持代码,则填写基类名,否则不要填写
填写成员变量名,每行一个,不包括数据类型
填写成员变量是为了在需要时输出它的值,如果成员变量很多,可以只填写重要的成员变量
用Ctrl+C拷贝这一行
粘贴到这个位置(头文件类体内)
用Ctrl+C拷贝这一行
粘贴到这个位置(头文件类体外)
拷贝这几行
粘贴到源文件
VU自动生成测试类,测试类生成后可以直接编译;自动生成测试函数,测试函数生成后自动弹出测试用例编辑器
这里打开产品文件(源文件)
当打开一个产品文件时,VU会查询是否存在对应的测试类,如果不存在,则弹出这个窗口
在生成测试文件前,最好先完成上一节所述的准备工作
已生成测试类,需手工将文件加入测试工程(使用IDE插件时会自动加入)
测试工程目录下的这两个文件就是VU刚生成的测试文件,把它们加入测试工程
从这里选择要测试的函数,如果函数不在列表中,先在源文件中编写一个空的实现
如果不存在对应的测试函数,会弹出此窗口,提示将生成测试函数
已经生成测试函数,自动弹出测试用例编辑器
填写第一个测试用例的输入数据和预期输出
编译并运行测试工程,即可执行测试
VU通过三个阶段完成彻底的测试:基本功能测试、白盒测试、边界测试。
第一阶段使用测试用例编辑器人工建立典型的测试用例,只需建立容易想到的测试用例,不必考虑测试是否完整;第二阶段在第一阶段的基础上,自动统计白盒覆盖
率,使用测试用例设计器,设计遗漏的测试用例,达到100%语句、条件、分支、路径覆盖;第三阶段使用预先定义的边界值自动生成测试用例,检查代码是否对
特殊输入作了适当处理
显示各个测试用例的输入数据,单击可选中一个
显示函数注释,以便了解函数功能,有助于设计测试用例
当前用例的输入数据和预期输出
各个子窗口均可以"最大化"
VU会生成第一个测试用例,由用户填写输入数据和预期输出。如果输入数据或预期输出比较复杂,在填完第一个测试用例后,最好先运行测试,以便检查录入错误
其他用例通过拷贝当前用例并修改的方式快速建立,点击这里就会拷贝当前用例,并把新的用例作为当前用例,修改输入输出即可建立新的用例
通常,输入数据和预期输出都要修改
可以移动当前用例的位置以便重排序
测试用例依据输入分为四类:正常输入、边界输入、非法输入、其他输入,从这里可以选定当前用例的类别
用不同的背景色区分用例的类别。
点击这里切换到代码模式,需要时可以直接编辑代码
点击"确定"保存测试用例集
先看看当参数是引用、指针、指针的指针时,VU生成的测试用例是如何处理的。这个函数,它的参数分别为对象、指针、引用、指针的指针 VU生成的代码中,全部都是对象,可以直接赋值,这样处理是为了简化问题。VU在调用这些对象时,再按参数的本来类型作适当处理 这是为了处理指针的指针而生成的中间变量,不要修改它。只有最后是"="的才是可能需要赋值的 这是测试结果 现在演示当参数是高级数据类型的情形 第一个参数是对象的引用,第二个参数是对象的指针,全部都生成对象。由于VU使用pObj代表被测试对象的指针,用ret代表返回值,所以当参数名为pObj或ret时,会加一个下划线 变量名后面的"="只表示这个变量可能需要赋值,对于基本数据类型或定义了=操作符的高级类型,可以直接赋值,其他情况可以灵活处理,只要符合C++的语法就行了 对于没有构造函数或其他初始化函数的结构,用.操作符(点操作符)给各个域赋值 如果不是直接赋值,自动生成的"="可以删除,也可以置之不理 一个结构可能有很多个域,一个对象可能有很多个成员,只要为被测试函数需要读取的域或成员设定初始值就行了,不必理会其他无关的数据 有构造函数的类,则可以直接调用构造函数。调用缺省构造函数可以不作任何修改,VU会自动删除多余的"=" 如果要调用构造函数CMyClass(int),则可以这样写... 这样就可以了,VU会自动删除最后的"=" 也可以调用对象的其他实始化函数,例如:_pObj.Init(),总之,可以使用各种C++语法为参数设定初始值 当输入输出比较复杂时,建立第一个测试用例后,最好编译并运行测试,没有编译错误时再建立其他测试用例 这是测试结果 由于没有为结构PERSON添加测试支持代码,所以这里不能显示对象的值 CMyClass类已添加测试支持代码,所以当它的对象指针作为参数时也会输出数值,这些数据输出在实际的工作中具有相当重要的作用 现在来看一下添加更多的用例 当输入输出比较复杂时,通常只是第一个用例稍麻烦些,第二个及更多的用例一般只需要修改一两个数值 当输入输出比较复杂时,请注意以下要领:1、可以使用普通C++语法;2、只为被测试函数需要读取的域或成员设定初始值;3、建立第一个测试用例后编译并运行测试,排除编译错误后再建立其他用例。 |
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |