对三种黑盒测试技术的单元测试与集成测试
[toc]
1. 被测试代码及任务说明
1.1. 被测试代码
对被测试代码进行了增删,主要增加了处理处理部分,同时使用switch-case
结构优化了代码性能,完整代码如下:
1.2. 任务说明
- 对于三种黑盒测试技术分别测试对应的测试用例生成功能及集成测试
- 单元测试需要对构件的5方面进行测试:
- 模块或构件接口
- 局部数据结构
- 边界条件
- 独立路径
- 处理错误的路径
- 需要为每个单元测试开发驱动器或/和子程序桩
- 因为本黑盒测试用例生成类已经开发完毕,各模块的子程序桩便不需要单独设计,子程序由各模块调用即可
- 驱动器程序可以为
main()
,这里会在集成测试时再设计测试方法调用三种黑盒测试用例生成方法
2. 等价类划分
2.1. 需求描述
对输入范围划分,返回一个有效区间和两个无效区间
2.2. Junit程序设计
2.2.1. 测试模块或构件接口
给出正常输入判断是否符合预期输出
2.2.2. 测试局部数据结构
本功能模块无局部变量,不予测试
2.2.3. 边界条件
对[0,1]
,[-1,0]
,[Integer.MIN_VALUE,Integer.MAX_VALUE]
容易发生错误的边界测试
2.2.4. 独立路径
- 根据代码画出对应的流图
- 代码
- 流图
- 环形复杂度CC(G)=1
- 独立路径集即
{74-75-76-77-78}
所以此前测试用例已覆盖独立路径
2.2.5. 处理错误的路径
整数溢出ArithmeticException
继承自RuntimeException
,为非受查异常,但是对于整数溢出计算过程无误而程序无法得知其计算是否正确,所以需要开发者声明此异常.这里使用[Integer.MIN_VALUE,Integer.MAX_VALUE]
测试整数溢出的错误处理.
2.3. Junit程序实现
2.4. Junit测试结果
通过三个,对于整数溢出准确报了错误,错误处理路径正常
3. 边界值分析
3.1. 需求描述
对于各区间去边界值,并返回边界值,注意返回的边界值里没有重复值.
3.2. Junit程序设计
3.2.1. 测试模块或构件接口
给出正常输入判断是否符合预期输出,包括没有重复值
3.2.2. 测试局部数据结构
本功能模块无局部变量,不予测试.
3.2.3. 边界条件
对[0,1]
,[-1,0]
容易发生错误的边界测试
3.2.4. 独立路径
- 根据代码画出对应的流图
- 代码
![](_v_images/20200423105409639_13297.png =1000x)
- 流图略,易知环形复杂度CC(G)=2
- 独立路径集:
{95-96-99-101-102-103-104-105-106-107}
{95-96-97}
包括3.2.5在内的其他测试需求中的测试用例已覆盖独立路径
3.2.5. 处理错误的路径
因为输入来自上一模块,错误输入将被拒绝;但是本模块对于边界值的处理因采取的是+1/-1/+3/-3
这样的方式,特别地,区间范围为3时将不能生成不重复的区间值,这里采用一个中间区间为3的测试用例:
{{-2147483648, 3}, {4, 7}, {8, 2147483647}}
测试处理错误的路径;同时本模块一定会发生整数越界,在主函数中已予以说明.
3.3. Junit程序实现
3.4. Junit测试结果
![](_v_images/20200423100508681_19213.png =1000x)
4. 随机数生成器
4.1. 需求描述
应用随机数生成器对每个区间生成指定数量(从命令行输入)的随机值.注意返回的值里没有重复值.
4.2. Junit程序设计
因为是返回的是随机值,这里判断输出是否符合标准代之以:
- 返回值数目是否正确
- 返回值是否有重复
- 返回值是否在区间内
4.2.1. 测试模块或构件接口
输入正常输入{{-2147483648,-6},{-5,10},{11,2147483647}},5
4.2.2. 测试局部数据结构
检查局部数据结构是为了保证临时存储在模块内的数据在程序执行过程中完整、正确,局部功能是整个功能运行的基础。重点是一些函数是否正确执行,内部是否运行正确。局部数据结构往往是错误的根源,应仔细设计测试用例,力求发现下面几类错误:
-
不合适或不相容的类型说明;
-
变量无初值;
-
变量初始化或省缺值有错;
-
不正确的变量名(拼错或不正确地截断);
-
出现上溢、下溢和地址异常。
这里测试内部关键的局部函数randomValueSet()
4.2.3. 边界条件
- 输入中间区间很小的边界条件:
{{-2147483648,-2},{-1,1},{2,2147483647}},5
- 输入左边区间很小的边界条件:
{{-2147483648,-2147483647},{-2147483646,1},{2,2147483647}},5
- 输入右边区间很小的边界条件:
{{-2147483648,-1},{0,21474836475},{2147483646,2147483647}},5
4.2.4. 独立路径
- 根据代码画出对应的流图
- 代码
![](_v_images/20200417163326890_26690.png =1129x)
- 流图
因为程序有2个终止条件,将两个条件合并为一个
- 环形复杂度CC(G)=6
- 独立路径集:
{113.1-114}
{113.1-113.2-114}
{113.1-113.2-113.3-114}
{113.1-113.2-113.3-116-117.1-117.2-120}
{113.1-113.2-113.3-116-117.1-117.2-125-126,127,128-133-117.3-117.2-120}
{113.1-113.2-113.3-116-117.1-117.2-125-126,127,128-130,131-133-117.3-117.2-120}
- 生成测试用例
前三个被边界条件生成的测试用例覆盖;第四个程序本身不允许实现;第六个被4.2.1覆盖;对第5个:
{{-2147483648,-2},{-1,1},{2,2147483647}},3
4.2.5. 处理错误的路径
边界条件的测试用例可覆盖这个错误的处理路径:java.lang.RuntimeException: 区间过小不足以生成指定数目的随机数
4.3. Junit程序实现
4.4. Junit测试结果
程序在正确处理及异常输入,错误处理各方面运行正常
![](_v_images/20200418212615537_5946.png =600x)
5. 集成测试
5.1. 需求描述
把以上通过了单元测试的模块一起够着一个在设计中所描述的程序结构.
5.2. Junit程序设计
随机数生成模块与边界值分析模块的输入为等价类划分模块的结果:
所以采用增量集成测试中的自底向上测试方法
5.3. Junit程序实现
5.4. Junit测试结果
6. Junit程序测试总结
Junit是事实上的Java开发测试标准工具,这次的实践使我很好地学会了这个工具,也使我认识到测试驱动开发是可行的并且会使得程序高度解耦,内部结构也清晰.单元测试的5个测试要求倒逼程序本身明确实现需求,考虑到各种依赖,对边界的处理,软件的扩展性以及对软件错误的处理,程序因此高内聚低耦合同时健壮性,可读性都得到提高.集成测试使开发人员需要审视全局,理清数据流走向.
对软件测试的学习与实践不仅提高了软件测试能力,也无形提高了代码开发能力,尤其是在对模块的抽象封装与代码的质量方面.