测试理论|软件测试基础___测试理论篇

前言 高手,是避免失败,而不是追求成功
目录
前言
高手,是避免失败,而不是追求成功
1.为什么要写测试理论篇
2.软件测试的目标,模型及核心
3.软件测试目标案例
4.软件测试的策略
5.软件测试的依据1
6.软件测试的依据2
7.软件测试的依据的案例总结
8.软件测试的不可穷尽性1
9.软件测试的不可穷尽性2
11.Bug的汇报和处理流程
12.Bug的汇报的原则与案例
13.错误的思想实现 和 [目标-差异]思想
14.错误的设计和缺失的设计
15.测试计划和测试用例

1.为什么要写测试理论篇


当前,我们在网络上可以轻易搜到大量软件测试理论知识.然而事实上,国内当前的测试理论领域可以说是一片空白,你能搜到的理论知识有以下几个特点:
1.过时 2.绝对化 3.碎片化
1.过时
软件测试理论始于20世纪中后期,然后在后面几十年里,几乎没有更新.举个例子:软件测试用例设计方法里有一个因果图法,一个判定表法,这两个方法我接触测试行业以来从来没有用过,也没有见人用过.
可以说,根本没用.在大量资料中作者到处引用那些过时理论,给学习软件测试的人造成了巨大困扰.过去几十年里,软件项目的管理流程发生了变化.从瀑布模型到V模型,W模型,迭代模型,甚至develops模型.
不同模型下软件测试人员的工作方式方法完全不同,怎么会有防止四海皆准的测试理论呢

2.绝对化
不同的项目有不同的要求,在这个项目里可以用的方法,在那个项目里可能不行,而大量过时的测试理论资料可不管这些,上来就给你一个明确定义,即使这个定义很可能只适用于某一种类型的项目.
"看看书上是怎么写的"这种就是典型的教条主义,测试人员不应被测试理论资料所局限,即使把定义背的滚瓜烂熟也没有用,不能理解以发挥作用,没有任何现实价值.
要清楚明白对于学习过的任何理论知识,保持怀疑态度,并谨记,他们既可能随时会过时,也可能只是用于特定时期的特定项目

3.碎片化
通过网络搜索来学习,需要读者有信息筛选的能力,信息筛选需要通过实践来跟练,过于碎片化的知识影响学习效果.很可能你搜索出来一大堆资料里只有一小部分是真实有用的
这对新入行或转行过来的测试人员来说,是非常痛苦的
结语 本篇宗旨是给大家介绍从事软件测试行业所需要的理论知识
致力于解决如上三个问题,提供一套系统化的,可以根据项目灵活把握的,符合当下新时代特点的软件测试理论知识,同时也善告大家不要犯教条主义错误
结合自己遇到的项目实际情况,具体问题,具体分析.
2.软件测试的目标,模型及核心


测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

3.软件测试目标案例


在理解了软件测试的目标,模型及核心之后,我们需要知道,每个实际项目乃至于一个项目的每个时期,做软件测试的目标都会发生变化,都可能有所不同.
项目:某B2B电商平台网站改版
简介:对一个正在运营中B2B电商平台做改版,主要修改了前端页面风格,并作一些后台逻辑修改.优化了一些诸如测试流程等的用户操作流程.增加了一块让用户可以通过短视频做营销的功能
项目时间:1个月后就是领导拍板敲定的上线日期
项目人员:2开发1测试
项目特点分析:时间紧 任务重 在了解实际想要交付功能后 我就知道项目绝对做不完的,或者绝对来不及的,可以预见以下结果:
1.一开始领导不会面对现实,只会安排加班
2.然后会发现功能始终无法正常交付,即使交付也用不了
3.最终会有三种可能a)强行上线 b)砍掉一块功能 c)推迟上线

