一 : Python单元测试正确使用规则
Python中有一种测试方法叫做单元测试。它的使用可以给我们开发人员在实际程序开发中带来非常大的好处。在这里我们就可以通过本文介绍的关于Python单元测试的相关内容来对这一方面的知识有一个相应的了解。
测试是一个贯穿于整个开发过程的连续过程,从某个意义上说,软件开发的过程实际上就是测试过程。正如Martin Fowler所说的"在你不知道如何测试代码之前,就不该编写程序。而一旦你完成了程序,测试代码也应该完成。除非测试成功,你不能认为你编写出了可以工作的程序。"
测试最基本的原理就是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败。为了更好地理解PyUnit这一自动测试框架的作用,先来看一个简单的例子,假设我们要对例1中的Widget类进行测试:
例1. widget.py
- #将要被测试的类
- classWidget:
- def__init__(self,size=(40,40)):
- self._size=size
- defgetSize(self):
- returnself._size
- defresize(self,width,height):
- ifwidth0orheight<0:
- raiseValueError,"illegalsize"
- self._size=(width,height)
- defdispose(self):
- pass
采用手工方式进行Python单元测试的Python程序员很可能会写出类似例2的测试代码来,
例2. manual.py
- fromwidgetimportWidget
- #执行测试的类
- classTestWidget:
- deftestSize(self):
- expectedSize=(40,40);
- widget=Widget()
- ifwidget.getSize()==expectedSize:
- print"test[Widget]:getSizeworksperfected!"
- else:
- print"test[Widget]:getSizedoesn'twork!"
- #测试
- if__name__=='__main__':
- myTest=TestWidget()
- myTest.testSize()
稍一留心你不难发现这种手工测试方法存在许多问题。首先,测试程序的写法没有一定的规范可以遵循,十个程序员完全可能写出十种不同的测试程序来,如果每个 Python程序员都有自己不同的设计测试类的方法,光维护被测试的类就够麻烦了,谁还顾得上维护测试类。其次,需要编写大量的辅助代码才能进行单元测试,例1中用于测试的代码甚至比被测试的代码还要多,而这毫无疑问将增大Python程序员的工作量。
为了让单元测试代码能够被测试和维护人员更容易地理解,最好的解决办法是让开发人员遵循一定的规范来编写用于测试的代码,具体到Python程序员来讲,则是要采用 PyUnit这一自动测试框架来构造单元测试用例。目前PyUnit已经得到了大多数Python开发人员的认可,成了事实上的Python单元测试标准。如果采用 PyUnit来进行同样的测试,则测试代码将如例3所示:
例3. auto.py
- fromwidgetimportWidget
- importunittest
- #执行测试的类
- classWidgetTestCase(unittest.TestCase):
- defsetUp(self):
- self.widget=Widget()
- deftearDown(self):
- self.widget=None
- deftestSize(self):
- self.assertEqual(self.widget.getSize(),(40,40))
- #构造测试集
- defsuite():
- suite=unittest.TestSuite()
- suite.addTest(WidgetTestCase("testSize"))
- returnsuite
- #测试
- if__name__=="__main__":
- unittest.main(defaultTest='suite')
在采用Python单元测试框架后,用于测试的代码做了相应的改动:
用import语句引入unittest模块。
让所有执行测试的类都继承于TestCase类,可以将TestCase看成是对特定类进行测试的方法的集合。
在setUp()方法中进行测试前的初始化工作,并在tearDown()方法中执行测试后的清除工作,setUp()和tearDown()都是TestCase类中定义的方法。
在testSize()中调用assertEqual()方法,对Widget类中getSize()方法的返回值和预期值进行比较,确保两者是相等的,assertEqual()也是TestCase类中定义的方法。
提供名为suite()的全局方法,PyUnit在执行测试的过程调用suit()方法来确定有多少个测试用例需要被执行,可以将TestSuite看成是包含所有测试用例的一个容器。
虽然看起来有点复杂,但PyUnit使得所有的Python程序员都可以使用同样的Python单元测试方法,测试过程不再是杂乱无章的了,而是在同一规范指导下进行的有序行为,这就是使用PyUnit这一自动单元测试框架所带来的最大好处。
二 : 单元测试规范 初学者必看
应用软件 单元测试规范 版本:1.0
北京XX出品有限公司
单元测试规范
版本说明
第 1 页 共 17 页
单元测试规范
目录
1 引言.......................................................... 3
1.1 编写目的.................................................................................................................. 3
1.2 背景.......................................................................................................................... 3
1.3 定义.......................................................................................................................... 3
1.4 参考文档.................................................................................................................. 3
2 单元测试........................................................ 4
2.1 单元的定义.............................................................................................................. 4
2.2 角色工作体系.......................................................................................................... 4
2.3 单元测试规程.......................................................................................................... 4
2.4 单元测试工具.......................................................................................................... 5
2.5 测试的目录结构...................................................................................................... 5
2.6 测试代码的书写规范.............................................................................................. 6
2.7 测试单元的文件组成及命名规范.......................................................................... 6
2.8 单元测试的实施...................................................................................................... 6
3 测试结果提交和验收 .............................................. 8
3.1 单元测试工作产品提交.......................................................................................... 8
3.2 单元测试工作产品验收规范.................................................................................. 9
附录一:代码审查单 ............................................... 10
附录二:单元测试 Bug 清单.......................................... 13
附录三:驱动模块(类)模板 ........................................ 14
附录四:单元测试实例介绍.......................................... 17 第 2 页 共 17 页
单元测试规范
1 引言
1.1 编写目的
1.1.1 编写目的
本文档规定了应用软件系统和部分系统平台模块的单元测试方法和步骤、测试用例的设计方法、测 试代码的书写规范、流程以及单元测试的产品提交和验收规范,目的在于控制单元测试的质量,加强项 目的质量管理,从而提高整个产品的质量。
1.1.2 适用范围
主要是应用软件的单元测试、部分系统平台软件模块测试。
1.1.3 预期读者
本文档的预期读者为项目的项目经理、产品经理、系统软件主研人员、应用软件主研人员、高级测 试人员等。
1.2 背景
XXXXXX 系统软件平台是项目的重要组成部分,主要是依托 GUI 子系统、分析子系统和数据采集子 系统的硬件环境,共同为高层的应用软件提供必要的软、硬件功能支持,并为应用软件开发人员提供必 要的开发环境和测试环境。本规范的提出和制订旨在为软件单元测试提供依据和支持。
1.3 定义
被测模块:需要进行模块级测试的应用软件系统的一个单元或模块,也称被测单元 测试单元:用于对被测模块进行单元级测试,由源代码、测试脚本和输入数据等构成的程序单元
1.4 参考文档
[1] CppUnit Documentation
[2] gprof homepage
[3] gcov homepage
[4] 应用软件编写规范
[5] DemoUnit 测试单元
[6] 单元测试培训材料
[7] 单元测试总结报告
第 3 页 共 17 页
单元测试规范
2 单元测试
2.1 单元的定义
对于结构化的编程语言,程序单元指程序中定义的函数或子程序。单元测试是指对函数或子程序所 进行的测试。
对于面向对象的编程语言,程序单元指特定的一个具体的类或相关的多个类。单元测试主要是指对 类方法的测试。
2.2 角色工作体系
2.3 单元测试规程
包括静态的代码审查和动态测试两个阶段。 代码审查是按照《代码审查单》中的条项对单元模块进行逐项检查,并填写《单元测试 Bug 清单》。
《代码审查单》的格式见附录一,《单元测试 Bug 清单》见附录二。
动态测试阶段首先编写驱动模块(或主类)和桩模块后,在驱动模块和桩模块中设计相应的测试用 例,对所有的测试用例进行统一编号,在源代码中进行注释标识。测试用例应该覆盖单元模块的所有功 能项,如果单元模块有性能、余量等其它测试特性要求,则必须设计相应的测试用例测试这些特性,编 制完测试用例后,把测试用例提交给配置管理员或测试主管进行审查,审查没有通过则根据审查意见进 行修改,直到审查通过后测试人员加载测试用例,编译运行得到测试结果,比对测试结果,如果发现错 误或 Bug 则需要填写《单元测试 Bug 清单》并提交给测试经理和配置管理人员。 在进行功能测试时,可
以利用其它测试工具进行内存溢出分析、代码覆盖率分析、代码性能测试等。
2.3.1 代码审查
要求:根据《代码审查单》中的要求,对被测试单元进行逐项检查,检查后在对应的条项后进行 标记,发现问题后,填写《代码单元测试 Bug 清单》并提交。
2.3.2 测试用例
测试用例是测试数据及与之相关的测试规程的一个特定的集合,它是为验证被测试程序(为测试路 径或验证是否符合特定需求)而产生的。
测试用例设计用于白盒测试和黑盒测试。
第 4 页 共 17 页
单元测试规范
白盒测试进入的前提条件是在测试人员已经对被测试对象有了一定的了解,基本上明确了被测试软 件的逻辑结构。过程是通过针对程序逻辑结构设计和加载测试用例,驱动程序执行,检查在不同点程序 的状态,以确定实际的状态是否与预期的状态一致。
白盒测试主要是对被测试对象进行如下测试项目:
1、 对程序模块的所有独立的执行路径至少覆盖一次;
2、 对所有的逻辑判定,真假两种情况都至少覆盖一次;
3、 在循环的边界和运行界限内执行循环体;
4、 测试内部数据结构的有效性等。
白盒测试达到的目标:语句覆盖率达到 100%,分支覆盖率达到 100%,覆盖程序中主要的路径,主 要路径是指完成需求和设计功能的代码所在的路径和程序异常处理执行到的路径。
黑盒测试是要首先了解软件产品具备的功能和性能等需求,再根据需求设计一批测试用例以验证程 序内部活动是否符合设计要求的活动。
黑盒测试主要是对被测试对象进行如下测试项目:
1、 测试程序单元的功能是否实现;
2、 测试程序单元性能是否满足要求(可选);
3、 可选的其它测试特性,如边界、余量、安全性、可靠性、强度测试、人机交互界面测试等。 黑盒
测试达到的目标:程序单元正确地实现了需求和设计上要求的功能,满足性能要求,同时程序 单元要有可靠性和安全性。
2.4 单元测试工具
项目规定使用以下测试工具实现应用软件系统单元测试和子系统集成测试,以及部分系统平台软件 模块的相关测试。
?? CppUnit:正确性测试和功能测试
?? ccmalloc:动态内存访问检查
?? gcov:代码覆盖率分析
?? gprof:代码性能分析
2.5 测试的目录结构
建议将模块单元的测试代码组织在一个单独的目录中,作为模块单元源代码目录的一个子目录,取 名为 TestDemo。在测试代码目录下分布创建 5 个子目录分别对应 PC Linux、PXA250 评估板、IXP425 评估板、PXA255 目标板、IXP425 目标板的测试目录,用于构建、执行单元测试、管理测试日志和测试 报告。
第 5 页 共 17 页
单元测试规范
2.6 测试代码的书写规范
其规范见附录三。
2.7 测试单元的文件组成及命名规范
每个测试单元由测试代码文件、程序主函数文件和编译运行脚本文件组成,单元测试完成之后还生 成一系列测试报告,这些测试报告将与模块单元一起提交。
为了便于管理,对组成测试单元的各个文件及测试生成的测试结果和测试报告文件的命名都从被测 类/模块派生而来。假定被测类为 DemoClass,测试单元包含如下文件及其所处目录位置如下所述:
1) 测试单元文件 TestDemo/DemoClassTest.h:
测试类头文件 TestDemo/DemoClassTest.cpp:测
试类实现文件 TestDemo/DemoUnitMain.cpp:测
试类主函数
TestDemo/$(运行平台)/Makefile:用于特定运行平台的 makefile 文件
TestDemo/$(运行平台)/DemoTestDemo:为特定运行平台生成的可执行程序
其中运行平台为:PC Linux、PXA250 评估板、PXA255 目标板、IXP425 评估板、IXP425 目标板 5 种。
2) 测试结果文件
TestDemo/$(运行平台)/DemoUnit-O0.log:采用-O0 编译的正确性测试结果文件
TestDemo/$(运行平台)/DemoUnit-O2.log:采用-O2 编译的正确性测试结果文件
TestDemo/$(运行平台)/DemoUnit-O3.log:采用-O3 编译的正确性测试结果文件
TestDemo/$(运行平台)/DemoUnit.ccmalloc:内存检查结果文件
TestDemo/$(运行平台)/DemoClass.gcov:DemoClass.cpp 的代码覆盖率结果文件
TestDemo/$(运行平台)/DemoUnit.gprof:DemoUnit 被测单元的代码性能分析结果文件
其中运行平台为:PC Linux、PXA250 评估板、PXA255 目标板、IXP425 评估板、IXP425 目标板
2.8 单元测试的实施
按照单元测试规程进行实施,进行代码审查和动态测试。
1) 单元测试或集成测试涉及的源程序三种:被测类/被测单元、已通过的类/桩模块、测试单元。
只需对被测类进行测试设计、进行代码覆盖率分析和代码性能分析,用多种优化编译选项进行 编译和测试;
2) 不需为已通过的类/桩模块进行测试设计,这些模块单元和测试单元本身都进行代码不需要使用
ccmalloc、gcov 和 gprof 等工具要求的编译选项和编译优化选项进行编译,也不需要为其生 成.gcov 代码覆盖率报告。
3) 对于各种运行平台下,都需要使用-O0, -O2, -O3 三种编译优化选项对测试单元进行编译,并
运行一个测试单元中的所有测试用例,生成测试报告
第 6 页 共 17 页
单元测试规范
2.8.1 单元模块正确性测试
进行单元正确性测试的过程是将被测单元源程序、测试单元源程序和测试主函数程序放到一起编译 产生可执行程序,并在目标平台上运行可执行程序,即可获得测试结果报告。对应上述的 DemoClass 被测类的正确性测试过程的命令序列为:
$(CC) $(OPT) -c DemoClass.cpp ;编译被测类
$(CC) -c DemoClassTest.cpp
$(CC) -c DemoUnitMain.cpp
$(CC) -o DemoTestDemo DemoClass.o DemoClassTest.o DemoUnitMain.o -lstdc++ -lcppunit ./DemoTestDemo ;运行测试
./DemoTestDemo DemoUnit$(OPT).log ;生成单元测试结果文件,该文件随模块一起提交
其中,变量 CC 为 C/C++编译器,如 gcc/g++;$(OPT)为编译优化选项。 项目要求每个被测模块在用-O0, -O2 和-O3 三种编译选项进行编译,并分别进行正确性测试。
2.8.2 单元内存溢出检查
项目要求用 ccmalloc 内存检查工具对被测单元进行内存溢出检查,测试过程与正确性测试相似, 只是要求被测单元代码的编译和最后的连接命令前添加 ccmalloc 命令,如下命令序列所示:
ccmalloc $(CC) $(OPT) -c DemoClass.cpp
$(CC) -c DemoClassTest.cpp
$(CC) -c DemoUnitMain.cpp
ccmalloc $(CC) -o DemoTestDemo DemoClass.o DemoClassTest.o DemoUnitMain.o -lstdc++ -lcppunit
./DemoTestDemo ;运行测试,产生内存检查结果显示于屏幕
./DemoTestDemo 2> DemoUnit.ccmalloc ; 运行测试,产生内存检查结果文件用于提交
2.8.3 测试代码覆盖率分析
项目要求用 gcov 工具对测试单元的代码覆盖率进行分析,测试单元的代码覆盖率分析的命令序列 如下所示:
$(CC) $(OPT) -c -g -fprofile-arcs -ftest-coverage DemoClass.cpp -fprofile-arcs
;对被测代码使用-g -ftest-coverage 等编译选项
$(CC) -c DemoClassTest.cpp
$(CC) -c DemoUnitMain.cpp
$(CC) -o DemoTestDemo DemoClass.o DemoClassTest.o DemoUnitMain.o -lstdc++ -lcppunit ./DemoTestDemo ;运行测试
gcov DemoClass.cpp > DemoClass.gcov.sum ;对每个被测源程序生成 2 个覆盖率结果文件
; DemoClasscpp.gcov 和 DemoClass.gcov.sum
;前者包含源代码每条语句的执行计数,
;后者包含一个该文件覆盖率统计
cat DemoClass.gcov.sum DemoClass.cpp > DemoClass.gcov ;合并以上两个代码覆盖率文件, 第 7 页 共 17 页
单元测试规范
;最后提交合并后的文件 2.8.4 模块单元代码性能分析
项目还要求用 gcov 工具对测试单元的代码性能进行分析,测试单元的代码性能分析的命令序列如 下所示:
$(CC) $(OPT) -c -g -pg DemoClass.cpp ;对被测类使用-g -pg 等编译选项
$(CC) -c DemoClassTest.cpp
$(CC) -c DemoUnitMain.cpp
$(CC) -pg -o DemoTestDemo DemoClass.o DemoClassTest.o DemoUnitMain.o -lstdc++ -lcppunit ./DemoTestDemo ;运行测试
gprof -pg DemoTestDemo >DemoUnit.prof ;产生性能分析结果文件
3 测试结果提交和验收
3.1 单元测试工作产品提交
项目要求随模块提交 2.8 列出的 5 种测试单元文件和 6 种测试结果和测试报告文件,而每增加一种 被测类,提交时要求增加相应的测试类文件和代码覆盖率报告文件。
3.1.1 提交的测试产品
1 对于每个被测类的测试文档产品
?? 测试类头.h 文件
?? 测试类实现.cpp 文件
?? PC Linux 平台和 2 个 XScale 平台(2 个 PXA25X 平台或 2 种 IXP425 平台)下的代码覆盖率.gcov
文件
2 对于每个测试单元的测试文档产品
?? 测试类主函数.cpp 文件
3 对于每种运行平台的测试文档产品
对于每个测试单元需要提在 PC Linux 平台和 2 个 XScale 平台(2 个 PXA25X 平台或 2 种 IXP425 平台)下的以下文档
?? Makefile 文件
?? 内存检查结果.ccmalloc 文件
?? 代码覆盖率分析.gcov 文件
?? 代码性能分析.gprof 文件
?? 利用-O0, -O2, -O3 三种编译优化选项编译被测代码时产生正确性测试结果.log 文件 4 单元测试总结报告.report
TestDemo/DemoUnit.report:总结单元测试情况,需要手工书写。内容包括 4 个部分:
?? 被测类名:列出所有被测类的类名
?? 测试用例:按被测类列出所有测试用例及其描述信息,主要是用例源程序代码和相应的注释信
息。
?? 正确性测试报告:列出每种运行平台下测试单元运行的测试结果。从具有最高编译选项并且通 第 8 页 共 17 页
单元测试规范
过了全部测试用例的测试报告中拷贝 ?? 代码覆盖率测试结果:列出测试单元在任意平台下运行时,被测类的代码覆盖率信息。从相应
被测类的.gcov 文件中拷贝。
一个 Demo 单元测试总结报告请参考 DemoUnit.report[9]。
3.1.2 测试产品提交方式
单元编码/测试人员应该在所有测试项目完成之后,删除所有无关的临时文件,仅留下需要提交的 项目,然后将 TestDemo 目录作为一个整体保留其目录结构进行提交。最后手工完成一个文本格式的单 元测试总结报告。
3.2 单元测试工作产品验收规范
项目的模块单元提交时,要对-O0、-O2 和-O3 三种编译优化的正确性测试报告.log 文件、每个被 测类/被测源文件的代码覆盖率结果.gcov 文件和内存检查结果.ccmalloc 文件。
通过的准则如下:
1) 正确性测试结果文件:在所有运行平台下,至少在一种编译优化选项下通过了全部的测试用例,
保证测试用例覆盖了单元模块中的所有功能点;
2) 其它测试特性结果文件:在所有运行平台下,测试覆盖该模块所要求的其它测试特性并测试通
过;
3) 内存检查结果文件:在所有运行平台下,运行所有测试用例之后未发生内存泄漏;
4) 代码覆盖率文件:在所有运行平台下,每个被测类/ 被测文件的可执行语句的代码覆盖率达到
100%;
4) 每一个单元测试 Bug 清单都处于一个明确的状态,不能改正的必须给出详细的解释说明;
5) 单元测试工作产品的验收采用同级评审的方法,由评审组决定测试是否通过,来保证单元测试 的质量和软件产品的质量。
第 9 页 共 17 页
单元测试规范
附录一:代码审查单
代码审查单
第 10 页 共 17 页
单元测试规范
第 11 页 共 17 页
单元测试规范
第 12 页 共 17 页
单元测试规范
附录二:单元测试 Bug 清单
单元测试 Bug 清单
第 13 页 共 17 页
单元测试规范
附录三:驱动模块(类)模板
一般情况下,应用软件系统每个被测单元由一个 C++类组成,由一些的.h 头文件和.cpp 类实现文 件组成。则测试单元通常可以由 3 个文件组成,测试单元头文件,测试单元实现文件和测试主函数文件。 假定被测类类名为 DemoClass,测试单元命名为 DemoUnit,如果一个测试单元只测试一个被测类,可以 使 DemoUnit 与 DemoClass 一致,则这 3 个文件分别取名为:
?? 测试单元头文件:DemoClassTest.h
?? 测试单元实现文件:DemoClassTest.cpp
?? 测试主函数文件:DemoUnitMain.cpp
以下以描述这 3 个的框架结构。一个完整的 Demo 可以参考 DemoClass 测试单元[7]。
1) 测试单元头文件
测试单元头文件采用 CppUnit 规范定义测试类,声明测试用例方法。对于被测类 DemoClass, 其测试单元头文件取名为 DemoClassTest.h,其结构如下所示:
/* DemoClass 测试代码头文件
#include "../DemoClass.h" */ */ /* 包含被测单元的头文件(在上层目录中)
#include <cppunit/TestFixture.h> /* 使用 TestFixture 类 */
#include <cppunit/extensions/HelperMacros.h> /* 使用 Helper Macros */
#include <cppunit/TestSuite.h> /* 使用 TestSuite 类*/
class DemoClassTest : public CppUnit::TestFixture
*/
{
public:
CPPUNIT_TEST_SUITE( DemoClassTest ); /* 声明 TestSuite 名,与测试类一致 */
CPPUNIT_TEST( test_tc1 ); /* 在 TestSuite 中添加测试用例 */
CPPUNIT_TEST( test_tc2 ); /* 在 TestSuite 中添加测试用例 */
??
CPPUNIT_TEST_SUITE_END(); /* 在 TestSuite 中添加其他测试用例 */ /* TestSuite 声明结束 */ /* 继承 TestFixture 定义测试类
protected:
demo_unit *unit1, *unit2, *unit3;
setup()函数中
*/
??.
public:
void setUp();
void tearDown();
void test_tc1();
void test_tc2(); /* 测试准备或建立测试环境 */ /* 测试结束撤销测试环境,如释放动态变量等 */ /* 测试用例方法定义 */ /* 测试用例方法定义 */ /* 测试过程涉及的被测类对象指针,在 动态建立并初使化,在 teardown() 函数中撤销
第 14 页 共 17 页
单元测试规范
??.
?????
} /* 其他测试用例方法声明 */ */ /* 开发者自定义的其他数据成员和方法成员定义
2) 测试单元实现文件
测试单元实现文件实现测试单元头文件中定义的各个测试用例方法和测试类的其他方法成员。对应 上述测试单元头文件,相应的测试单元实现文件为 DemoClass.cpp,其结构表示如下:
/* demo unit 测试单元 源代码 */
#include "DemoClassTest.h" /* 包含 DemoClass 的测试单元头文件 */
#include <string.h> /* stl 的 std::string 类 */
#include <iostream.h> /* io 流定义头文件 */
#include <cppunit/TestAssert.h> /* 程序中用到了 TestAssert 类 */
/* 在 CppUnit 中注册 DemoClass 的 TestSuite,测试类名一致 */
CPPUNIT_TEST_SUITE_REGISTRATION( DemoClassTest);
void DemoClassTest::setUp() /* 建立测试环境
{
unit1 = new DemoClass( 1, 2 );
?..
*/ */ /* 如创建被测类对象 }
void DemoClassTest::tearDown()
{
delete unit1;
??
}
void DemoClassTest::test_tc1()
{ /* 销毁测试环境 /* 释放被测对象 */ */ /* 的测试用例方法 1 的实现 */
/* 测试用例方法的实现代码,测试人员在代码中调用被测模块的方法进行测试,通过 CppUnit 的 ASSERT 宏检查被测模块代码的运行是否正确,并报告异常 */
/* 执行到测试用例方法的最后,意味在此之前没有发生测试异常事件,意味者本测试用例成 功,添加一个语句输出本测试用例信息及其测试成功的信息,其格式为:
"PASS: <测试用例方法名称>,<测试用例功能描述> <换行符> */
cout<<"PASS: test_tc1,测试 DEMO CLASS 的构造函数正确性\n";
}
?????? /* 最后添加测试类其他方法的实现 */
3) 测试主函数文件
测试单元主函数用于执行测试类中定义的各种测试用例方法,执行各个测试用例,如果我们充 分利用 CppUnit 提供的宏来书写测试单元,测试单元主函数可以设计成与被测模块和测试类无关, 而对所有被测模块使用同一个测试主函数文件。
第 15 页 共 17 页
单元测试规范
被测模块 DemoClass 的测试驱动程序文件名为:DemoUnitMain.cpp。该程序的内容如下:
/* 单元测试主函数,固定不变 */
#include <cppunit/TextTestResult.h>
#include <cppunit/TestSuite.h>
#include <vector>
#include <iostream>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestCase.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/CompilerOutputter.h>
#include <vector>
#include <iostream>
int main( int argc, char **argv)
{
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry
CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest( registry.makeTest() );
TestSuite */ ®istry = /* 加 载 测 试 类 实 现 文 件 中 注 册 的
/* 运行所有 TestSuite */ bool wasSucessful = runner.run( "", false );
return wasSucessful ? 0 : 1;
}
4) 编程规范
以上从 CppUnit 测试工具的特点列出测试单元的程序结构,每个 C/C++测试程序文件应的编程 风格和规范应该遵从应用软件编程规范[6]的要求。
第 16 页 共 17 页
单元测试规范
附录四:单元测试实例介绍
DemoUnit 示例测试单元介绍
该 DemoUnit 包括 DemoClass 和 Complex 两个被测类。DemoUnit 中按照上述规范设计了 DemoClass 的测试类代码,但 Complex 的测试类并没有按以上规范设计。
在 PC Linux 平台下执行测试
在 TestDemo/PC Linux/Makefile 文件实现了在 PC Linux 下执行测试和生成各类测试报告的脚本。 测试执行方法介绍如下:
1) 执行正常测试,查找模块缺陷,显示测试结果
make default -i
2) 生成正确性测试报告.log 文件和代码覆盖率文件
make gcov -i OPT=-O0
make gcov -i OPT=-O2
make gcov -i OPT=-O3
3) 内存溢出分析
make ccmalloc -i
4) 代码性能分析
make -i gprof
5) 删除各种中间临时文件
make clean
第 17 页 共 17 页
三 : 单元测试编写规范
单元测试编写规范
单元测试规范 单元测试编写规范
文件修改控制
单元测试规范 单元测试编写规范
目录
第一章文档介绍 ............................................................................................................................... 4
目的........................................................................................................................................... 4
阅读对象 ................................................................................................................................... 4
第二章概述....................................................................................................................................... 4
2.1 定义 ................................................................................................................................... 4
2.2 目的 ................................................................................................................................... 4
2.3 步骤 ................................................................................................................................... 4
2.4 常见模块单元的错误 ........................................................................................................ 5
第三章单元测试步骤 ....................................................................................................................... 6
3.1 设计单元测试方案 ............................................................................................................ 6
3.1.1 输入、输出 ........................................................................................................... 6
3.1.2 任务 ....................................................................................................................... 6
3.2 编写单元测试CASE .......................................................................................................... 7
3.2.1 输入、输出 ........................................................................................................... 7
3.2.2 任务 ....................................................................................................................... 7
3.3 执行单元测试 .................................................................................................................... 9
3.3.1 输入、输出 ........................................................................................................... 9
3.3.2 任务 ....................................................................................................................... 9
3.4 分析单元测试结果 ............................................................................................................ 9
3.4.1 输入、输出 ........................................................................................................... 9
3.4.2 任务 ..................................................................................................................... 10
单元测试规范 单元测试编写规范
第一章 文档介绍
目的
本文档是关于进行单元测试(Unit Test)的规范性文档,本文档中描述了单元测试的原则、流程和方法,是软件开发人员在进行单元测试时的工作指南。[www.61k.com)
阅读对象
本文档适合以下人员阅读
? 项目经理
? 软件开发工程师
? 软件测试工程师
第二章概述
2.1 定义
单元测试是对软件基本组成单元进行的测试,所谓“单元”是指:
? 具有明确的功能
? 具有明确的规格定义(详细设计说明书)
? 有与其他部分明确的接口定义
? 能够与程序的其他部分清晰地进行区分
2.2 目的
单元测试用例的设计是要验证被测程序单元的如下这些方面:
1) 是否正确实现了规定的功能
2) 模块内部是否存在错误
2.3 步骤
单元测试的侧重点在于发现程序设计或者实现中的逻辑错误。它分为计划、设计、实现、执行和评估五个步骤。各步骤的定义如下:
1) 计划单元测试
确定测试需求,制订测试策略,确定测试所用资源,创建测试任务的时间表。
单元测试规范 单元测试编写规范
2) 设计单元测试
设计单元测试模型,制订测试方案,确认测试过程
3) 实现单元测试
根据单元测试计划和方案,制订具体的测试用例,创建可重用的测试脚本。[www.61k.com)
4) 执行单元测试
根据单元测试的方案、用例对软件单元进行测试,验证测试结果并记录测试过程中出现的缺陷。
5) 评估单元测试
对单元测试的结果进行评估,主要从需求覆盖和代码覆盖的角度进行测试完备性的评估。
2.4 常见模块单元的错误
模块内部错误往往存在于下列方面:
1) 模块接口:测试模块的数据流
a) 调用所测模块时输入参数与模块的形式参数在个数、属性、顺序上是否匹配
b) 所测模块在调用其他模块时,它输入给其他模块的参数在个数、属性、顺序上是否
匹配
c) 是否修改了只做输入用的形式参数
d) 输出给标准函数的参数在在个数、属性、顺序上是否匹配
e) 全局变量的定义在各模块中是否一致
f) 限制是否通过形式参数来传递
2) 局部数据结构:
a) 不正确的或者不一致的数据类型说明
b) 使用未赋值或者未初始化的变量
c) 错误的初始值或者错误的默认值
d) 变量名拼写错误
e) 不一致的数据类型
3) 路径错误:不正确的计算、比较和控制流
4) 错误处理
a) 出错的描述难以理解
b) 出错的描述不足以对错误定位和确定出错原因
c) 显示的错误与实际错误不符
d) 对错误条件的处理不正确
e) 在对错误进行处理之前,错误条件已经引起了系统的干预
5) 边界
a) 在循环的第0次,第一次和最后一次是否有错误
b) 运算或者判断中最大最小值是否有错误
c) 数据流、控制流中刚好大于、小于或等于最大或最小值时是否有错误
单元测试规范 单元测试编写规范
第三章单元测试步骤
3.1 设计单元测试方案
3.1.1 输入、输出
3.1.2 任务
1. 设计单元测试的模型,一般如下图所示
构造单元测试模型需要:
? 定义(设计)驱动模块,用以调用被测程序单元
? 定义(设计)测试桩模块,用以模拟被测程序单元调用的函数接口
? 设计测试数据和状态,准备单元测试的动态结构
? 确定测试的流程
另外,测试模型也可能是由所采用的测试工具所决定的。(www.61k.com)
2. 指定测试项目
指定对不同特性(或者特性组合)进行充分测试的途径,包括测试工具、方法和技术的描述以及对测试结果进行提取和分析的方法。
3. 定义测试完备性标准(例如代码覆盖、路径覆盖或者条件覆盖),并规定判定测试完备性的手段,例如利用工具或者设计测试代码等。
单元测试规范 单元测试编写规范
3.2 编写单元测试CASE
3.2.1 输入、输出
3.2.2 任务
1. 根据《XXX单元测试方案》构造测试环境(将待测程序单元纳入测试工具,实现驱动模
块和桩模块),编写测试代码(自己开发或使用测试工具)。[www.61k.com]需要的时候生成或者导入测试所需要的数据。
2. 设计单元测试用例
设计测试用例的时候要根据《XXX单元测试方案》中所规定的测试方法、测试项目和完备性标准进行。单元测试用例的设计,主要有以下五个步骤:
1) 为系统运行起来设计测试用例
首先需要设计这样的测试用例,该用例的执行可以证明测试环境和被测单元是可用的。如果连这样的测试用例都失败了,那么其他的测试用例都失去了执行的基础
2) 为正向测试而设计测试用例
其次需要设计正向测试用例。这些用例也是基本的单元测试用例,它们是用来证明设计规格说明书中对应的功能和性能指标是否能够实现。这些测试用例是按照设计说明书中的描述来开发的。
3) 为逆向测试而设计测试用例
逆向测试的测试用例是用来证明软件没有做不应该做的事情。这个步骤可以基于错误猜测的基础进行测试用例的构造。
4) 为特殊要求设计测试用例
从系统的性能、安全性、保密性的角度为具有这些要求的系统制订的测试用例。
5) 为覆盖率设计测试用例
测试用例的设计要保证一定的覆盖率要求,所以在最后一步还需要补充一些测试用例,以保证测试用例对代码、路径、或者条件的覆盖率。
在单元测试的设计中,针对测试项目和测试覆盖率的要求经常采用如下的一些方法:
A) 规格导出法
规格导出法是根据相关的规格说明来设计测试用例,每一个测试用例用来检验
一个或多个规格陈述的语句。一个比较实际的办法是按照规格陈述的语句顺序
来为被测单元设计测试用例。这种测试用例的设计可以保证在规格说明中所有
的要求在测试案例中都能得到体现,但是它只是一种正向测试的思路,需要其
他的测试用例的补充才能达成测试的完整性。
B) 等价类划分法
等价类划分是一种正式的测试用例设计方法,它基于被测单元的输入、输出所
做的划分,对每一个划分中的所有输入、被测单元都有相同(等价)的反应。
单元测试规范 单元测试编写规范
C)
D)
E)
F)
G)
H)
I) 例如对一个范围是0-100的整数输入来说,2,38,66应该都具有相同的效力,而 -1,120也有相同的效力。(www.61k.com)等价类划分法就是针对每一个等价类设计至少一个测试用例来确保被测程序单元的处理是完整的。等价类划分的设计方法也属于正向测试的技术。 边界值分析法 边界值分析法使用与等价类划分法相同的划分,只是边界值分析假定错误更多地存在于两个划分的边界上,相应地为边界上及两侧的情况设计测试用例。 状态转移测试法 对于那些以状态机作为模型或者设计为状态机的软件,状态转移测试是合适的。状态转移测试法的测试用例涵盖能导致状态迁移的事件来测试状态之间的转换是否正确。用这种方法可以测试逆向的测试用例,如状态和事件的非法组合。 分支测试法 在分支测试中,根据单元中控制流分支或者判断点来设计测试用例。这通常用于达到一定的测试覆盖率。在单元测试中,如果使用黑盒测试技术,那么需要去猜测存在哪些逻辑分支并相应为这些分支的执行准备测试用例,如果使用白盒测试技术,那么则需要根据该程序单元中的控制流设计测试用例,完成分支覆盖的要求。 条件测试法 条件测试法中包含了很多测试用例设计技术,它们都致力于弥补在遇到复杂逻辑条件的时候分支测试的弱点。条件测试的目标是测试在每个逻辑条件的单个成份及它们组合的情况下程序都是正确的。在考虑各个逻辑条件的组合的时候,决策表是一种有用的工具。 在条件测试法中,需要设计足够的测试用例,确保每种逻辑条件的组合都被测试到。 数据定义-使用测试法 数据定义是指数据被赋值的地方,数据使用是指数据项被读取或者使用的地方。使用这种方法设计测试用例时,主要考虑用用例来驱动数据被定义到被使用的路径。这种方法主要用于检查数据的初始化和处理的正确性,也可以在静态检查中使用。 内部边界值测试法 这种方法与边界值分析法类似,但是它偏重的是白盒测试技术,也就是说从程序单元的规格说明中导出等价类和边界值。除了外部可见的数据之外,程序的内部的数据也存在等价类和边界值,它们只能通过对程序单元的设计规格说明进行分析而得到。内部边界值测试法一般只作为测试用例设计的补充方法,与其他方法结合使用。 错误猜测法
错误猜测是基于经验和其他一些测试技术的。在经验的基础上,测试设计者猜测错误的类型及在特定的软件中错误发生的位置,并设计测试用例去发现它们。例如,如果所有的资源需要动态申请,那么我们就需要判断是否所有的资源都被正确释放了。一个发现错误的好地方就是资源释放的地方。对一个有经验的工程师,错误猜测法可能是最好的设计测试用例的方法,因为它可能发现别的设计方法所遗漏的错误。为了最大限度的利用有效的经验并逐步丰富测试用例的设计技术,建立一个错误类型的列表是一个好方法,这个列表可以帮助
单元测试规范 单元测试编写规范
工程师猜测程序单元中的错误会在哪里。(www.61k.com)这个列表需要通过在实践中不断的维
护和扩充来帮助达成错误猜测的有效性。
3. 将设计好的测试用例用工具或者文档记录下来。在需要的时候,标注某个测试用例是为
了哪个测试项目而设计的。一般来说,测试用例都需要注明:测试条件、测试输入、测试操作和预期输出这四大要素。
4. 将设计好的测试用例编写为测试脚本(test script)或测试程序,如果设计自动化测试,
驱动模块从测试脚本中逐条读取测试用例并且通过程序或者测试人员的目测判断程序单元的行为或者输出是否符合预期。一般来说,测试工具或者驱动模块也需要将每一条测试用例执行的结果进行记录,以供分析之用。
3.3 执行单元测试
3.3.1 输入、输出
3.3.2 任务
1. 执行单元测试用例
对单元测试用例的执行一般意味着由驱动模块读取测试脚本,然后通过程序判断或者测试人员目测判断的方式确认测试用例是否执行通过。
d) 首先应该确保测试环境和测试程序能正常执行,如果不能正常执行则需要进行相应
修改直至正常。
e) 在遇到测试用例执行失败而无法执行之后的单元测试用例时,需要调整被测程序单
元直到该用例能够正常执行。修改之后需要重新执行之前的测试用例(回归测试)。使用测试工具或者编写自动化的测试驱动模块可以使这项工作相对容易些。
2. 对测试用例的执行结果进行记录,如果使用工具或者编写了自动化的测试驱动模块,这
一步工作可以自动化。
3. 根据测试结果修改源代码,重新构造测试环境,需要的时候修改测试用例。
3.4 分析单元测试结果
3.4.1 输入、输出
单元测试规范 单元测试编写规范
3.4.2 任务
1. 分析测试的完备性,判断是否执行了事先设计的所有测试用例以及在测试过程中新增加
的测试用例。[www.61k.com)
2. 使用工具或者其他自定义的方法判断单元测试的覆盖率是否符合事先定义的覆盖率。
3. 如果未能达成覆盖率,则补充测试用例,重新执行测试。
本文标题:单元测试规范-Python单元测试正确使用规则61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1