第2章 软件测试分析与设计
现在软件测试界对软件自动化测试非常重视,每年有各种各样的软件测试大会,而这些大会的关注点都集中在软件自动化测试,对软件测试自动化开始重视了,这是一件好事情,本书下篇也都是介绍软件测试自动化的。但是另一方面,据权威报告,2019年在中国仅有5%的软件公司做到了完全意义上的软件自动化测试,这说明了什么?请读者自己思考一下。读者都知道软件开发,不管采取什么样的开发模型,都离不开分析、设计、编码、测试和部署5个环节,而软件测试也可以分为测试分析、测试设计、测试准备(包括测试数据的准备、测试代码的开发、测试环境的搭建等几个方面)、测试执行和测试总结。而现在AI技术刚刚起步,虽然一些大厂开始尝试用AI技术来进行软件测试分析、设计与执行,但是效果并不理想,MBT(Model Base Test:基于模型的软件测试)落地也非常困难,自动化软件测试也仅仅在软件测试执行方面起到了非常重要的作用,虽然随着DevOps概念的提出,软件测试的左移和右移也被提出,但是发现缺陷仍旧是软件测试的关键目标,而大部分缺陷还是需要靠人工测试来完成,软件自动化测试主要作用也仅仅在回归测试起到关键的作用。一方面在开发自动化软件测试代码之前,肯定也进行手工测试,否则自动化测试中的断言是无法获知的;另一方面自动化软件测试对被测程序也要进行分析和设计,所以软件测试分析与设计是软件测试的灵魂,是一个不可被忽略的要素。
正如第一章所述,软件分析有6W2H法则、CPIE模型、KART模型、SBTM模型、HTSM模型、ACC模型、MFQ模型和PPDCS模型。软件设计包括传统的软件测试和基于质量的软件测试方法。这些测试分析和设计技术是非常重要的,但是仅仅通过这些法则、模型、技巧就够了吗?就能够做好软件测试分析与设计工作吗,答案是否定的。比如下面这种情形大家可能都遇到过,产品做得很好,但是《产品安装手册》写得非常粗糙,团队虽然知道DevOps提倡自动化发布产品,但是由于各种因素限制,本企业没有实现,产品上线仍旧需要运维工程师通过研发人员书写的《产品安装手册》进行产品安装和升级工作。然而低质量的《产品安装手册》严重阻碍了运维工程师的工作,,早就提交的产品,客户在一段时间内没有得到使用。这种情形下问题出在哪了呢?也许产品的自身质量非常的好。这就是研发人员没有把运维工程师也作为客户,仅仅把最终的产品使用者才作为客户,从而没有对《产品安装手册》认真测试过。本章专门对软件测试分析与设计进行思考,使其可以真正落地运作。
现在讨论一下做好软件测试分析与设计工作所需要的能力。这些能力包括思维能力、学习能力和其他能力。
思维能力包括逻辑思维、逆向思维、发散思维、整体思维、简单思维和极端思维能力。
逻辑思维是一种建立在数学基础上的思维方式,是一种科学的思维方式。逻辑思维是基于大家都共识的公理基础上,通过逻辑推演的方式来思考问题的思维方法。比如有一个问题:地球之外如果有智慧生物,可否与地球人进行交流的?有一种回答:地外智慧生物与地球人就如同地球人与地球上的蚂蚁一样是不可以进行交流的。这种方式属于典型的类比式思维,是一种不严谨的思维方式,这里的致命点在于为什么能把地外智慧生物、地球人与蚂蚁在一起进行讨论,三者其实是风马牛不相及的东西。而逻辑思维方式是先建立两个公理:1)数学是智慧生命共有的语言,2)如果地外智慧生物向地球人发射数学信息,那么地外智慧生物与地球人就可以沟通了。基于这两点共识基础上,如果地球人收到了2、3、5、7、11… 质数序列,或者3.1415926…,就说明地外智慧生物与地球人开始沟通了。
通过逻辑思维方式对于学习业务知识是非常有用的,笔者以前测试过会计软件,在会计业务中收入与花费一定要保持平衡是一个基本规律,基于这个规律就可以推出各种业务知识了。
逆向思维也是作为测试分析与设计的时候需要掌握的技能,最经典的逆向思维故事就是司马光砸缸。一个小朋友不小心掉入了水缸,按照通常思路肯定是想办法把缸里的小朋友救出来,但是聪明的小司马光砸缸急中生智,想出把缸砸破,让水流出来,这样落缸的小朋友起码可以先不被淹死,然后把缸砸得更破,从而救出那个小朋友。
在电子商务系统中先选择商品,然后下单,最后支付。在测试这个场景的时候,可以考虑以下几种情形,系统会如何应答。
•A用户下单后没有支付。
•B用户没有选择商品,就进入下单的界面(通过拷贝粘贴URL)。
•C用户下单,支付过程中发现没有绑定任何银行卡并且支付宝、微信钱包也都没有钱。
•…
发散性思维其实也是逆向思维的一个扩展,如图2-1所示,是对上传文件功能的测试思维导图。
图2-1 测试文件上传
首先考虑正常的文件上传,然后可以从文件大小、文件格式、与文件名及目录及安全性几方面考虑。
•文件大小(比如10K-20M)。
Ø文件比规定的大小要大,考虑边界值选择上传的文件大小为20M、20.1M。
Ø文件比规定的大小要小,考虑边界值选择上传的文件大小为10K、9.9K。
•文件格式(比如JPG、GIF和PNG三种格式的图片文件)。
Ø选择上传的文件名为a.exe上传。
Ø选择上传的文件名为a.exe a.txt,打开写入“这是一个加图片文件”,然后把文件改为a.jpg后上传。
Ø选择上传的照片文件,名为pic.jpg,改名为pic.txt后上传。
•与文件名及目录。
Ø选择文件,把文件删除,点击【上传】按键。
Ø选择文件pic.jpg,把文件名改为my.jpg,点击【上传】按键。
Ø选择文件,把服务器上的文件所处的目录删除,点击【上传】按键。
•安全性。
Ø在上传过程中,把pic.jpg改为pic.txt。
Ø在上传过程中,把pic.txt改为pic.jpg。
Ø在上传过程中,把pic. jpg改为pic.exe(假设服务器为Windows Server 2019,pic.jpg是一个病毒文件)。
发散性思维设计测试用例可以自己独自进行,但是笔者建议最好每个小组每周就一个专题进行半小时的通过头脑风暴的方式进行一次。
整体思维就是看待一个被测产品,不要只见树木不见森林,而要对产品整体进行测试。中国有一家非常有名的通信公司,当时它们的终端产品、核心网、基站单独工作都没有问题,但是整合起来一起工作就发现问题了,于是成立了整体测试部门,笔者也正是这个机会进入了这家企业。另外比如一个电子商务系统,可以建立这么一个测试用例。
(1)注册一个用户。
(2)利用这个用户登录系统。
(3)修改登录密码。
(4)用修改过的密码重新登录。
(5)通过分类选择一些产品放入购物车。
(6)通过查询选择一些产品放入购物车。
(7)进入购物车,修改产品A和产品B的数量。
(8)对产品A下单。
(9)支付产品A。
(10)修改支付密码。
(11)对购物车内的产品B下单并且用修改后的支付密码支付。
(12)确认其中产品A。
(13)对产品A写评语。
(14)对产品B提出退货。
(15)确认产品B退货申请。
(16)退货成功,确认钱是否退回。
如果各位阅读过James,A.Whittaker的《探索式软件测试》[6]一书,整体思维观念与此书中的“最长路径测试法”是一致的。
简单思维法就是用最简单的方法去处理问题。有一次楼道一位朋友听说我是学计算机的,他们家的打印机突然坏了,让我去看一下,我花了一个多小时终于把问题找到了,造成打印机不能工作的原因竟然是没有插上PC机,我想了许多复杂的情形,就是没有想到这一点。在软件测试中比如测试表单提交是否测试一下放弃操作,测试是否接受协议的时候选择不接受等等。其实仍旧在James,A.Whittaker的《探索式软件测试》[6]一书,提到的旅馆区测试也就是这种思维方式。
极端思维正是与简单思维相反的一种思维方式,比如测试转账过程中突然把服务器的电给断了,或者把客户机或服务器网给断了,查看会发现什么情形。前几年就有一个报道,某一用户在通过Internet在电脑上通过一家电子商务网站支付一个商品的时候突然断电了,当这个用户再次打开电脑,连上网进入到这家电子商务网站,发现钱已经从自己MAST卡中扣除,但是电商处显示支付失败,这笔钱就真空消失了。
IT知识包括。
•测试知识。测试分析与设计、自动化测试、性能测试、安全测试、APP测试、敏捷测试、APP测试…。
•自动化测试框架。JUnit、TestNG、unittest、pytest…。
•编码。C、C++、Java、Python、JavaScript、Go、Ruby…。
•操作系统。Windows、Linux、Mac、iOS、线程、进程、队列、调度…。
•算法。各种排序算法、二叉树遍历算法、八皇后算法、汉诺塔算法…。
•数据库。SQL语句、索引、存储过程、MySQL、Oracle、Sqlite3…。
•网络架构。集群架构、分布式架构、微服务架构…。
•前端技术。HTML、CSS、JavaScript、jQuery、Zepto、UnderScore、Backbone、Knockout、React、 AngularJS…。
•开发框架。Java的SpringMVC、Spring、Mybatis、Dubbo和Python的Django、Flask…。
•软件工程。瀑布模型、XP、Scrum、DevOps、V模型、W模型、X模型、H模型…。
•最新技术。云计算、大数据、人工智能、区块链…。
IT知识包括的内容真是非常多,作为软件测试人员应该成为一名T型人才,就是一专多能的人才。俗话说技高不压身,拥有IT知识越丰富,做好软件测试分析和设计工作会越得心应手,也越不会被开发瞧不起。但是人的尽力是有限的,业界所谓的全栈型人才也是在某一方面做到全栈,不可能样样都精通。
在这里还是要重审笔者的一向观点,刚刚从大学象牙塔出来的同学们,不要立刻从事软件测试职业,最好从事3-5年让开发以后,根据自己的具体情况再选择进入。一个理工科毕业的,特别是数学专业毕业的从事过软件开发工作的同学往往在软件测试工作上做得会更好,发展空间会更大,也就是说天花板会更高一些(当然业内也有一些文科、医科、农林牧副渔的同学测试工作也做得很好,毕竟这是少数)。
俗话说:术业有专攻,闻道有先后。学习专业的业务知识对于非科班出生的软件测试工程师的确有些难度。我曾经从事过门户网站、电子商务网站、ERP、CRM系统、数字电视机顶盒、银行系统、财会系统以及通信产品的测试与开发工作,深知作为一个计算机专业出生的软件工程师来熟悉这些业务,特别是数字电视机顶盒、银行系统、财会系统以及通信产品,的确难度不小。我有好些同行也正因为学的是软件专业,后来到机械、电子、银行、税务等部门帮助这些企业做信息化建设,由于不能了解企业的业务需求,从而换公司或者离开IT行业。总结起来可以从以下几点做起。
•直接向客户请教。
客户是需求的提出者,作为一名传统的需求分析师,通常从产品研发层面获取需求,但是作为一名专业的需求分析师还需要从质量方面获取质量需求。一般而言,质量需求关注比较细节的问题,比如密码有无强度限制?登录是否需要验证码?所以建议获取质量需求的时候,不要采取面对面的方式,而可以采取事先列个清单,然后让用户去确认的形式。每次尽可能在充分理解需求的前提下,把要问的问题想全面,减少调研的次数,过多的调研会造成用户的疲倦感。
•阅读需求规格说明书。
如果接受的是一个历史产品,认证阅读需求规格说明书(SRS)也是一种很好的手段,对于不明白的地方,可以结合2.2.3-2 提问能力,向相关人员提出问题,从而解决疑惑。
•阅读《用户使用手册》。
如果产品是一个以维护为主的产品,对于非互联网产品,往往存在《用户使用手册》。阅读这份材料也是了解业务知识的重要手段。但是《用户使用手册》是面对于用户专业人士而写的,里面有一些名词和术语,如果没有一定的专业知识,可能阅读起来会比较困难。
•阅读同事写的测试用例和缺陷报告。
阅读同事写的测试用例和缺陷报告,在某种程度上,缺陷报告其实也可以看作是测试用例。测试用例,特别是自动化测试用例,往往描述的是产品最基本的业务逻辑,是那些来公司比你早的同事对业务分析后的测试分析结论,阅读这些材料,对于一位刚来公司的新手快速掌握公司业务是非常重要的,在这里刚来公司的新手可以使软件测试人员,甚至也可以是包括软件开发、运维、项目管理等其他人员。
•建议采用DDD开发模式。
领域驱动设计(Domain Driven Design,DDD)[23]尝试通过其自有的原则与套路来解决软件的复杂性问题,它将研发者的目光首先聚焦在业务本身上,使技术架构和代码实现成为软件建模过程中的“副产品”。由此可见DDD开发模式目的就是在开发者与业务需求者之间建立起一座桥梁,如果采用DDD开发模式,对于测试人员了解业务同样也是一种非常有效的手段。
•从书籍、官网、网络、论坛中学习。
尽管前面的方法可以了解系统的业务需求,但是如果对业务一点没有接触过,从0开始去了解这些知识是非常必要的。在最开始的时候,通过书籍和官网来系统地学习业务知识是非常有用的。虽然也可以从网络和论坛中来学习,但是书籍和官网比较系统,特别是官网没有进行其他人的二次加工,可信性是比较高的,而网络、论坛中的错误观点比较多,且为碎片化知识。建议各位以书籍和官网学习为主,而以网络和论坛学习为辅。
应该如何来看待失败呢?
•不要惧怕失败。
中国有句古话:失败是成功之母。首先不要惧怕失败,失败是必然的,成功才是偶然,关键要学会从失败中找出规律,找出原因,从而避免再次犯同样的错误。在哪里跌倒,就从哪里爬起来。
•不能总是失败。
虽然失败是成功之母,但是不能总是失败,总是失败会影响士气。所以仍旧需要尽快从失败中找出规律,早日成功。特别是在以前跌倒的地方再一次跌倒,这个是绝对不被允许的。
•与其他人一起分享失败。
自己一个人总结失败经验往往效率是不高的,要学会拉下面子,把失败与你的好友分享,让他们帮助你跳出个人的思维框架,往往会获得早日的成功,在这里特别需要注意的是学会拉下面子,拉下面子并不表示你没有能力,别人会笑话你。你只有拉下面子才表示你有决心做好事情,并且你向好友拉下了面子,如果他是你真正的好友,他不但不会嘲笑你,反而会觉得你是信任他的,从而他会很好的帮助你分析失败后面的原因。当然也可能你找的好友并非你真正的好友,但是你也可以从此看出他对你的态度,大不了以后就再也不找他了。
•回顾会议是很好的活动。
在Scrum框架下,每个Sprint后都有一个回顾会议(Retrospective Meeting),回顾会议是一种集体总结经验与教训的方式。在回顾会议中不断要总结失败的原因,也要总结成功的经验。经验和教训是一个事情的两个方面,是同样重要的。•从各个方面去总结。
要学会从方法、思维、知识、技能、经验、性格、客观因素、主观因素、情商等各个方面去分析总结,而不要限制于一个方面。由于考虑方面步骤,造成低效的总结也是经常存在的,在回顾会议下,建议大家一起用头脑风暴的方式去分析问题。
为什么别人能够找到BUG,而我却找不到?为什么别人能够帮助开发提高质量,而我却不行?这些大概都是许多测试人员经常会问自己的问题。记得十几年前就有一句话:开发如西医,拥抱技术变化;测试如中医,拥抱经验。虽然这句话有些片面,但是也存在部分正确的地方,在测试领域,除了自动化测试的框架在不断地变化,但是从软件分析和设计的层面上而言经验是十分重要的,作者本人认为是最重要的。
其实不管中医西医、开发测试,经验都是非常重要的。我有一位朋友的母亲,前一段时间一直觉得腹胀,许多医生都认为他是肠胃问题,吃了许多开胃健脾,帮助消化的药,都没有多少改善。后来有一位医生(在部队里专业排名Top4)认为她得了一种很严重的妇科疾病,需要手术治疗,虽然手术前的各种检查结果都非常正常,但是这位医生根据自己多年的经验(或者说自觉)认为一定要进行手术,否则后果会很危险,结果在手术进行中发现的确是哪位医生猜想的疾病,并且十分严重,幸亏诊断比较早而且准确,后来病人恢复得很好,还在各处旅游。
经验不同于知识,是不能被通用化后被归类的,仅作为思维方式的一种产出在某一个领域被分享。虽然James Batch在《软件探索式测试》一书中以漫游的方式总结了商业区、历史区、娱乐区、旅游区、旅馆区和破旧区六种测试类型,但是也不是系统的,并且在某些方面还有些得牵强附会。
获取经验的积累在于一个“广”字。涉猎面“广”,比如你从事过多领域的测试,可以相互之间学习借鉴。比如嵌入式软件的测试,产品的可靠性测试是非常关键的,经常在使用过程中测试突然拔插电源对软件及硬件的影响。在金融领域,当业务正在进行,突然拔插电源或者网卡,可能也是一种好的测试思想。阅读量“广”,有事没事多翻翻同事们写的测试用例或者测试缺陷报告,不仅像前面所述对提高业务的理解有益,同时通过阅读,理解别人为什么通过什么样的思考来设计这个测试用例,发生某个缺陷后面隐藏了什么思维模式,从而获得更多的测试经验。朋友圈“广”,在当今移动互联网时代,通过类似于微信、极客时间等APP产品,多与大家一起讨论测试问题,多帮别人去解决具体的问题,都是提升经验的好的方法。
经验在于积累,积累以后要擅于分享。在这里分享可以是以学习班、讨论班的方式进行,也可以以WiKi等书面的形式进行。分享一方面可以锻炼表达能力,另一方面也可以对经验进行再加工,通过讨论去伪存真,找到更加深入理解或者对不正确的地方加以改正。当然经验的积累也是通过PDCA的方式螺旋式提升的。
对于测试分析与设计者而言,沟通主要可以考虑与客户、开发、运维和领导的沟通。
•与客户的沟通。
与客户的沟通表现在与客户交流从而深入挖掘测试或者质量的需求,另外也可以通过与客户的交流,解决客户对技术的疑问。
•与开发的沟通。
与开发的沟通一定要体现出测试的价值,在研发领域测试经常被开发看不起,网上、书上、论坛上对于这类讨论很多,但是笔者认为关键点在于测试人员要提高自己的IT技术水平,要让开发认为测试是对他们工作的有力补充,而不是来找麻烦的。另一方面要让开发懂得共同对产品质量负责的意识,产品质量不是通过测试提高的,而是通过优秀的代码得到的。这里要特别提一下TDD,T不仅仅是指单元测试代码,而是包括接口测试、GUI测试甚至是用文本书写的测试用例在内的所有测试用例。在开发之前,先设计出测试用例,共享给开发,让开发尽可能在第一时间做正确的事情,让BUG消灭在萌芽状态甚至不发生,这才是正确做事的方法。
•与运维的沟通。
与运维的沟通主要体现在协助安装产品和做好线上测试。在DevOps下可以用自动化工具来把产品部署到生产环境中。测试人员应该有能力检查部署后产品是否能够正确地运行,需要对部署到生产环境中的产品进行冒烟测试,验证一下基本功能是否正确。许多企业没有实施DevOps或者没有自动化部署,就还需要测试人员帮助运维在生产环境中部署产品。对于一些正在使用的产品或者迭代开发的产品,在线升级也是非常重要的,在在线升级过程中要尽可能不影响客户的正常使用,如果升级失败需要回滚到升级前的状态,所以在真正升级之前,利用升级代码在研发环境下模拟做好升级和回滚测试也是非常重要的。
现在线上测试也变得越来越重视,比如全链路压测、基于微服务的契约测试等等。做好线上测试需要在运维的指导下进行,并且注意测试完毕一定要把测试环境清理干净,所以线上测试进行之前必须要做好相应的测试计划与设计。
•与领导的沟通。
与领导的沟通主要体现在客观反映产品质量的实际情况,额就是说不要把质量说得过好或者过差。另外对于需要的是否可以发布正式版本,可以给领导提供建议,但是千万不要替领导做出决策,毕竟领导是产品的投资方(或者投资方的代理人),作为打工性质的测试工程师是没有权限承担的。
前面已经提到过提问的技巧。机械工业出版社出版的《学会提问》是很好的一本书,推荐各位阅读。在这里我归纳了下,需要做到以下几点。
•不提网上可以查到的知识。
随着移动互联网的普及,获得知识的途径简直太方便了,只要坐在沙发上,泡上一杯香浓美味的咖啡,打开各种APP,就可以获得各种各样的知识了。所以对于直接能够在网上、现有的文档中可以查到的知识,特别是带有普及性质的知识,比如什么是5G?移动通信有几种制式?等问题问别人了,毕竟别人回答你的问题,会消耗他的时间和精力。当通过查询,可能问题就全部或者部分解决,如果部分解决甚至不容易或者查不到所要的知识,再询问也为时不晚。
•不要害怕提问。
另一种极端情况是由于担心消耗别人的时间和尽力从而不敢提问也是不可取的。有时候一个人埋头研究了大半天还没有解决的问题,问了一下旁边的同事,立刻就解决了,类似这种情况也是经常发生的。但是在什么时候去提问?是没有唯一的答案的,需要各位自己去总结。
•带着思考去提问。
提问的时候需要带着自己的思考,对于某一类问题,可以自己先有一个不明确的答案,在提问工程中,看看回答问题人是否与你想象的答案保持一致,如果不一致及时分析下原因,看看是自己理解有问题还是对方理解有局限,然后可以进一步的去发问,从而得到问题的最终答案。
•对答案要有自己的分析。
人毕竟是人,是人就会犯错误,所以别人回答你的问题,结果是否正确需要你自己去判断。一概全信或者一概全不信都是不可取的。一概全信是没有独立思考意识的体现,而一概全不信那为什么要提问呢。对答案分析过程中过于固执也是不可取的,要学会换位思考,以无知者的眼光来看待一个全新的领域问题。
•学会选择提问对象。
学会选择提问对象也是一个很重要的方面,比如在广州街头,向一个说着浓重东北口音大妈询问路线,是明显不可取的。向什么人问什么问题是很有讲究的。
•不耻下问、不羞上问。
对于比自己阅历少的年轻人与比自己阅历大的老人提问都不要带有羞耻之心,不懂就是不懂,问问题不是故意刁难人,而是寻求问题的答案。所以在问问题和回答别人问题过程中都要注意对事不对人。
在这里特别要提一下基因能力。大家知道爱迪生说过:“成功=99%的努力+1%的天赋,但有时发现1%的天赋才是至关重要的”。我国某一位著名的女歌唱家也说过:“我尽可能接受有音乐天赋的学生,一位优秀的歌手好的嗓音占有决定性作用,然后才是发音技巧”。由此可见天赋,也就是这里所说的基因,在测试分析和设计领域也是占有很重要的作用的。
以前我有一位同事,他总是发现不了分配给他模块的一些明显的缺陷,大家也经常分享测试用例给他看,也让他对阅读大家写的的缺陷报告,但是他依旧发现不了缺陷。后来这个同事离开了公司。半年多后我获得了他的QQ号,与他重新建立了联系,当我问他是否还在从事软件测试工作吗?他的回答是:“你们全是些歪脑子,我现在做技术支持不做测试了”。
的确,不可否认,从事测试行业,特别是做软件测试分析和设计,是需要基因的,有些人很难发现缺陷,而有些人很容易发现缺陷。这些并不是努力和学习可以解决的问题。现在有这么一句话,我非常赞成:“世上没有笨蛋,关键是不是让他坐在他适合的职位上”。所以某些人在自己岗位上做不出成就来,就要问一下自己,自己是不是适合这个岗位?是否具有这个岗位的基因?