这和我们测试目标有什么关系?
1.这种项目大概率需要测试人员对项目是否被发布提供建议.我们需要提前分析每一块功能模块对项目来说重要程度,重点功能重点测,次要功能可能后期就被砍掉了.时间是被挤出来的
软件测试的核心问题就是效率.我们遇到最大问题不是不能测全测好,而是在有限时间内,难以测全,于是就要划分优先级.重要的先做,多做.如此项目,前端页面改版比做,必上线的.
值得一提的是,我们一般不提正面建议,也就是说只跟领导讲还有什么风险,即不说不能发布,也不说能发布,非要问我们,就说因为什么什么问题还没有修复好/或什么功能到现在还没开发完
,未来按时发布的风险较大. 而开发一般会把功能拖到最后一天才给测试.因此我们必须做到:每天催,每天向领导汇报进度(不是我没测完,是开发压根没开发好),防止背锅.
2.因为时间太紧,赶工肯定有很多Bug,我们不需要找到所有Bug,这是不可能的,但我们为了效率,工作必须有个重点,我们的重点是要找到所有重要的或者严重的Bug.特别核心业务模块中的
严重Bug.这是测试策略的问题.这些严重Bug通常是指用户在完成主要操作或常用操作时,会遇到的导致操作不下去的Bug,导致金钱等受损或有重大风险的Bug,其他安全方面的Bug等等.
而不是那些边边角角的细枝末节.据我所知有些测试同学因为早期从等价类,边界值等古典测试用例设计方法开始学,导致他们特别喜欢钻牛角尖.一个待测功能的主要用户操作流程没测过.
先去测各种边界值.然后很高兴地向开发提一堆"当某个文本框输入65536个字符时,系统不能给出有意义的错误信息"之类的边边角角Bug,且不说这种情况下出问题算不算Bug,请想一下用户
遇得到这个Bug吗.这种Bug,只在你能明确证明他会有严重影响的时候,才算一个有意义的Bug.更多时候,他只是一个改进点.在这种时间紧任务重的项目里,就不要去找那些改进点了
有限时间多花在主要用户流程上吧.
3.砍掉一块功能或推迟上线大家见多了.再讲讲强行上线是怎么做的吧.所谓强行上线.就是非那天不可.领导又不愿意砍掉功能.比如有时候为了赶某个特殊时间节点.此时开发被迫日夜加班
.可是开发最后还是没有交给测试.测试时间可能压缩到了原计划的几分之一.这时候就只能加人了.也就是让开发一起测.还不够的话,把其他部门的人.比如产品.前台.财务.人事.客服等等
,全叫过来一起执行测试用例.要做到全体一起赶工.测试人员必须提供测试用例.所以在这种项目里,测试用例必须写,而且最好写详细点.
4.软件测试的策略


测试策略是你所做的计划,其目的是实现你的测试目标.前提条件是必须根据你的项目实际情况来采取不同的测试策略.
测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

测试理论|软件测试基础___测试理论篇
文章图片

5.软件测试的依据1


当我们做测试时,我们需要判断软件的功能是否正确,或者说是否符合预期.但问题是,我们怎么判断一个功能是否正确呢.这就需要一个依据
软件测试的依据指我们用来判断待测软件的功能,性能等指标是否符合预期的一个标准
这个标准是且不限以下这些:

  • 一份标准的需求文档
  • 一份不标准需求文档或电子邮件等
  • 一份需求讨论会的会议纪要
  • 用户给出的反馈
  • 企业标准,行业标准,国家标准,国际标准等标准
  • 相关法律法规
  • 竞争对手的产品的类似功能
  • 常识
  • 安全
  • 性能
为什么需要依据?
软件工程是一个复杂活动.往往需要多人协作.不同人对于同一句话,同一个事物,往往有不同的理解
绝大多数项目要么没有需求文档,要么需求文档不完整或不是最新的.不建议在没确定测试依据之前就开始测试,测试一句不明确时做测试会导致测试人员背锅
到最后项目组成员会质疑测试人员"为什么没测出来""测试做的不够"当然,项目组成员不会取质疑基层管理人员"为什么没有明确流程""为什么没有安排需求讨论""为什么没有安排设计评审和测试用例评审",也不会之一开发人员
"为什么代码没考虑这种情况""为什么想当然实现了没讨论过的功能""为什么改了代码不跑单元测试"
客观上讲,测试人员因为软件项目工程化的历史原因,长久以来都处于高危背锅侠的位置上.如果测试自己失误漏测了,测试背锅,开发失误.改代码引入新Bug结果没发现,测试背锅,产品设计人员需求设计错了结果大家都没发现,测试背锅.
所以测试人员必须把自己摘出去.要把自己从背锅侠列表里摘出来,就需要做到凡事都要有依据.不做任何超出权限的决定,而改为相对应角色管理者请示(比如决定项目是否能发布,这是项目管理人员的职责范围)另外,测试不是神仙
开发会出Bug,测试也会出Bug,开发的Bug是代码,测试的Bug可能是代码也可能是文档,可能是动作或过程.
只有改进流程,才能提高项目的生产率,而不是期望测试本身不出错
6.软件测试的依据2


