所谓软件测试,就是一个过程或一系列过程,用来确认计算机代码完成了其应该完成的功能,不执行其不该有的操作。
程序功能描述:程序从用户获取 3 个整数输入值,分别代表三角形三条边的长度。程序判断该三角形为不规则三角形、等腰三角形或等边三角形。
是否有测试用例是一个有效的不规则三角形?
是否有测试用例是一个有效的等腰三角形?
是否有测试用例是一个有效的等边三角形?
是否至少有 3 个测试用例覆盖了等腰三角形的三种情况?如:3、3、4,3、4、3,4、3、3。
是否有测试用例为某边的长度为 0 ?
是否有测试用例为某边的长度为负数?
是否有测试用例其中两边之和等于第三边的长度?
是否至少有 3 测试用例覆盖了两边之和等于第三边的全部 3 种情况?
是否有测试用例其中两边之和小于第三边的长度?
是否至少有 3 测试用例覆盖了两边之和小于第三边的全部 3 种情况?
是否有测试用例为 3 条边的长度均为 0 ?
是否有测试用例输入的边长符合不规则三角形要求但为非整数?
是否有测试用例输入的边长个数不对?
对于每一个测试用例,除了定义输入情况以外是否同时定义了相对的预期输出值?
10.特殊字符
应当一开始就假设程序中隐藏着错误,然后执行测试去尽可能多地发现程序的错误。实际上,这种假设是几乎对所有程序都成立的。所以,测试的另一种定义为:测试是为发现错误而执行程序的过程。拥有这样的观念,其实是把测试的定位拔高了一筹:测试会找出并推荐修改程序的错误,从而提高程序的可靠性和质量。
心理学影响测试的另一个效应是,人类行为总是倾向于具有高度目标性,如果我们的目的是要证明程序中不存在错误,我们潜意识中就会倾向于选择可能较少导致程序失效的测试方法和数据。反之,我们的目标定位尽可能多地发现程序的错误,就会设计并更好地执行较优的测试方法。
还有一个心理学效应或说概念,是关于“成功与否的测试”。如果认为发现了程序错误的测试称为不成功,而没有发现程序错误的称为成功,那就是本末倒置了。但基本大多数人一不留神就会倾向于这么想。需要警惕。
另一个需要警惕的是,如果软件测试的目标是证明软件做了应该做的,也就是该有的功能都有了,就不易发现软件还有一类错误:做了不该做的。
对于具有一定复杂性的程序,较真起来,测试将几乎永远也做不完。因为要发现程序中的所有错误常常是不可能的。那么到底需要做到什么程度呢?这就需要引入“经济学”的思考方法,综合多种考虑因素,合理选择合适的测试策略。
通过有限的测试用例极大限度的提高发现问题的数量,取得最好的测试效果。
回归测试:
保持测试用例,当程序其他部件发生变动后重新执行。
数据引用错误
数据声明错误
运算错误
比较错误
控制流程错误
接口错误
输入输出错误
其他检查
1、数据引用错误
1)是否有引用的变量未赋值或未初始化?
2)下标的值是否在范围之内?
3)记录和结构的属性是否匹配?
4)是否计算位串的地址?是否传递位串参数?
2、运算错误
1)是否存在非算术变量间的运算?
2)是否存在混合摸式的运算?
3)是否存在不同字长变量问的运算?
4)目标变量的大小是否小于赋值大小?
5)中间结果是否上溢或下溢?
6)是否存在二进制的不精确度?
3、数据声明错误
1)数组和字符串的初始化是否正确?
2)变量是否赋予了正确的长度,类型和存储类?
3)是否所有的变量都已声明?
4、控制流程错误
1)是否每个循环都终止了?
2)是否存在由于入口条件不满足而跳过循环体?
3)可能的循环越界是否正确?
4)是否存在“仅差一个”的迭代错误?
5、输入输出错误
1)文件的属性是否正确?文件在使用前是否打开使用后是否关闭?文件结束条件是否被正确处理?
2) I/O语句是否符合格式规范?是否处理了I/O 错误?
3)缓冲大小与记录大小是否配?
6、内存错误
1)为指针分配内存后,是否判断指针是否为null?
2)指针使用前是否赋初值?
3)数组或指针的下标是否越界?
4)内存申请和释放是否匹配?
5)将指针所指向的内存释放后,是否第一时间将指针置为null?(防止使用“野指针”)
6)是否将函数内部的局部变量(分配在栈上)作为返回值?
桌面检查是一种比较古老的人工检查方法,就是简单的由一个人阅读程序,对照错误列表检查程序。当然基于前面提到的软件测试原则,最好还是由非本程序的人员来检查比较好。
同行评审是一种依据程序整体质量、可维护性、可扩展性、易用性和清晰性对匿名程序进行评价的技术。其目的是为程序员提供评价的手段。
首先,“完全的测试是不可能的”,意思是我们不可能设计出全部的测试用例来对软件进行测试。正确的方法是,在所有可能的测试用例中,找出有可能发现最多错误的那个用例子集。
这就需要用的一定的测试策略,包括黑盒测试和白盒测试两大类。对于白盒测试,主要就是从覆盖程序的逻辑结构出发设计测试用例。而黑盒测试包括等价类划分、边界值分析、因果图分析、错误猜测几类。
如果规格说明中包含输入条件的组合情况,应首先使用因果图分析方法。
在任何情况下都使用边界值分析方法。
注意同时考虑有效等价类和无效等价类。
用错误猜测技术增加更多的测试用例。
使用白盒测试的覆盖分析方法针对上述测试用例集的覆盖情况进行检查。
可靠性由高到低:多重条件覆盖准则>判定/条件覆盖准则>分支覆盖>判定覆盖>语句覆盖
白盒测试的逻辑覆盖的几个层次:
语句覆盖
判定覆盖:要求每个判断都必须有“是”和“否”的结果,而且每个入口点都必须至少被调用一次。
条件覆盖:确保将一个判断中的每个条件的所有可能的结果至少执行一次。
判定/条件覆盖:设计出充足的测试用例。将一个判断中的每个条件的所有可能的结果至少执行一次;将每个判断的每个条件的所有可能的结果至少执行一次;将每个判断的所有可能的结果至少执行一次;将每个入口点都至少调用一次。
缺点:看上去所有条件的所有结果似乎都执行到了,但由于有些特定的条件会屏蔽其他条件,所以不能全部执行到。
多重条件覆盖:要求编写足够多的测试用例,将每个判定中的所有可能的条件结果的组合,以及所有的入口点都至少执行一次。
最后的多重条件覆盖是覆盖情况最好的,对于前面几个的覆盖情况也是包含的关系。其用例设计方法为:
将每个判断的所有结果都至少执行一次。
将每个判断的所有可能的条件结果的组合都至少执行一次。
将所有的程序入口都至少调用一次。
等价类:如果等价类的某个测试用例发现了某个错误,该等价类的其他测试用例也应该能发现这个错误。相反,如果该测试用例没能发现错误,那么其他测试用例也不能发现错误。当然了,这是一个理想状态下的划分。
有效等价类与无效等价类:有效等价类代表对程序的有效输入,而无效等价类代表的是其他任何可能的输入条件。
根据给定的输入规则和外部条件确定等价类:
然后就可以根据确定好等价类进行用例设计了。原则是:
所谓边界条件,是指输入和输出的可能情况中那些恰好处于边界、超过边界、在边界以下的情况。这与等价类是有点相似,不同点在于:
等价类没那么关注刚好处于边界值的情况。
等价类没那么关注输出的边界情况。
分析指南:
如果输入条件规定了一个取值范围,应当设计两个边界值、两个边界值之外取值的共 4 个用例。
如果输入条件规定了输入值的数量,应当设计一个 0 个、一个最小数量、一个最大数量、一个超出范围共 4 个用例。
对每个输出条件应用指南 1 。
对每个输出条件应用指南 2 。
如果输出或输出是一个有序序列,需要特别注意覆盖序列的第一个和最后一个元素。
前面的等价类划分和边界值分析只关注与软件的输入和输出规格,对于更多的规格说明,可以对应整理出因果图进行进一步的逻辑分析,从一个不同的视角,或者说更系统性的视角来设计测试用例。其分析设计过程如下:
错误猜测不算是什么测试用例设计的策略。其实就是设计人员的潜意识和直觉。不过也是有其特点:
分三大块介绍单元测试:
是将模块的功能与定义模块的功能规格说明或接口规格说明进行比较。这里测试的目标不是为了说明模块符合其规格说明,而是为了揭示出模块与其规格说明存在矛盾。
1)测试用例的设计
2)执行模块测试和集成的顺序
模块测试的测试用例设计如下:
使用一种或多种白盒测试方法分析模块的逻辑结构,然后使用黑盒测试方法对照模块的规格说明以补充测试用例
非增量测试:先独立地测试每个模块,然后再将这些模块组装成完整的程序。又叫“崩溃(big-bang)”测试。
增量测试:先将下一步要测试的模块组装到测试完成的模块集合中,然后再进行测试。又叫集成测试。1)自顶向下;2)自底向上
模块测试适用于规模较大的程序。
模块测试是对程序中的单个子程序、模块或过程进行测试的过程,并不是一上来就对整个程序进行测试,而是先把注意力集中在构成程序的小模块的测试上面。
模块测试中的测试用例设计设计过程:使用一种或多种白盒测试方法分析模块的逻辑结构,然后使用黑盒测试方法对照模块的规格说明书以补充测试用例。
1. 增量测试的总的工作量要少一些。因为非增量测试中的每一个模块的测试,都需要写对应的驱动模块和桩模块以辅助测试。
2. 增量测试可以尽早发现模块之间的不匹配的接口与假设。
3. 增量测试会将测试进行得更彻底。因为不断集成,覆盖了更多的情况。
增量测试的缺点(非增量测试的优点):
注意认识误区:系统测试并非是测试整个系统或程序功能的过程,而是要跳出来,将系统或程序与其初始目标进行比较。
能力测试:确保程序的目标功能实现
容量测试:发现处理大容量数据时的程序异常
强度测试:发现在大规模负载、高强度不间断持续的数据处理中的异常
可用性测试:评估最终用户在使用软件并与软件交互时存在的可用性问题
可用性测试主要是关注“人的因素”。而这其中应当检查的项包括:
安全性测试:试图攻破程序的安全防线
性能测试:评估程序的的响应时间和吞吐率
存储测试:确保程序可以正确处理其对存储的需求
配置测试:检查程序是否能在推荐配置上流程运行
兼容性/转换测试:评估新版本是否能兼容老的版本
安装测试:确保能够在所有支持的平台上安装软件
可靠性测试:评估程序是否能达到规格说明中的运行时常和平均故障间隔时间要求
可恢复性测试:测试系统恢复相关的功能是否按设计要求实现
服务/可维护性测试:评估系统是否拥有良好的数据处理和日志机制,以备技术支持和调试之需
文档测试:校验所有用户文档是否准确
过程测试:对软件操作系统或维护所需涉及的流程进行评估和确定
验收测试是将程序与其最初的需求及最终用户当前的需要进行比较的过程。该测试通常是有程序的客户或最终用户来进行。
Alpha测试是由用户在开发环境下进行的测试,也可以是开发机构内部的用户在模拟实际操作环境下进行的测试。开发者坐在用户旁边,这是在开发者受控的环境下进行的测试。由开发者随时记录下错误情况和使用中的问题。
Beta测试是由软件的多个用户在一个或多个用户的实际使用环境下进行的测试。开发者通常不在测试现场,这是在开发者无法控制的环境下进行的测试。由用户记录下遇到的所有问题,定期向开发者报告。beta测试是一模拟真实的使用环境从而发现缺陷的一种测试
安装测试:1)用户必须选择大量的选项。2)必须分配并加载文件和库。3)必须进行有效的硬件配置。4)软件可能要求网络联通,以便与其他软件连接
测试计划应当考虑的方面:
目标,每个阶段都需要清晰地目标
结束准则,制定标准以判断每个阶段做到何种程度可以结束
速度,也就是各个阶段的执行时间表
责任
测试用例库及标准
工具
计算机时间
硬件配置
集成
跟踪步骤
调试步骤
回归测试
准则规定发现了某个既定数量的缺陷后,可以结束测试。这依赖于提前对软件开发的各个阶段的各种类别的缺陷总数量有较为准确的预估。
预估方法有:
详细记录测试过程的缺陷发现数据,绘制曲线图,查看变化趋势,可以在缺陷发现数量已从最高峰下降到较低水平时结束测试。
调试是一个包含两个步骤的过程,从执行了一个成功的测试用例、发现了一个问题之后开始。
第一步,确定程序中可疑错误的准确性质和位置;
第二步,修正错误。
利用内存信息输出来调试。
根据一般的“在程序中插入打印语句”建议来调试。
使用自动化的调试工具进行调试。
都忽略了思考的过程
确定相关数据。
组织数据。
作出假设。
证明假设。
解决问题。
列举出所有可能的原因或假设。
利用数据排除可能的原因。
提炼剩下的假设。
证明剩下的假设。
修复问题。
根据实际代码流程进行分析。
如果说归纳法是数据分析,演绎法是逻辑分析,回溯法就是代码分析。
编写专用的测试用例进行辅助调试。
存在一个缺陷的地方,很有可能还存在其他缺陷。
应纠正错误本身,而不仅是其症状。
正确纠正错误的可能性并非 100% 。
随着程序规模的增加,正确修改错误的可能性反而降低。
改正错误有引入新错误的可能性。
修改错误的过程也是临时回到设计阶段的过程。
应修改源代码,而不是目标代码。
程序员可以通过详细分析出现的错误,从而提高自己的水平。分析的思路有:
本质上,敏捷测试是协同测试的一种形式,它要求每一个人都参与到测试计划的设计、实现以及执行中去。他们的任务是通过持续的测试反馈推动项目进行,帮助开发者修复缺陷。
XP 更倾向于适合中小规模的软件开发,这些软件的规格说明变更非常频繁,而且它们还可以进行接近实时的沟通。
单元测试是极限测试中采用的主要测试方法,它具有两条简单规则:所有代码模块在编码开始之前必须设计好单元测试用例,在产品发布之前必须通过单元测试。
消费者无需为访问的网站付费,因此一旦面对的是一般化的网站设计或性能,人们可能会很快离开该网站而去选择竞争对手的网站。
参考:
软件测试的艺术—Glonford J.Myors
https://blog.csdn.net/u013547284/article/details/70856026
https://blog.csdn.net/engrossment/article/details/92002243