总要去找,东西到处都是 — 勘探名言
本部分由4章组成:
- 检查产品说明书
- 闭着眼睛测试软件
- 检查代码
- 带上X光眼睛检查软件
0x00 检查产品说明书(静态黑盒子测试)
首先了解两组测试术语:
- 黑盒子测试和白盒子测试
黑盒子测试是指测试员无法看到内部如何运作,只知道进行一些输入就能得到输出结果。
白盒子测试(开盒测试)是指测试员可以看到内部运作,比如可以访问程序员的代码,并通过检查代码来协助测试。
- 静态测试和动态测试
静态测试是指测试不运行的部分,这是检查和审阅。
动态测试是指运行和使用软件,也就是一般认为的测试。
测试产品说明书属于静态黑盒子测试
当然如果测试员能够参与产品说明书的定义过程,也可以进行白盒子测试,但是进行白盒子测试时,测试员倾向于产品说明书是正确的。
对产品说明书进行高级审查
高级审查是指从一个高度审视产品说明书,而不是直接钻进去。
高级审查可以找出根本的大问题,查出是否有遗漏之处
高级审查的清单:
-
设身处地为客户着想,从客户的角度出发
-
研究现有的标准和规范
测试员要做的是检查是否套用了正确的标准,对软件进行验证和合法性检查的时候,还要注意是否和现有的标准和规范有抵触。
- 审查和测试同类软件
产品说明书的低级测试技术
低级测试技术有助于保证所有细节都被定义。
产品说明书属性检查清单
优秀的产品说明书具备以下8个属性:
- 完整:没有遗漏
- 准确:目标要正确
- 精确:定义不含糊
- 一致:功能描述不矛盾,功能不冲突
- 贴切:描述是否有多余之处
- 合理:特定预算和进度下,可实现
- 代码无关:坚持定义产品,而不是其软件设计,架构和代码
- 可测试:特性是否可测试
产品说明书用语检查清单
用语要求精确,不能含糊其辞
注意以下的用语和陈述:
- 总是,所有,从不,每一种,没有,这些肯定或绝对的用语
- 当然,因此,明显,显然,这些意图诱使接受假定情况的用语
- 某些,有时,通常,大多,几乎,这些太过模糊的用语
- 等等,诸如此类,以此类推等,以这样的结束词的功能清单无法测试
- 良好,迅速,稳定,这些没有明确定义的用语
- 已处理,已拒绝,已忽略,已消除,这些隐含大量需要说明的用语
- 如果…那么…,缺少否则结构的陈述
0x01 闭着眼睛测试软件(动态黑盒子测试)
动态黑盒子测试把软件看成一个黑盒子,测试工作是进行输入,观察输出,并检查检验结果。输入的结果是什么这个由产品说明书来指明,如果没有产品说明书,这时候的测试称为探索测试,将软件本身作为产品说明书。
动态黑盒子测试又称为行为测试。
软件测试两个基本方法:通过测试和失败测试
通过测试:确认软件能做什么,而不考验其能力;
失败测试:以破坏软件而设计的测试案例,称为失败测试或迫使失败测试。
以汽车为例,出厂后,在低速下测试称为通过测试,这时候可能会掩盖很多缺陷;然后再进行高速下的失败测试。
选择测试案例的方法:等价分配
等价分配:分步骤将过多的测试案例减少到同样有效的小范围的过程。
以测试计算器为例,1+1,1+2,1+3可以看成是一个等价区间,1+99999999999999999999999999999999就需要要看成另外一个等价区间了,因为这个和两个较小的数相加测试的是不同的软件缺陷。当然划分等价区间是一个比较主观的过程。
数据测试
对数据进行测试,即检查用户输入的数据,返回的结果和中间的计算结果是否正确。
数据测试可以根据以下原则划分等价区间:边界条件,次边界条件,空值和无效值。
边界条件
测试边界的理由是,如果软件能在极限的情况下运行,在正常情况下就不会有问题了。
最常见的例子是数组,当初始化时候注意第一个索引是0,最后一个索引是n-1,检查这两个边界条件。(当然这已经不是黑盒子测试了)。边界可以从产品说明书中找出,如一个输入框,允许的输入字符最长和最短是多少,这就是两个边界。
除了在边界线上测试外,还需要在边界线附近测试,即在边界内部(认为应该正确的)一两个数据,边界外部(认为应该错误的)一两个数据也需要测试。如一个输入框允许最长输入255个字符,就应该测试255,也需要测试254和256。
次边界条件
边界条件在产品说明书中有定义,而有些边界条件在软件内部,最终用户无法看到,这个也需要被测试。最常见的两个次边界条件是2的乘方和ASCII表。
软件是采用二进制的,所以在软件内部,2的乘方有时候会有特殊处理,所以在测试的时候需要注意2的乘方这个次边界条件。如测试1–1000范围输入时候,除了1,1000,还有0,2,999,1001之外,还想需要注意双位数据14,15,16,字节数据,254,255,256。
测试ASCII表,比如文本允许输入大小写字母,根据ASCII表,这个合法区间字符前后的值为@,[,{,这些也需要被测试。当然如果采用的不是ASCII编码的话就不需要考虑了。
空值
空值指默认值,空白,空值,零值和无。
如果一个文本框要求输入字符,那么也应该测试如果不输入任何字符时,软件是否会替换成默认值或者直接爆出错误提示。
无效值
无效值指非法的,错误的,不正确的,垃圾的数据输入。
之前的测试属于通过测试,而无效值测试属于失败测试。比如,文本框只允许输入大小写字母,那就输入数字。这一步测试需要的是创造力。
状态测试
状态指的是软件当前所处的的情况或模式。以windows画图程序为例,选择铅笔工具,鼠标变为铅笔,铅笔图标显示按下;然后选择喷枪工具,鼠标变为喷枪,铅笔工具弹起,喷枪工具按下。这就是两个状态。
状态测试就是测试软件程序的状态及其转换。
建立状态转换图
状态测试的第一步就是建立状态转换图。状态转换图必须包含以下项目:
- 每一种可能的独立状态
- 从一种状态转入另一种状态所需的输入和条件
- 进入和退出某种状态的设置条件和输出结果
减少要测试的状态及其转换的数量
有以下5种方法:
- 每种状态至少访问一次,每一种状态都必须被测试
- 测试看起来最常见最普遍的状态转换
- 测试状态之间最不常见的分支,可能会隐藏着隐蔽的软件缺陷
- 测试所有的错误状态及其返回值
- 测试随机状态转换
失败状态测试
失败状态测试的方法有竞争条件,重复,压迫和重负
竞争条件
竞争条件是为了测试软件在未预料到的操作中断中如何反应。常见的竞争条件有:
- 两个不同的程序同时保存或打开了同一个文档
- 共享同一个端口,同一台打印机
- 使用不同软件访问同一个共享数据库
重复
重复测试是指不断执行同样的操作,比如不断启动和关闭软件,可以测试软件关闭时是否正确的释放了资源。
压迫
压迫测试是指在不够理想的情况(内存小,网速慢等)下运行软件。可以测试软件对外部条件的要求和依赖程度。
重负
重负测试是指在尽量提供条件的情况下,让软件处理尽可能大的数据。如对服务器进行同时几千个模拟连接。
其他黑盒子测试的方法
像愚蠢的用户那样做
不按照规则运行软件。
在已经找到软件缺陷的地方再找找
找到的软件缺陷更多,说明软件缺陷更多。所以在已经找到的地方再找找可能会找到相似类型的软件缺陷。
经验、直觉和预感
这属于老司机的领域。
0x02 检查代码(静态白盒子测试)
静态白盒子测试就是在不运行软件的情况下,有条理的检查软件的设计,体系结构和代码的过程。静态白盒子测试也称为结构分析。
进行静态白盒子测试可以尽早的发现软件缺陷,也可以为后续的黑盒子测试案例设计提供思路。
正式审查
正式审查是进行静态白盒子测试的过程。
有4个基本要素:
- 确定问题,除了找出软件的问题,也要找出软件遗漏的项目
- 遵守规则,按照一套固定的规则进行
- 准备,每一个合作者都必须做好审查的准备
- 编写报告,审查结果的书面报告
正式审查有以下三种方式。
同事审查
最简单的正式审查方法。通常是编写程序的程序员和审查者之间进行,一起审核代码,查找问题。
公开陈述
比同时审查更加正规,编写程序的程序员向小组其他成员陈述自己的代码,并接收提问。
检验
检验是最正式的审查。不同于前两种审查的是,代码的表述者不是编写代码的人。另外的参与者是检验员,其从用户,测试者的角度来审查代码。
检查是否符合编码标准和规范
之所以要符合编码标准和规范,是因为按照编码标准和规范写的软件有以下特性:
- 可靠性
- 可读性/可维护性
- 移植性
编码标准和规范要注意和编码风格区分,如if语句大括号另起一行还是在当前行,代码风格没有正确与否。
通用代码审查清单
数据引用错误
使用未经正确初始化和引用方式的变量、常量、数组、字符串等。
数据声明错误
不正确声明或使用变量和常量,如变量名是否合法。
计算错误
检查是否有数学逻辑上的错误,如除数为0。
比较错误
大于,小于,等于,不等于,真,假。比较和判断错误很可能是边界问题。
控制流程问题
如循环结构未按照预想的工作,通常这是计算错误或比较错误直接或间接导致的。
子程序参数错误
子程序不正确地传递数据。
输入/输出错误
包括文件读取,接收键盘或鼠标输入以及向打印机或屏幕终端输出设备写入错误。
其他检查
- 编码检查
- 软件是否要孪到其他编译器或CPU,具有许可吗?有计划和测试吗?
- 是否考虑了兼容性
- 程序编译时出现的警告或者提示信息,有可能潜伏着软件缺陷
0x03 带上X光眼镜检查软件(动态白盒子测试)
动态白盒子测试不仅仅是查看代码,还包括直接测试和控制软件。动态白盒子测试包括以下4个部分:
- 直接测试底层功能、过程、子程序和库。
- 以完整程序的方式从顶层测试软件。
- 从软件获得读取变量和状态信息的访问权,以便确定测试与预期结果是否相符。
- 估算执行测试时“命中”的代码量和具体代码,然后调整测试,去掉多余的,补充遗漏的。
动态白盒子测试也成为结构测试。
在进行白盒子测试之前,一定要先根据测试说明书建立黑盒子测试案例,然后再根据白盒子知识对案例进行进一步提炼。
动态白盒子测试和调试的区别
两者所用的技术类似,但目标不同。动态白盒子测试的目标是为了找出软件缺陷,而调试是为了修复它。
单元测试和集成测试
在底层进行的测试被称为单元测试或者模块测试,等到单元经过测试,底层软件缺陷被找出和修复之后,就集成到一起,对模块进行集成测试。
如果在单元测试中发现问题,那么问题就在单元中;如果在集成测试中发现问题,那么就一定与单元之间的交互有关系。
这种递增测试有两种途径:自底向上和自顶向下。
自底向上
在自底向上测试中,需要编写称为测试驱动的模块测验正在测试的模块。测试驱动模块以将来真正模块的方式挂接,向处于测试的模块发送测试案例数据,接受返回结果,验证结果是否正确。
自顶向下
如图,为了测试顶层的显示模块,编写了一段称为存根的代码作为接口模块,从文件中把温度值直接提供给显示模块。
测试驱动和存根的区别就是:测试驱动是替代顶层模块,而存根是替代底层模块。
白盒子测试也可以像黑盒子一样分为数据范围和代码范围的测试。
数据范围
数据范围的测试有以下4种类型:
数据流
数据流范围是指在整个软件中跟踪一批数据。如利用调试器跟踪一个变量的值。
次边界
参考之前的ASCII表和2的乘方次边界条件。
公式和等式
如以下公式:
在黑盒子测试时,可能会设计一个n=0的测试案例,但是如果知道了这个公式,那么就会发现n=0会导致除数为0的错误。
错误强制
利用调试器,修改某一个变量的值。如前面的公式,可以强制n=0,来测试软件对错误的处理是否正确。当然如果在之前的代码中,有对n检查大于0的话,这个测试案例就是非法的。
代码范围
代码范围测试有以下3中类型:
程序语句和代码行范围
保证每个语句都被执行到,但是这个并不能保证找遍了软件的所有途径。
分支范围
if date == '2017-01-01':
print('happy new year')
print('date is %s'%date)
在上述代码中,为了达到100%的覆盖率,需要赋值date
为'2017-01-01'
,测试了所有的语句,但是并没有测试所有的分支,还应该测试其他日期。
条件范围
if date == '2017-01-01' and time == '00:00:00':
print('happy new year')
print('date is %s, and time is %s'%(date,time))
在条件范围中,每一种可能都要考虑到,所以设计了以下4个案例:
date | time |
0000-01-01 | 11:11:11 |
0000-01-01 | 00:00:00 |
2000-01-01 | 11:11:11 |
2000-01-01 | 00:00:00 |
但是如果按照分支范围,前三个根据等价分配,可以合并为一个案例。