怎么确定一个项目测试依据
1.有没有标准的需求文档,该文档完整不完整,不完整能否补充完整,找谁来补充完整,无法补充完整该怎么办,需求文档存在但是没有更新到最新版应该怎么办,比如有没有专职负责管理和维护需求的产品经理等.
2.能不能开会讨论需求,文档不齐或不新,在会议上形成会议纪要等文本形式的需求.能不能形成一个需求讨论的周例会或每日例会.
3.有没有了解需求的人,没条件开会的时候可不可以由测试人员提出问题列表,由了解需求的人回复,形成文本形式的需求,并抄送给所有相关的人,比如发给敏捷团队的PO角色,让对方从需求角度给予回答和澄清.
4.没有了解需求的人,可不可以由测试人员或其他角色人员学习需求或通过操作现成软件等方式尝试汇总需求,最后汇总成一个需求点列表,形成文本形式的需求,比如,问问项目的技术支持人员,给用户的用户手册长什么样.
从用户手册里可以找到一些需求点.用户手册也天然是需求文档的补充,即使这个项目压根没有需求文档.
5.需求无法形成或不存在现成需求,能不能结合相关企业标准,行业标准,国家标准,国际标准给项目设置一个大前提需求.比如你在微软测试word软件的字体大小功能.不同字体大小比如五号字,究竟在显示器上应该多大,
都有相关的行业标准可查
6.需求没有标准可参照是否可以参考同类软件,比如竞争对手的软件的类似功能,比如你测爱奇艺VIP功能,参考一下腾讯视频同样功能,看能不能做的比竞争对手好
7.有没有真实用户反馈,有没有可能组织用户接受性测试,或阿尔法测试,贝塔测试等,从真实用户的反馈中,可以看到很多真实的或没有那么真实的用户需求,对具体的用户反馈,还得具体情况具体分析,看其中是否反映了真实用户需求.
8.有没有违背常识的功能,比如注册流程越简单越好,需求文档却给了一个十分复杂的流程.一般项目中需求对不对测试人员也要管
9.有没有犯法的功能,分析一下是否会被牵连
10.有没有影响用户数据安全,服务器安全等安全相关的问题,看似正常的功能,实际上会有极大安全风险,幸好安全方面的问题的背锅侠一般另有其人.
11.有没有影响性能的问题,比如一个功能虽然没啥问题,但是很慢,这也很严重,即使需求文档压根没有提一个页面打开应该小于几秒钟
12.有没有影响用户体验的问题

当你新加入一个项目组,不知道测试依据是什么,务必多提问,可以问开发,问组长,问其他同事,可以以问题列表形式发给他们,而不要自己想当然盲目测,出现误差会有损职业形象
7.软件测试的依据的案例总结


测试依据是你用来辨别一个问题是不是Bug的方法.
测试是一种认知活动,而非一种机械活动,也就是说必须确定了测试的依据,才能进行测试
我们做出判断的依据是用户对这个软件的期望
8.软件测试的不可穷尽性1


穷尽的测试,真正意思是,在测试完毕之后,测试人员知道在系统里没有残留着任何未知的Bug.如果你可以通过更多的测试来找到他们,你的测试也就还没有穷尽.
穷尽覆盖率:代码覆盖/分支覆盖/路径覆盖?
什么是覆盖率?
---对某一段代码或者代码的某一种属性做测试,其测试达到的程度被称为是覆盖率.
比如对语句的覆盖,对分支或条件的覆盖,对所有程序可能执行路径的覆盖等
--把现有的测试与可能执行的测试作比较,现有测试能够占总的可能执行的测试的多少比例作为计算覆盖率的方法
--输入待定的某个值或某组值
--在编码中遗漏的代码
--中断,以及其他并行操作的情况
代码的遗漏,这种问题通过覆盖率根本无法发现.
例如管理者一昧要求测试必须实现多少覆盖率,反而会产生反效果,造成一大堆低效测试用例.
当测试人员或开发人员受到必须达到百分之多少的覆盖率的压力的狮虎,自然就会去选择编写那些容易提高覆盖率的测试用例,而不是实现那些更能发现Bug的测试用例.
并且你规定了百分之几,几乎没有人愿意在达到标准后去做更多测试

同时也要考虑 输入值本身是无穷无尽的,对同一程序,从黑盒测试到白盒测试的角度划分的等价类也是不同的.在等价类划分好了之后,仍然可以出现等价类没覆盖到的某个特定值会使软件报错
平台也是无穷无尽的,比如windows 10的xxx版,redhat的linux xxx版.以及在mac上运行,也包括不同软硬件组合的更多场景
软件在运行时,遇到的中断也是无穷无尽的,比如运行程序时,系统开始更新了,要重启了,又比如运行到一半,其他程序把内存占光了,或把cpu占光了,各种各样特殊情况都有可能影响这个软件的运行.
另外,性能测试,安全测试等,都可以设计无穷多的场景.
9.软件测试的不可穷尽性2


覆盖率所无法覆盖的Bug
为什么又提到了覆盖率,因为直至今日,仍然有很多基层干部不懂覆盖率覆盖不到什么东西,仍然有以覆盖率作为考核标准的公司或团队.让我们继续看一下覆盖率问题.覆盖率所无法覆盖的Bug除了上一篇提到的这些:
---输入特定的某个值或某组值,代码路径是覆盖了,但很遗憾无法覆盖所有输入值,等价类也不一定靠谱
--在编码中遗漏的代码,虽然你覆盖率百分之一百了,但是开发漏掉的代码总覆盖不到了把.
--中断,以及其他并行操作的情况,代码可以覆盖,运行环境上的系统中断却无法覆盖
--需求中所包含的错误,从一开始就错了,测试覆盖再多错误的逻辑又有什么用
--兼容性方面的错误,比如让APP运行在不同平台或在不同浏览器上打开网页
--配置错误,不是代码的错误,代码覆盖率百分百也测不到
--性能问题,又是一种覆盖率无法覆盖的问题
这些问题有一个共同点就是,即使你代码覆盖率硬生生堆到百分百了,仍然的对这些问题无能为力或者说对减少与发现这些问题毫无帮助.希望下次有人提议用覆盖率作为绩效考核指标的时候,你可以把这7种无法覆盖的问题
给他看看.
测试人员不再发现新Bug了?
这里可以套用Wellbull模型,把这个理论应用在软件测试上会发生两种情况:
1.单位时间内发现的Bug数量逐渐减少
2.当发现Bug所花的时间间隔逐步上升.
是不是说测试人员发现Bug数量逐渐减少或者不再发现新Bug就可以认定版本稳定了.
这种逻辑本质上是站不住脚的.心理因素驱使着测试人员后几周不如前期那么"用力"去找Bug.
需要注意,当测试设计是错的时候,测再多也是测错的.
系统是不会自然而然稳定的,能不能稳定取决于设计和探索性测试到底做的好不好,以及取决于新代码是否减少了
在传统瀑布模型,我们往往强调测试计划,在现代的迭代测试模型下,测试计划的角色已经淡化了,
但我们在项目有限的时间内,是可以通过制定计划,然后让团队评审这个计划,来限定我们的测试范围的,这样可以有效缩减测试范围,化无穷为有限
11.Bug的汇报和处理流程


这里关于Bug的知识收录在笔者关于Bug知多少(注意这是个链接) 的文章中,在这里就不多赘述了
12.Bug的汇报的原则与案例


Bug的汇报原则
当测试人员需要填报一个Bug时,我们称之为"提Bug"或"提问题单"
我们需要遵循一些原则:
1.Bug的描述要尽量精确.
2.Bug的描述要尽量完整.提供足够信息,不要让其他人猜你是什么意思.包括附带各种相关日志,环境信息.发现问题后的原因初步分析,可能产生的风险等.不可随意提交一张截图当作Bug描述
当时看似没问题,但会导致以后这个Bug单的意义被遗忘.
3.Bug的整个生命周期都需要测试人员进行跟踪,关注及推动对Bug的处理,测试人员还需要对不合理的处理方案提出异议,而非提上去就完事了.
4.Bug的描述中尽量避免对Bug的修复方案提出意见,除非这些意见经过团队讨论或已经得到相关技术专家认可,我们提出问题,但不直接解决问题,问题的解决是需要多方面考量的,应当交给团队或技术专家负责
5.Bug的提交一般提交在Bug管理系统中,而不应该使用邮件,文档等易被忽略,易丢失的载体来提交Bug,但对于与Bug相关的技术讨论可以通过邮件等形式,只不过最后这些讨论需要附加到Bug管理系统中去存档
6.当Bug被提交后,测试人员应当判断是否需要针对这个Bug新增测试用例,用于回归测试,避免同样的问题再次出现.
7.当Bug被提交后,测试人员应当与开发人员等相关角色共同分析这个Bug产生的根本原因,比如是需求缺陷,设计缺陷,编码缺陷,还是环境问题,脚本问题,亦或不明原因.根据不同的根本原因,可能以后可以采取不同的
预防措施.减少同类问题的出现,特别的,对生产环境上被用户发现的严重Bug,整个开发团队应该共同做这个分析,而不是把锅扣在谁的头上就完事了.扣锅是"懒政",问题没得到解决,下次还会发现一样的问题.在软件项目
过程中,任何角色都有可能犯错,并不会因为"测试","开发","经理"这样的头衔差异而使得"某人不应该犯一丁点错误","某人犯错误可以原谅""某人犯了错误也是下属的锅"这样的不合理判断成立
8.当某个Bug是偶现的,开发无法复现时,这个Bug可以被推迟或暂时关闭,往往很多偶先的Bug都是有背后原因的,测试人员应当汇报偶现的Bug,而不是因为这个问题出现几率低,就不报了,开发人员应当尝试收集相关日志,
判断问题出现的点,而不是因为这个问题出现几率低,就不修了.

Bug的汇报格式
标题:xxxxx(简略概述)
详细描述:xxxx(较为详细的概述)
严重程度:高,中,低(不严重也可能先被修,比如把公司logo拼错)
分配人:某开发或某经理(把Bug提交给谁,至关重要)
步骤:(问题重现步骤或发现的步骤)
1.xxxxx
2.xxxxx
3.xxxxx
预期结果:(假如系统没Bug,此时应当看到什么样的结果)
xxxx
实际结果:(现在实际看到了什么样的结果)
xxxxx

根据具体项目不同也可以再此格式上做增减:
环境:发现问题的环境是那一套
标签:用于把问题归类,比如release_20200101发现的Bug
发现版本:发现问题的版本
修复版本:修复问题的版本(关Bug的时候填)
模块:问题属于哪个模块
重现频率:问题复现的频率,可填"高"中"低"只发现一次"也可填"平均五次里出现两次"这样的描述.

Bug汇报案例
案例1:
标题:用户注册时填写错误的邮箱地址格式时,应该在填写时直接俄出现错误提示.
详细描述:当新用户进入用户注册页面后,在填写邮箱地址时,如果填写了错误的邮箱地址格式,应该在填写是直接在也没面上出现红色提示,但现在没有任何提示
,而是在用户点了注册按钮后,出现UnknowError的错误信息.
严重程度:高
优先程度:高
分配人:某开发
步骤:
1.打开网站首页 https://xxx.xxx.xxx.xx
2.点击右上角"注册"进入用户注册页面
3.填写以下信息:
用户名:张三
密码:666666
邮箱地址:123456789@gmail.com
4.点击注册按钮
预期结果:
步骤3中用户填写邮箱地址后看见红色提示,请输入正确的电子邮箱地址
实际结果:
步骤3时没有任何错误提示,步骤4提交表单之后出现了Unknow Error
环境:测试环境1
截图:(图1 圈出应该有错误提示的地方 图2直接显示Unknow Error)

案例2:
标题:[偶现]当以登录用户反复刷新购物车详情页面,有时会导致购物车内容无法显示.
详细描述:当用户进入购物车详情页面并反复进行刷新,有时会导致购物车内容无法显示.重修按频率大约刷新十次会有一次.页面直接卡住,
出现错误信息:Whitelabel Error Page.
严重程度:高
优先程度:中
分配人:某开发
步骤:
1.使用用户"张三"打开网站首页https://xxx.xxx.xxx.xx
2.从上方导航进入购物车页面
3.反复刷新页面
预期结果:
页面被正常刷新
实际结果:
当刷新次数较多时,会出现如下截图所示错误:
(有张图 Error Page 图不贴了)
环境:测试环境2
重现频率:平均十次刷新出一次.
最后强调:
在提问时,也请遵循提Bug的原则和格式,不要让人家猜你遇到的任何问题.

13.错误的思想实现 和 [目标-差异]思想


软件Bug的三个层次
缺失的设计
错误的设计
错误的实现
意识到这三个层次存在才能理解他们,从而对软件测试理解远远超过及他人,本节也是测试理论篇的精髓之一,建议深入理解.
第一层:错误的实现 我们目前在绝大多数现存软件测试理论资料上能看到的绝大多数软件测试方法,可以说都是针对这个层次的问题而被发明出来的.等价类,边界值,因果图,判定表,这四大古典测试用例设计方法(也称古典方法)全都是针对"实现的错误"这个层次的Bug产生的设计思想,因为古典方法诞生于上个世纪,他们顶多只能对瀑布模型下开发的代码管用.
让我们一起通过思维实验的方式看一下古典方法问题出在哪:
假设我们设计一个程序,这个程序没有任何输入值,就固定输入"hello world"这样一个字符串,然后忽略一切软件硬件环境等外部物理因素,我们怎么测这个程序?
例1:古典方法没法测的例子
print("hello world")
就这样一个例子,是没有办法划分等价类的,也不存在边界值,照着他画出来的因果图和判定表更是毫无意义.

为什么没法测?
因为古典方法只能测出实现层面的错误.

如果一定要测,测试用例或许可以这样写:
步骤:
1.运行待测程序
预期结果:
屏幕输出("hello world)
这里用到测试设计思想是什么?
是比四大古典测试用例设计方法更朴素的思想:[目标-差异]思想.
目标,就是我们期望程序怎样运行,是预期结果.
差异,就是我们实现运行它之后,它会得到怎样的结果,特别要注意,与目标有没有差异,没有差异,就执行通过了,pass.有差异就失败了,fail.
[目标-差异]思想是软件测试最核心的思想.我们不论做什么测试都是确认目标,然后确认差异.古典方法有一个前提假设,就是目标已经明确,且目标是正确的.然后古典方法做的
就是用不同方法去确认现实与目标的差异.

第一个层次的Bug,错误的实现,意思就是说,目标已经正确明了,但实现时会出错,比如测试1我们拼错了一个单词.

例2:错误的实现
print("hell world")
屏幕输出出错,于是产生第一层次的Bug,错误的实现.
假如这个例子,不仅仅向屏幕上打字,而有丰富输入输出内容,有复杂的内部逻辑路径,而且你对程序的目标清晰的目标,那么,此时才是古典方法的用武之地,当然很遗憾,现实世界的程序过于复杂,并没有清晰明了的目标.即使有,测试人员也难以了解这个目标.我们看一下例子,有一个方法叫complex-fuc,他的功能在于每个迭代里都做了修改,以下例子记录了他的若干个版本.

例3:这该死的等价类划分
#第一版
def complex_func(a,b):
return a * b
#第二版
defcomplex_func(a,b):
if a ! = 0 :
return a * b
else:
return b
#第三版要命的
def complex_func(a,b):
if a % 5 !=0 and a>0:
return a * b
elif b % 3 !=0 or b > a:
return a*a*b*3721
elif b%3 == 91 and b return (a % 5) *b
else:
return b-a

第一第二版程序,我们还可以划分等价类吧.可以写写测试用例
第三版?鬼知道写了什么.划分等价类?太难了吧
问题就在这里,且不说很多测试人员根本不知道程序内部逻辑.就是看过程序内部逻辑的人,你真的搞得清楚这个内部逻辑是怎么回事吗,
那怎么划分等价类?按照这个第三版功能,这个等价类非划的头痛不可.现实工作中,我们通过迭代不断更改软件功能,一个原本如第一版第二版例3一样清晰
的功能,可能一夜之间就改成了第三版这样复杂且理不清的功能.

所以,就像之前说的,使用古典方法的前提是:
你对该程序的目标清晰明了.现实世界中,通常做不到

那么你猜现实直接中的测试人员怎么测例3这样被改来改去,最后谁也不知道具体需求的功能?
凭自己猜想捏造一些等价类来测.黑盒测试人员,往往连代码都没看过,他们怎么知道哪些输入时等价的?不,他们不知道,他们只测"我觉得是等价的等价类".
至于程序内部是不是这样的,那就不知道了.

等一下,那么可不可以按照需求来划分等价类呢?就像黑盒测试人员常说的,我们按照需求来.
当然可以,可以划出自己心安,但实际并没有卵用的等价类来.
比如下面这个例子.

例4:心安理得的等价类.
需求:计算两个数相除的结果,输入被除数a,除数b,返回商c.
计算公式c=a/b
def divide(a,b):
c=a/b
return c
对于例4,需求和公式都很明确,那么这个程序有Bug吗,黑盒测试人员怎么测.

不管黑盒测试人员怎么测,以下一个调用就出Bug了:
print(divide(5,0))
出错信息是:ZeroDivisionError:division by zero
为什么呢,因为除数不能为0,这是数学法则规定的.python解释器也逃脱不了数学法则的掌控.所以当我们把b传参为0的时候,该程序就出错了.所以说,黑盒测试人员按照需求划分等价类,测了半天,才发现,需求里根本没有提到b为0的情况.那么以需求文档作为划分等价类的依据,又怎么可能保证真的把每个等价类都测到了呢?这里最少要测b为0的情况和b不为0的情况,这样两个等价类吧.

那还有Bug吗?假如我们意识到了数学法则的存在,测了b为0和b不为0,是不是就可以了.
并不,数学法则之后,我们还有"python解释器的实现"要考虑.
总之,四大方法的任何一个,都发现不了这两个确实存在的Bug.这是因为,这两个Bug不是这个层次的方法能发现的Bug.他们处于更高的维度.它们是由错误的设计
或者缺失的设计导致的Bug.使用针对错误的实现的测试方法又怎能发现他们呢,就像二维空间无法测三维空间的立体实物一样.
14.错误的设计和缺失的设计


第二层:错误的设计
什么叫错误的设计呢?
这个功能应该是这样,但我开发的时候设计成了那样,结果导致南辕北辙.要发现错误的设计,就要自己能想出来现有的设计错误在哪里,正确的设计是什么样.这是任何谷底啊方法都做不到的,古典方法根本没有要求测试人员有任何的软件设计能力,架构能力.
设计就错了,照着错误的设计做出阿里的实现是不是一定错误呢?
你可能碰巧错误的设计下再做错误的实现.结果误打误撞产生了正确的代码.但这个概率太小了.
(有时候代码写错又跑错了环境就可能导致负负得正,程序执行竟然没有问题)
我们可以认为,错误的设计一定会导致错误的实现.

很多错误的设计是由于在设计阶段,开发者想当然,不做详尽的调查与验证.有很多错误的设计会在开发代码的实现阶段被发现,但是少量遗留下来的一般都是很麻烦的问题.
比如,有两个模块A和B,用来根据用户的输入在数据库里建表.
用户输入数据-->模块A-->模块B-->数据库
模块A负责校验用户输入数据的正确性,包括命名规范和长度,模块B负责创建资源.
场景1,用户再输入数据里输入一些表名,模块A检验表名是否符合命名,规范,模块B在数据库里建表.

然后这个场景1里设计错误了,命名规范校验时允许表明里出现任意的大小写字母.
但是这个项目里的数据库在以前迭代里设置成了"大小写不敏感",实际上我们后来发现,这个设置的意思是数据库自动把所有的表名和字段名都改成小写了.不管你建表的sql
里表名写的是大写还是小写,创建出来的表实际表名它就是小写的.
这样我们测试模块A的时候,因为涉及要大小写字母都可以出现在表名里,所以测试自然会通过,也符合需求.因为需求只是说要它能把数据存进数据库里去.但是,却出现了Bug,
因为存进去的数据的大小写和用户输入的不一样了.用户明明输入的大写表名,最后测出来发现自动变成小写表名了.这样,查这个问题查了半天才发现,是因为数据库设置导致大写均被转化成了小写.
这就是由于开发没有考虑以前做过的功能,孤立的进行设计,而导致了错误的设计.最后导致改这个Bug,不仅要改模块A,修改校验逻辑,还要更改其他更多被牵连的Bug.

这里,单元测试发现不了这个问题,只有集成测试才能发现,因此我们需要现代的设计方法,能针对错误的设计和缺失的设计来做测试的新方法.

第三层 缺失的设计
什么叫缺失的设计呢?
就是完成某项功能,压根没意识到需求设计的点,导致的部分缺失.要发现缺失的设计,就是要发现被遗漏的代码.这是任何古典方法都做不到的.
(很多基层管理人员推崇的代码扫描也扫描不到这本应该存在却实际不存在的代码.所以即使代码测试覆盖率百分之一百了,有意义吗?)

古典测试设计方法的局限性
古典测试方法给我们一种错觉:
例如测试人员前期做了足够多的测试用例设计,后期就只要执行这些测试用例就能保证项目质量了.
现实无情打脸:
即使测试人员在前期做了足够多的测试用例设计,但只能发现第一层次"错误的实现"导致的Bug,无法提前预知会出现那些错误的设计和缺失的设计.实际测试人员需要根据项目实际情况,在项目的推进过程中,根据新收集到的信息,不断修改原有的测试用例设计,新增新的测试设计.而非指望在一个迭代的前期就完成测试设计,就可以高枕无忧了,这纯粹是做梦.
就像开发人员在写代码时会修正一部分之前错误的设计一样,测试的设计也存在错误的设计和缺失的设计的问题,在测试开始之后,也需要修正一部分之前错误的设计,弥补一部分缺失的设计.
软件测试是一个动态的,不断变化的过程,而不是简单且固定的.
测试人员在参加设计评审会时发现设计错误应该及时提醒开发修复Bug,切不能在开发进行编码,得到一些低效代码后才修改.
实际工作中受限于开发水平有限,又是不得不让一些差一点的设计进入编码环节,这里只说一个原则:具体问题具体分析.一定程度上烂代码可以让他上,
超过一定程度的烂,就不能让他上,具体度的把握,只能根据实际项目,实际开发水平,实际进度要求,实际项目资源综合考虑,具体情况具体分析,综合把控.

测试人员必须掌握足够的开发技术,必须参加设计评审会议.
现代的软件测试方法要求大家:
1.要具备开发的技术.否则无法理解程序的设计思路,怎么找到错误的设计和缺失的设计呢.
2.要全程参与开发,否则设计已经做完了,要开始实现了,才发现错误的设计和缺失的设计,那就迟了,来不及改了.
3.要打破对旧方法的迷信,对覆盖率的迷信,对需求文档的迷信,对开发人员的迷信等固有思维.然后发挥主观能动性,不是开发告诉你怎么测你就怎么测,而是要有独立的思考能力,从软件架构角度,软件设计角度,用户角度等多角色思考这个功能应该做成什么样.
在我们设计一个功能时,可以设计成60分,也可以设计成30分,80分,100分.测试人员在设计阶段就要给项目挑毛病了.
我来举个例子,有一个功能的需求是这样的:
定期读取数据库里的内容,生成一张简单的excel报表,告诉用户数据库里的权限相关的东西在发生了什么变化.
然后开发这样设计:
1.首先找了大概七八条sql语句,这些sql语句由数据库官方文档提供,用于查出数据库里权限相关的东西.
2.把这些sql语句在数据库里执行,执行结果存入excel,列名使用数据库里的字段名,数据值就使用数据库里查出来的值
3.七八条sql汇总成七八张excel表格.
开发说这么测:你sql运行一下看看是不是跟生成的报表里的数据一样.
实际上我怎么测:我测什么呀,我看一眼这个生成出来的excel,就可以报bug了,实际上我都不需要测,我就可以质疑他这个功能根本就是错的.
这是一个设计阶段的问题:用户想看的到底是原始数据,还是程序里计算整理过清晰展示的权限变化图标?
你把原始数据提供给用户看是什么意思呢?数据列名这么抽象,这些列是什么意思都很难区分.还有这么多原始数据,有些表里用true/false表示有没有这个权限,
有些表里用yes/no来表示有没有这个权限,为什么不能统一展现形式?这些压根没设计过,需求提出者只提了有这些东西,开发的设计只是直接把原始数据拿出来就有了这些东西了,但测试人员想到的应该是:用户根本看不懂吧,这样的设计根本不合理吧,注意,这里我既没有划等价类,也没有测边界值.既没有因果图,也没有判定表.根本不需要,这些古典方法就使用了也发现不了设计层面的Bug,因为开发实现没有错误.没有实现层面上的Bug存在,他确实是从数据库里查出来的数据,确实放进了excel报表里,我能想到这里的问题是因为:我以前了解过数据分析,数据分析的基本,不就是把原始数据做计算整理,展现成清晰的图表吗,谁见过数据分析里把原始数据直接丢给用户的?所以他这个设计顶多50分,不及格的设计,糊弄糊弄人还行,真要用还不够体面.
15.测试计划和测试用例


测试计划就是针对测试的目标来编写的.
测试计划描述我们怎样实现测试的目标.

瀑布模型时代流传至今的测试计划 早在瀑布模型还有人用的年代,测试计划已经作为项目计划的一部分,成为了一种很常见的软件测试文档,活跃于各种项目组中,至今,迭代模型时代,仍然有很多项目组沿用以前测试计划文档.
当然,不论是现在还是以前,也都有很多项目组是把测试计划作为项目计划的一部分来编写的,也就是说,测试计划文档可能有,但不一定是一个独立文档.
同时,迭代模型的流行,导致一部分项目组选择不在制定测试计划.取而代之,用敏捷流程里的feature/item来管理这些计划.
测试计划的重要性正在逐步被淡化,但是在性能测试等特殊范围内测试计划还是挺重要的.
这里我们要讨论的是普通测试计划,通常要包括一些元素:
  • 测试目标
  • 测试范围.哪些要测,哪些不测
  • 测试策略,用什么技术手段怎么测,做哪些类型的测试,分别怎么测
  • 测试通过条件或结束条件,怎样算测通了,怎样算测完了
  • 测试的进度安排
  • 测试的人员安排
  • 项目风险
  • 测试环境
  • 测试数据
  • 测试工具
  • 其他任何与达成测试目标有关的内容
通常我们是不写测试计划的,这个文档主要还是应用于瀑布模型时代,因为那个时代,有足够的时间来编写和修改计划,而现在,不断迭代,哪有什么时间做这种文档呢.
如果有需要,可以参考软件测试流程编辑测试计划

测试用例的格式 测试用例是记录测试相关要点的文档,用来让其他不太了解这块需求的人可以照着这个文档做测试

说到测试用例的编写,我们要考虑的两点:
1.格式
2.测试设计方法
测试用例格式不是一成不变的,而是根据实际情况来决定的.
Checklist检查点列表
1.检查用户可以用正确的用户名密码登录
2.检查用户如果用错误的用户名密码登录时会提示"密码错误"
3.检查用户可以正确登出.
这样的写法不太详细,其描述也有一定模糊性,什么叫正确登出?
这种Check list适合自己用,或者再没有人怼的情况下用,如果有人要针对你,质疑你的测试范围,那你就没办法了.只有写完整的测试用例.
TestCase完整的测试用例
1.在excel中管理测试用例(心中有线,自然有线)
编号操作步骤预期结果实际结果测试执行人
11.使用用户aaa,密码bbb,登陆网站登陆成功
这样就是一种测试用例的写法,其中实际结果和执行人栏位留到运行时候填写.
也可以这样,这种就加入了测试数据,也可以把预期结果和实际结果针对每个步骤来写:
编号步骤预期结果测试数据实际结果测试执行人
11.使用正确的密码,登陆网站1.登陆成功aaa/bbb
2.登出2.登出成功-
3.再次登入3.再次登入ccc/bbb
其他字段想加还可以继续加.
2.在jira等类似的系统里写测试用例.
除了上面这些字段外,还可以增加一些比如模块之类的.因为在系统里填,所以通常都不需要自己设计格式了,就按系统的要求填.
3.有时给测试用例分类或分组,那么还要加上标签或模块等代表分类或分组的字段.

TestScript测试脚本
直接写测试脚本取代测试用例,也是一种可行的做法.前提是你们项目组里没有人针对你,如果有人针对你,你可以考虑从测试脚本生成测试用例文本,或者编写完整测试用例.
小结
总而言之,写测试用例最关键是搞清楚为什么写
  • 为了过审而写
  • 为了让别人替带你做回归测试而写
  • 为了理清测试点覆盖率
  • 为了跟踪测试进度
为了评审而写的就进了详细,为了让别人照着做测试而写就要分确定的人和不确定的人,确定的人就要提前跟他沟通,不确定的人就要把测试用例写详细点,为了理清测试点覆盖率,
那就写个chek list就好了,为了跟踪测试进度,那就要多加一列需求编号,把测试用例和需求点联起来.

【测试理论|软件测试基础___测试理论篇】

    推荐阅读