2023年6月21日发(作者:)

软件测试52讲-笔记(持续更新中...)软件测试52讲01 | 你真的懂测试吗?从“⽤户登录”测试谈起在测试⼯作当中,设计测试⽤例⽅法包括很多种:等价类划分、边界值分析、错误推测、因果图、判定表驱动、正交试验设计、功能图、场景等。但是作为测试⼯程师,我们的⽬标是要保证系统在各种应⽤场景下的功能是符合设计要求的,所以我们就要考虑⽤例内容就需要更多、更全⾯。当我们拿到“⽤户登录”的功能需求时,可以结合等价类划分和边界值分析⽅法来设计测试⽤例:⼊门级别的测试⽤例:1. 输⼊已注册的⽤户名和正确的密码,验证是否登录成功;2. 输⼊已注册的⽤户名和不正确的密码,验证是否登录失败,并且提⽰信息正确;3. 输⼊未注册的⽤户名和任意密码,验证是否登录失败,并且提⽰信息正确;4. ⽤户名和密码两者都为空,验证是否登录失败,并且提⽰信息正确;5. ⽤户名和密码两者之⼀为空,验证是否登录失败,并且提⽰信息正确;6. 如果登录功能启⽤了验证码功能,在⽤户名和密码正确的前提下,输⼊正确的验证码,验证是否登录成功;7. 如果登录功能启⽤了验证码功能,在⽤户名和密码正确的前提下,输⼊错误的验证码,验证是否登录失败,并且提⽰信息正确。有了些许经验的会增加测试点的⽤例:1. ⽤户名和密码是否⼤⼩写敏感;2. 页⾯上的密码框是否加密显⽰;3. 后台系统创建的⽤户第⼀次登录成功时,是否提⽰修改密码;4. 忘记⽤户名和忘记密码的功能是否可⽤;5. 前端页⾯是否根据设计要求限制⽤户名和密码长度;6. 如果登录功能需要验证码,点击验证码图⽚是否可以更换验证码,更换后的验证码是否可⽤;7. 刷新页⾯是否会刷新验证码;8. 如果验证码具有时效性,需要分别验证时效内和时效外验证码的有效性;9. ⽤户登录成功但是会话超时后,继续操作是否会重定向到⽤户登录界⾯;10. 不同级别的⽤户,⽐如管理员⽤户和普通⽤户,登录系统后的权限是否正确;11. 页⾯默认焦点是否定位在⽤户名的输⼊框中;12. 快捷键Tab和Enter等,是否可以正常使⽤。其实上述都是根据明显的功能上的需求来设计⽤例的,但在软件测试的维度来看,除了这些显性的功能需求,⾮功能性需求也很重要,它涉及到安全性、性能及兼容性三⼤⽅⾯,这些容易被我们遗漏忽视的,往往也是决定软件质量的关键因素。安全性测试⽤例包括:1. ⽤户密码后台存储是否加密;2. ⽤户密码在⽹络传输过程中是否加密;3. 密码是否具有有效期,密码有效期到期后,是否提⽰需要修改密码;4. 不登录的情况下,在浏览器中直接输⼊登录后的URL地址,验证是否会重新定向到⽤户登录界⾯;5. 密码输⼊框是否不⽀持复制和粘贴;(补充:右键⽅式和热键⽅式)6. 密码输⼊框内输⼊的密码是否都可以在页⾯源码模式下被查看;7. ⽤户名和密码的输⼊框中分别输⼊典型的“SQL注⼊攻击”字符串,验证系统的返回页⾯;8. ⽤户名和密码的输⼊框中分别输⼊典型的“XSS跨站脚本攻击”字符串,验证系统⾏为是否被篡改;9. 连续多次登录失败情况下,系统上是否会阻⽌后续的尝试以应对暴⼒破解;10. 同⼀⽤户在同⼀终端的多种浏览器上登录,验证登录功能的互斥性是否符合设计预期;11. 同⼀⽤户先后在多台终端的浏览器上登录,验证登录是否具有互斥性。性能压⼒测试⽤例包括:1. 单⽤户登录的响应时间是否⼩于3秒;2. 单⽤户登录时,后台请求数量是否过多;3. ⾼并发场景下⽤户登录的响应时间是否⼩于5秒;4. ⾼并发场景下服务端的监控指标是否符合预期;5. ⾼集合点并发场景下,是否存在资源死锁和不合理的资源等待;6. 长时间⼤量⽤户连续登录和登出,服务器端是否存在内存泄漏。兼容性测试⽤例包括:1. 不同浏览器下,验证登录页⾯的显⽰以及功能正确性;2. 相同浏览器的不同版本下,验证登录页⾯的显⽰以及功能正确性;3. 不同移动设备终端的不同浏览器下,验证登录页⾯的显⽰以及功能正确性;4. 不同分辨率的界⾯下,验证登录页⾯的显⽰以及功能正确性。由于在整个项⽬周期迭代中,测试因受限于时间成本与经济成本,是⽆法去穷尽测试所有满⾜前提条件的数据组合的,⽽是采⽤基于风险较⼤的驱动模式,侧重选择测试范围和设计测试⽤例,以寻求缺陷风险和研发成本之间的平衡。其他补充:1. ⽹络延迟或者弱⽹或者切换⽹络或者断⽹时是否正常登录;2. 是否⽀持第三⽅登录;3. 是否可记住密码,记住的密码保存是否加密,记住密码是否有有效期,过期之后是否会清空密码;4. 密码强弱性校验,数据库设计和数据操作时是否合理;5. ⽤户登录过程中log是否对个⼈信息及密码明⽂打印;6. 登录⽤户限制:⽐如同时⽀持10个⽤户登录,同时9个或者11个⽤户登录是否正常或者提⽰信息正确;7. 未激活的⽤户登录;8. 被停⽤的⽤户登录;9. 涉及资产风险的,对登录设备和地区检测;10. 为空和输⼊空字符串时的校验;11. 使⽤中⽂键盘输⼊字母时和使⽤英⽂键盘输⼊字母时传给后端的字符串长度是否⼀致;(补充:全⾓与半⾓符号的区分,软键盘的输⼊)12. 登录成功后的session时效设置;13. 密码⼀栏是否需要设置明暗码切换按钮;14. 输⼊栏是否设置快速删除按钮;15. 是否⽤到缓存;16. ⽤户名和密码是否对空格敏感;17. 更改密码后是否还能⽤之前的密码登录;18. ⼀个⽤户是否具备多种登录⽅式(⽤户名,⼿机号,邮箱等);19. 第三⽅登录修改密码的影响(解绑后是否能正常登录和登出);20. 是否可以使⽤登录的API发送登录请求,并绕开验证码校验;21. 是否可以⽤抓包⼯具抓到的请求包直接登录;22. 截取到的token等信息,是否可以在其他终端上直接使⽤,绕开登录。Token过期时间校验;23. 除了前端校验格式长度,后端是否也校验;24. 登录后输⼊登录URL,是否还能再次登录?如果能,原登录⽤户是否变得⽆效25. 其他终端修改密码后,原记住密码终端是否提⽰密码已更改;26. 检查HTTP头的refer URL是否为登录起始页的URL,如果不同是否给出正确的提⽰并做⽇志记录和报警;27. 对某些系统,还要验证客户端证书是否与⽤户名匹配,不匹配时、或者客户端证书过期以及即将过期三种情况是否正确处理和提⽰;28. 已登录⽤户,杀死APP进城后,再次打开APP是否依然为登录状态;29. 对于银⾏系统,密码输⼊框是否可以正常调⽤密码控件;(补充:在不同安装证书的环境下)02 | 如何设计⼀个“好的”测试⽤例?其实在实际项⽬⼯作当中,软件⽣命周期内都会有不同的类型测试。⽐如,传统软件的开发阶段通常会有单元测试,软件模块集成阶段会有代码级集成测试,打包部署后悔有⾯向终端⽤户的GUI测试;再⽐如,电商⽹站的测试会分为服务端基于API的测试、中间件测试、前端GUI测试等。那么⼀个“好的”测试⽤例必须具备哪些特征?1. 整体完备性:“好的”测试⽤例⼀定是⼀个完备的整体,是有效测试⽤例组成的集合,能够完全覆盖测试需求;2. 等价类划分的准确性:是对于每个等价类都能保证只要其中⼀个输⼊测试通过,其他输⼊也⼀定测试通过;3. 等价类集合的完备性:需要保证所有可能的边界值和边界条件都已经正确识别;但对于⼤多数软件测试⽽⾔,综合使⽤等价类划分、边界值分析和错误推测这三⼤类⽅法就⾜够了。第⼀、等价类划分⽅法等价类中任意⼀个输⼊数据对于揭露程序中潜在错误都具有同等效果。后续我们只要从每个等价类中任意选取⼀个值进⾏测试,就可以⽤少量具有代表性的测试输⼊取得较好的测试覆盖结果。有效等价类:年按⼈类最⾼年龄120岁推算,有效年份应为2019~1899年中间;⽉应为1~12⽉;⽇应为1~31⽇;⽆效等价类:年⼩于1899年或⼤于2019年;⽉等于00或⼤于12;⽇等于00或⼤于31⽇;第⼆、边界值分析⽅法是对等价类划分的补充,从⼯程实践经验中可以发现,⼤量的错误发⽣在输⼊输出的边界值上,所需要对边界值进⾏重点测试,通常选取正好等于、刚刚⼤于或刚刚⼩于边界的值作为测试数据。选取闰年⾮闰年20040229以及20050228;⼤⼩⽉⽇期20000630以及2000731;第三、错误推测⽅法是基于对被测软件系统设计的理解、过往经验以及个⼈直觉,推测出软件可能存在的缺陷,从⽽有针对性的设计测试⽤例的⽅法。这个⽅法强调的是对被测试软件的需求理解以及设计实现的细节把握,当然还有个⼈的能⼒。⾝份证号不可重复;数据库链接失败;在具体设计⽤例时,⾸先需要搞清楚每⼀个业务需求所对应的的多个软件功能需求点,然后分析每个软件功能需求点对应的多个测试需求点,最后再针对每个测试需求点来设计测试⽤例。具体到测试⽤例本⾝的设计,还有两个关键点需要注意:1. 从软件功能需求出发,全⾯地、⽆遗漏地识别出测试需求是⾄关重要的,这将直接关系到⽤例的测试覆盖率。(⽐如,如果你没有出⽤户登录功能的安全性测试需求,那么后续设计的测试⽤例就完全不会涉及安全性,最终造成重要测试漏洞。)2. 对于识别出的每个测试需求点,需要总和运⽤等价类划分、边界值分析和错误推测⽅法来全⾯地设计测试⽤例。需要注意的是,要综合运⽤这三种法法,并针对每个测试需求点的具体情况,进⾏灵活选择。以“⽤户登录”的功能性测试需求为例,我们⾸先应该对“⽤户名”和“密码”这两个输⼊项分别进⾏等价类划分,列出对应的有效等价类和⽆效等价类,对于⽆效等价类的识别可以采⽤错误推测法(如⽤户名包含特殊字符等),然后基于两者可能的组合,是基础第⼀批测试⽤例。等价类划分完后,我们还需要补充“⽤户名”和“密码”这两个输⼊项的边界值的测试⽤例,⽐如⽤户名为空(NULL)、⽤户名长度刚好⼤于允许长度等。设计测试⽤例的其他经验:1. 需要深⼊理解被测试软件的架构,对内部的架构有清楚的认识,⽐如数据库连接⽅式、数据库的读写分离、消息中间件的配置、缓存系统的层级分布、第三⽅系统的集成等。2. 必须深⼊理解被测软件的设计与实现细节,深⼊理解软件内部的处理逻辑。3. 单单根据测算需求点设计的⽤例,只能覆盖“表⾯”的⼀层,往往覆盖不到内部的处理流程、分⽀处理,⽽没有覆盖到的部门就很可能出现缺陷遗漏。在具体实践中,你可以通过代码覆盖率指标找出可能的测试遗漏点。4. 切忌不要以开发代码的实现为依据设计测试⽤例。因为开发代码实现的错误会导致测试⽤例也出错,所以你应该根据原始需求设计测试⽤例。5. 在实际测试⼯作当中我们还可以建⽴常见缺陷知识库,那么在⽤例设计的过程中,会使⽤缺陷知识库作为检查点列表,去帮助优化补充测试⽤例的设计。03 | 什么是单元测试?如何做好单元测试?单元测试是指,对软件中的最⼩可测试单元在与程序其他部分相隔离的情况下进⾏检查和验证的⼯作,这⾥的最⼩可测试单元通常是指函数或者类。如何做好单元测试?⾸先必须要弄清楚单元测试的对象是代码,以及代码的基本特征和产⽣错误的原因,然后我们必须要掌握单元测试的基本⽅法和主要技术⼿段,⽐如,什么事驱动代码、桩代码和Mock代码等。第⼀,代码的基本特征与产⽣错误的原因⽆论是开发语⾔还是脚本语⾔,都会有条件分⽀、循环处理和函数调⽤等最基本的逻辑控制,如果抛开代码需要实现的具体业务逻辑,仅看代码结构的话,所有的代码都是在对数据进⾏分类处理,每⼀次条件判定都是⼀次分类处理,嵌套的条件判定或者循环执⾏,也是在做分类处理。如果有任何⼀个分类遗漏,都会产⽣缺陷;如果有任何⼀个分类错误,也会产⽣缺陷;如果分类正确也没有遗漏,但是分类时的处理逻辑错误,也会产⽣缺陷。在具体⼯程实践中,开发⼯程师为了设计并实现逻辑功能正确的代码,通常会有如下的考虑过程:1)如果要实现正常的功能逻辑,会有哪⼏种正常的输⼊;2)是否有需要特殊处理的多种边界输⼊;3)各种潜在⾮法输⼊的可能性以及如何处理;⽽现在很多公司都省略了单元测试这⼀过程。主要原因在于敏捷开发阶段,周期短、迭代快,开发诵读也要快的情况下,省略单元测试可以节约很⼤的时间成本以及⼈⼒成本。但放在长远的时间线上来看,因为不停的在迭代会让原先成⽴的接⼝出现⼀些隐患的bug,⽽导致不知道是那⾥出了问题,再去查找定位难免就会多浪费时间,这时候单元测试的作⽤就体现了,每次迭代的功能代码与测试代码对应,跑⼀遍测试代码就知道哪⾥出了问题,可及时修改。04 | 为什么要做⾃动化测试?什么样的项⽬适合做⾃动化测试?⾃动化测试,是把⼈对软件的测试⾏为转化为由机器执⾏测试⾏为的⼀种实践,对于最常见的GUI⾃动化测试来讲,就是由⾃动化测试⼯具模拟之前需要⼈⼯在软件界⾯上各种操作,并且⾃动验证其结果是否符合预期。⾃动化测试本质是先写⼀段代码,然后去测试另外⼀段代码,所以实现⾃动化测试⽤例本⾝是属于开发⼯作,需要投⼊⼤量时间和精⼒,并且已经开发完成的⽤例还必须随着被测对象的改变⽽不断更新,还需要为此付出维护测试⽤例的成本,⽽当维护成本⾼于其节省的测试成本时,⾃动化也就失去了价值与意义,我们也就需要在是否使⽤⾃动化测试上做权衡取舍了。为什么需要⾃动化测试?优势:1. 可代替⼤量⼿⼯机械重复性操作;2. ⼤幅度提升回归测试效率,适合敏捷开发过程;3. 更好的利⽤⽆⼈值守时间,去频繁的执⾏测试;4. 可以⾼效实现某些⼿⼯测试⽆法完成或者代价巨⼤的测试类型(如关键业务要7*24⼩时持续运⾏的系统稳定性和测试⾼并发场景的压⼒测试等);5. 可以保证每次测试执⾏的操作以及验证的⼀致性和可重复性,避免⼈为的遗漏和疏忽;劣势:1. ⽆法取代⼿⼯测试,它只能替代⼿⼯测试中执⾏频率⾼、机械化的重复步骤;2. ⽐⼿⼯测试要脆弱,⽆法应对被测系统的变化,它并不‘智能’,只按部就班的执⾏事先定义好的测试步骤并验证测试结果。对于执⾏中出现的明显错误和意外事件,⾃动化测试没有任何处理能⼒;3. ⾃动化测试⽤例的开发⼯作量远⼤于单次的⼿⼯测试,所以只有当开发完成的测试⽤例的有效执⾏次数⼤于5次时,才能收回⾃动化测试的成本;4. ⼿⼯测试发现bug数量通常⽐⾃动化测试的要多,并且⾃动化测试仅仅能发现回归测试范围的bug;5. 实⾏⾃动化测试的初期,⽤例开发效率通常都很低,⼤量初期开发的⽤例通常会在整个⾃动化测试体系成熟,和测试⼯程师全⾯掌握测试⼯具后,需要重构。什么样的项⽬适合⾃动化测试?1. 需求稳定,不会频繁变更;2. 研发和维护周期长,需要频繁执⾏回归测试;3. 需要在多种平台上重复运⾏相同的场景4. 某些测试项⽬通过⼿⼯测试⽆法实现,或者⼿⼯成本太⾼;5. 被测软件的开发较规范,能够保证系统的可测试性总之,对于⼀些中长期项⽬,对⽐较稳定的软件功能进⾏⾃动化测试,对变动较⼤或者需求暂时不明确的功能进⾏⼿⼯测试,最终⽬标是⽤20%的精⼒去覆盖80%的回归测试。05 | 你知道软件开发各阶段都有哪些⾃动化测试技术吗?其实在软件研发⽣命周期的各个阶段都有⾃动化测试技术的存在,对提升测试效率都有很⼤的作⽤。单元测试的⾃动化技术⾸先,单元测试本⾝就是⾃动化的,因为它根据软件详细设计采⽤等价类划分和边界值分析⽅法设计测试⽤例,在测试代码实现后再以⾃动化的⽅式统⼀执⾏。但这仅仅是⼀部分,并没有完整地描述单元测试“⾃动化”的内涵。从⼴义上讲,单元测试阶段的“⾃动化”内涵不仅仅指测试⽤例执⾏的⾃动化,还应该包含以下五个⽅⾯:1. ⽤例框架代码⽣成的⾃动化;2. 部分测试输⼊数据的⾃动化⽣成;3. ⾃动桩代码的⽣成;4. 被测代码的⾃动化静态分析;5. 测试覆盖率的⾃动统计与分析;代码级集成测试的⾃动化技术代码级集成测试是指将已经开发完成的软件模块放在⼀起测试。从测试⽤例设计和测试代码结构来看,它和单元测试⾮常相似,都是对被测试函数以不同的输⼊参数组合进⾏调⽤并验证结构,只不过代码级集成测试的关注点,更多的是软件模块之间的接⼝调⽤和数据传递。⽽与单元测试最⼤的区别只是,代码级集成测试中被测函数内部调⽤的其他函数必须是真实的,不允许使⽤桩代码代替,⽽单元测试汇总允许使⽤桩代码来模拟内部调⽤的其他函数。代码级集成测试对测试框架的要求⾮常⾼,这个框架除了可以顺利装载⾃⼰的软件模块外,还必须能装载其他相互依赖的模块,做到被测软件模块可运⾏(Runnable)。由于代码级集成测试主要应⽤在早期⾮互联⽹的传统软件企业,那时候的软件以“单体”应⽤居多,⼀个软件内部包含⼤量的功能,每⼀个软件功能都是通过不同的内部模块来实现的,那么这些内部模块在做集成的时候,就需要做代码级集成测试。⽽现在的开发理念追求的是系统复杂性的解耦,会去尽量避免“⼤单体”应⽤,采⽤Web Service或者PRC调⽤的⽅式来协作完成各个软件功能。所以现在的软件企业,尤其是互联⽹企业,基本不会去做代码级集成测试,在这⾥也就不再进⼀步展开了。Web Service测试的⾃动化技术Web Service测试,主要是指SOAP API和REST API这两类API测试,最典型的是采⽤SoapUI或Postman等类似的⼯具。但这类测试⼯具基本都是界⾯操作⼿动发起Request并验证Response,所以难以和CI/CD集成,于是就出现了API⾃动化测试框架。对于基于代码的API测试⽤例,通常包含三⼤步骤:1. 准备API调⽤时需要的测试数据;2. 准备API的调⽤参数并发起API的调⽤;3. 验证API调⽤的返回结果;GUI测试的⾃动化技术GUI测试的⾃动化技术可能是我们最熟悉的,也是发展时间最长、应⽤最⼴的⾃动化测试技术。核⼼思想是,基于页⾯元素识别技术,对页⾯元素进⾏⾃动化操作,以模拟实际终端⽤户的⾏为并验证软件功能的正确性。⽬前,GUI⾃动化测试主要分为两⼤⽅向,传统Web浏览器和移动端原⽣应⽤(Native App)的GUI⾃动化。虽然⼆者采⽤的具体技术差别很⼤,但是⽤例设计的思路类似。对于传统Web浏览器的GUI⾃动化测试,业内主流的开源⽅案采⽤Selenium,商业⽅案采⽤Micro Focus的UFT(前⾝是HP的QTP);对于移动端原⽣应⽤,通常采⽤主流的Appium,它对iOS环境集成了XCUITest,对Android环境集成了UIAutomator和Espresso。06 | 你真的懂测试覆盖率吗?测试覆盖率通常被⽤来衡量测试的充分性和完整性,从⼴义的⾓度来讲,测试覆盖率主要分为两⼤类,⼀类是⾯向项⽬的需求覆盖率,另⼀类是更偏向技术的代码覆盖率。需求覆盖率需求覆盖率是指测试对需求的覆盖程度,通常的做法是将每⼀条分解后的软件需求和对应的测试建⽴⼀对多的映射关系,最终⽬标是保证测试可以覆盖每个需求,以保证软件产品的质量。通常采⽤ALM,Doors和TestLink等需求管理⼯具来建⽴需求和测试的对应关系,并以此计算测试覆盖率。但是需求覆盖率的统计⽅式不在适⽤于现在的敏捷开发模式,所以现在谈到测试覆盖率,⼤多指的是代码覆盖率。代码覆盖率代码覆盖率是指,⾄少被执⾏了⼀次的条⽬数占整个条⽬数的百分⽐。如果“条⽬数”是语句,对应的就是代码⾏覆盖率;如果“条⽬数”是函数,对应的就是函数覆盖率;如果“条⽬数”是路径,那么对应的就是路径覆盖率。依此类推,可以得到绝⼤多数常见的代码覆盖率类型的定义。⾏覆盖率⼜称为语句覆盖率,指已经被执⾏到的语句占总可执⾏语句(不包含类似C++的头⽂件声明、代码注释、空⾏等等)的百分⽐。这是最常⽤也是要求最低的覆盖率指标。实际项⽬中通常会结合判定覆盖率或者条件覆盖率⼀起使⽤。判定覆盖⼜称为分⽀覆盖,⽤以度量程序中每⼀个判定的分⽀是否都被测试到了,即代码中每个判定的取真分⽀和取假分⽀是否各被覆盖⾄少各⼀次。⽐如,对于if(a>0&&b>0),就要求覆盖“a>0&&b>0”为TRUE和FALSE各⼀次。条件覆盖是指,判定中的每个条件的可能取值⾄少满⾜⼀次,度量判定中的每个条件的结果TRUE和FALSE是否都被测试到了。⽐如,对于if(a>0&&b>0),就要求“a>0”取TRUE和FALSE各⼀次,同时要求“b>0”取TRUE和FALSE各⼀次。代码覆盖率的价值统计代码覆盖率的根本⽬的是找出潜在的遗漏测试⽤例,并有针对性的进⾏补充,同时还可以识别出代码中那些由于需求变更等原因造成的不可达的废弃代码。代码覆盖率的局限性⾼的代码覆盖率不⼀定能保证软件质量,因为代码覆盖率的计算是基于现有代码的,并不能发现那些“未考虑某些输⼊”以及“未处理某些情况”形成的缺陷。07 | 如何⾼效填写软件缺陷报告缺陷报告是测试⼯程师与开发⼯程师交流沟通的重要桥梁,也是测试⼯程师⽇常⼯作的重要输出。⼀般我们会觉得这并不是什么难事,毕竟软件企业通常都有缺陷管理系统,⽐如典型的ALM(以前的Quality Center)、JIRA、Bugzilla、BugFree和Mantis等。当使⽤这类系统递交缺陷时,会⾃动⽣成模板,你只要按照其中的必填字段提供缺陷的详细信息就可以了。缺陷报告的组成1)缺陷标题:缺陷标题通常是别⼈最先看到的部分,是对缺陷的概括性描述,通常采⽤“在什么情况下发⽣了什么问题”的模式。⾸先,对“什么问题”的描述不仅要做到清晰简洁,最关键是要⾜够具体,切忌不能采⽤过于笼统的描述。(如:“⽤户不能正常登陆”“搜索功能有问题”和“⽤户信息页⾯的地址栏位置不正确”等,这样的描述会给⼈“说了等于没说”的感觉,再如,当你发现了⼀个菜单栏上某个条⽬缺失的问题,在递交缺陷报告前,通常会去缺陷管理系统搜索⼀下是否已经有⼈递交过类似的缺陷。当你以“菜单栏”为关键字搜索时,你可能会得到⼀堆“菜单栏有问题”的缺陷,如果缺陷标题的描述过于笼统,你就不得不点击进⼊每个已知缺陷点去看细节描述,这就会⼤⼤降低你的⼯作效率。所以,如果缺陷标题本⾝就能概括性地描述具体问题,你就可以通过阅读标题判断类似的缺陷是否被提交过,⼤⼤提⾼测试⼯程师提交缺陷报告的效率。所以,描述“什么问题”的同时还必须清楚地表述发⽣问题时的上下⽂,也就是问题出现的场景。)其次,标题应该尽可能描述问题本质,⽽避免只停留在问题的表⾯。(如,“商品⾦额输⼊框,可以输⼊英⽂字母和其他字符”这个描述就只描述了问题的表⾯现象,⽽采⽤诸如“商品⾦额输⼊框,没有对输⼊内容做校验”的⽅式,就可以透过标题看到缺陷的本质,这样可以帮助开发⼈员快速掌握问题的本质。).最后,缺陷标题不宜过长,对缺陷更详细的描述应该放在“缺陷概述”⾥。2)缺陷概述缺陷概述通常会提供更多概括性的缺陷本质与现象的描述,是缺陷标题的细化。这部分内容通常是开发⼯程师打开缺陷报告后最先关注的内容,所以⽤清晰简短的语句将问题的本质描述清楚是关键。缺陷概述还会包括缺陷的其他延展部分,⽐如你可以在这部分列出同⼀类型的缺陷可能出现的所有场景;再⽐如,你还可以描述同样的问题是否会在之前的版本中重现等。在这⾥,你应该尽量避免以缺陷重现步骤的形式来描述,⽽应该使⽤概括性的语句。3)缺陷影响缺陷影响描述的是,缺陷引起的问题对⽤户或者对业务的影响范围以及严重程度。缺陷影响决定了缺陷的优先级和严重程度,开发经理会以此为依据来决定修复该缺陷的优先级;⽽产品经理会以此为依据来衡量缺陷的严重程度,并决定是否要等该缺陷被修复后才能发布产品。4)环境配置5)前置条件前置条件是指测试步骤开始前系统应该处在的状态,其⽬的是减少缺陷重现步骤的描述。合理地使⽤前置条件可以在描述缺陷重现步骤时排除不必要的⼲扰,使其更有针对性。⽐如,某个业务操作需要先完成⽤户登录,你在缺陷重现步骤⾥就没有必要描述登录操作的步骤细节,可以直接使⽤“前置条件:⽤户已完成登录”的描述⽅式。6)缺陷重现步骤缺陷重现步骤是整个缺陷报告中最核⼼的内容,其⽬的在于⽤简洁的语⾔向开发⼯程师展⽰缺陷重现的具体操作步骤。通常测试⼯程师在写缺陷重现步骤前,需要反复执⾏这些步骤3次以上:⼀是,确保缺陷的可重现性;⼆是,找到最短的重现路径,过滤掉那些⾮必要的步骤,避免产⽣不必要的⼲扰。对于缺陷重现步骤的描述应该尽量避免以下3个常见问题:1. 笼统的描述,缺乏可操作的具体步骤。2. 出现于缺陷重现不相关的步骤。3. 缺乏对测试数据的相关描述。7)期望结果和实际结果期望结果和实际结果通常和缺陷重现步骤绑定在⼀起,在描述重现步骤的过程中,需要明确说明期待结果和实际结果。期待结果来⾃于对需求的理解,⽽实际结果来⾃于测试执⾏的结果。通常来讲,当你描述期望结果时,需要说明应该发⽣什么,⽽不是什么不应该发⽣;⽽描述实际结果时,你应该说明发⽣了什么,⽽不是什么没有发⽣。8)优先级(Priority)和严重程度(Severity)缺陷优先级是指缺陷必须被修复的紧急程度,⽽缺陷的严重程度是指因缺陷引起的故障对软件产品的影响程度。可见,严重程度是缺陷本⾝的属性,通常确定后就不再变化,⽽优先级是缺陷的⼯程属性,会随着项⽬进度、解决缺陷的成本等因素⽽变动。那么,缺陷的优先级和严重程度⼜有什么关系呢?1. 缺陷越严重,优先级就越⾼;2. 缺陷影响的范围越⼤,优先级也会越⾼;3. 有些缺陷虽然从⽤户影响⾓度来说不算严重,但是会妨碍测试或者是⾃动化测试的执⾏,这类缺陷属于典型的严重程度低,但是优先级⾼;4. 有些缺陷虽然严重程度⽐较⾼,但是考虑到修复成本以及技术难度,也会出现优先级较低的情况。9)根原因分析(Root Cause Analysis)根原因分析就是我们平时常说的RCA,如果你能在发现缺陷的同时,定位出问题的根本原因,清楚地描述缺陷产⽣的原因并反馈给开发⼯程师,那么开发⼯程师修复缺陷的效率就会⼤幅提升,⽽且你的技术影响⼒也会被开发认可。10)附件(Attachment)附件通常是为缺陷的存在提供必要的证据⽀持,常见的附件有界⾯截图、测试⽤例⽇志、服务器端⽇志、GUI测试的执⾏视屏等。对于那些很难⽤⽂字描述清楚的GUI界⾯布局的缺陷,你可以采⽤截图并⾼亮显⽰应该关注的区域的⽅式去提交缺陷报告。08 | 以终为始,如何才能做好测试计划?对于很多⾮产品型的互联⽹公司,由于采⽤了敏捷开发模式,的确很少去制定传统意义上的测试计划了,但这并不是说它们就不再制定测试计划了。其实,测试计划依旧存在,只是从原来的⼀次性集中制定测试计划,变成了以迭代的⽅式持续制定测试计划。⽆论对于早期最具典型的瀑布开发模型,还是现在的敏捷开发模型,测试计划的重要性始终没有发⽣变化。那么,没有测试计划会怎么样?1. 很难确切地知道具体的测试范围,已经应该采取的具体测试策略;2. 很难预估具体的⼯作量和所需要的测试⼯程师数量,同时还会造成各个测试⼯程师的分⼯不明确,引发某些测试⼯作被重复执⾏⽽有些测试则被遗漏的问题;3. 测试的整体进度完全不可控,甚⾄很难确切知道⽬前测试的完成情况,对于测试完成时间就更难预估准确的时间节点了;4. 整个项⽬对潜在风险的抵抗能⼒很弱,很难应对需求的变更以及其他突发事件。所以,⼀份好的测试计划要包括:测试范围、测试策略、测试资源、测试进度、和测试风险预估,这五⼤⽅⾯,并且每⼀部分都要给出应对可能出现的问题的解决办法。测试范围测试范围描述的是被测对象以及主要的测试内容。⽐如,对于⽤户登录模块,功能测试既需要测试浏览器端⼜需要测试移动端,同时还考虑登录的安全和并发性能相关的⾮功能性需求的测试等。测试范围的确定通常是在测试需求分析完成后进⾏,所以确定测试范围的过程在⼀定程度上也是对测试需求分析的进⼀步检验,这将有助于在早期阶段就发现潜在的测试遗漏。同时,由于不可能进⾏穷尽测试,⽽且测试的时间和资源都是有限的,所以必须有所取舍,进⾏有针对性的测试。因此,测试范围中需要明确“测什么”和“不测什么”。测试策略测试策略简单来讲就是需要明确“先测什么后测什么”和“如何来测”这两个问题。重要的项先测,⽽不重要的项要后测。测试策略会要求我们明确测试的重点,以及各项测试的先后顺序。⽐如,对⽤户登录模块来讲,“⽤户⽆法正常登录”和“⽤户⽆法重置密码”这两个潜在问题,对业务的影响孰轻孰重⼀⽬了然,所以,你应该按照优先级来先测“⽤户正常登录”,再测“⽤户重置密码”。测试策略还需要说明,采⽤什么样的测试类型和测试⽅法。这⾥需要注意的是,不仅要给出为什么要选⽤这个测试类型,还要详细说明具体的实施⽅法。第⼀,功能测试对于功能测试,我们应该根据测试需求分析的思维导图来设计测试⽤例。主线业务的功能测试由于经常需要执⾏回归测试,所以需要考虑实施⾃动化测试,通常应该先实现主⼲业务流程的测试⾃动化。实际操作时,你通常需要先列出主要的功能测试点,并决定哪些测试点适合采⽤⾃动化测试,并且决定具体使⽤说明样的框架和技术。对于需要⼿⼯测试的测试点,你要决定采⽤什么类型的测试⽤例设计⽅法,以及如何准备相关的测试数据。另外,我们还要评估被测软件的可测试性,如果有可测试性的问题,需要提前考虑切实可⾏的变通⽅案,甚⾄要求开发⼈员提供可测试性的接⼝。第⼆,兼容性测试对于兼容性测试来说,Web测试需要确定覆盖的浏览器类型和版本,移动设备测试需要确定覆盖的设备类型和具体iOS/Android的版本等。如果是既有产品,你可以通过⼤数据技术分析产品的历史数据得出Top30%的移动设备以及iOS/Android的版本列表,那么兼容性测试只需覆盖这部分即可。如果是⼀个全新的产品,你可以通过TalkingData这样的⽹站来查看⽬前主流的移动设备,分辨率⼤⼩、iOS/Android版本等信息来确定测试范围。兼容性测试的实施,往往是在过年测试的后期,也就是说需要等功能基本都稳定了,才会开始兼容性测试。当然也有特例,⽐如,对于前端引⼊了新的前端框架或者组件库,往往就会先在前期做兼容性评估,以确保不会引⼊后期⽆法解决的兼容性问题。兼容性测试⽤例的选取,往往来⾃于已经实现的⾃动化测试⽤例。因为兼容性测试往往要覆盖最常⽤的业务场景,⽽这些最常⽤的业务场景通常也是⾸批实现⾃动化测试的⽬标。所以,我们的GUI⾃动化框架,就需要能够⽀持同⼀套测试脚本在不做修改的前提下,运⾏于不同的浏览器。第三,性能测试对于性能测试,需要在明确了性能需求(并发⽤户数、响应时间、事务吞吐量等)的前提下,结合被测系统的特点,设计性能测试场景并确定性能测试框架。⽐如,是直接在API级别发起压⼒测试,还是必须模拟终端⽤户⾏为进⾏基于协议的压⼒测试。再⽐如,是基于模块进⾏压⼒测试,还是发起全链路压测。如果性能是背景数据敏感的场景,还需要确定背景数据量级与分布,并决定产⽣背景数据的技术⽅案,⽐如是通过API并发调⽤来产⽣测试数据,还是直接在数据库上做批量insert和update操作,或者是两种⽅式的结合。最后,⽆论采⽤哪种⽅式,都需要明确待开发的单⽤户脚本的数量,以便后续能够顺利组装压测测试场景。性能测试的实施,是⼀个⽐较复杂的问题。⾸先,需要根据你想要解决的问题,确定性能测试的类型;然后,根据具体的性能测试类型开展测试。1. 性能测试的实施,往往先要根据业务场景来决定需要开发哪些单⽤户脚本,脚本的开发会涉及到很多性能测试脚本特有的概念,⽐如思考时间、集合点、动态关联等等。2. 脚本开发完成后,你还要以脚本为单位组织测试场景(Scenario),场景定义简单来说就是百分之多少的⽤户在做登录、百分之多少的⽤户在做查询、每个⽤户的操作步骤之间需要等待多少时间、并发⽤户的增速是5秒⼀个,还是5秒2个等等。3. 最后,才是具体的测试场景执⾏。和⾃动化功能测试不同,性能测试执⾏完成后性能测试报告的解读,是整个测试过程中最关键的点。测试资源测试资源通常包括测试⼈员和测试环境,这两类资源都是有限的。测试计划的⽬的就是,保证在有限资源下的产出最⼤化。所以,测试资源就是需要明确“谁来测”和“在哪⾥测”这两个问题。测试⼈员是最重要的,直接关系到整个测试项⽬的成败和效率。测试⼈员的资源通常有两个维度:⼀是,测试⼯程师的数量;⼆是,测试⼯程师的个⼈经验和能⼒。你会发现,测试⼯程师的经验和能⼒不⾜,很难通过测试⼈员的数量来弥补。相反地,测试⼯程师的经验和能⼒都⾮常强的情况下,测试⼈员的数量可以适当地减少。通常在测试团队中,测试⼯程师既有资深,也会有初级,那么你就必须针对团队的实际情况去安排测试计划。⽐如,难度较⼤的⼯作,或者⼀些新⼯具、新⽅法的应⽤,⼜或者⾃动化测试开发⼯作,通常由资深的测试⼯程师来承担;⽽那些相对机械性、难度较⼩的⼯作,则由初级⼯程师完成。可见,你想要规划好测试资源,除了要了解项⽬本⾝外,还必须对测试团队的⼈员特点有清晰的把控。另外,我强烈建议你把具体的任务清晰地落实到每个⼈的⾝上,这将有利于家⾥清晰的责任机制,避免后续可能发⽣的扯⽪。相对于测试⼈员,测试环境就⽐较好理解了。不同的项⽬,可能会使⽤共享的测试环境,也可能使⽤专⽤的测试环境,甚⾄还会直接使⽤⽣产环境。另外,对于⽬前⼀些已经实现容器化部署与发布的项⽬,测试环境就会变得更简单与轻量级。测试进度在明确了测试范围、测试策略和测试资源之后,我们就要考虑具体的测试进度了。测试进度主要描述各类测试的开始时间,所需⼯作量,预计完成时间,并以此为依据来建议最终产品的上线发布时间。⽐如,版本接收测试(Build Acceptance Test)的⼯作量,冒烟测试(Smoke Test)的⼯作量,⾃动化脚本开发的⼯作量,缺陷修复的验证⼯作量,需要⼏轮回归测试、每⼀轮回归测试的⼯作量等等。在传统瀑布模型中,测试进度完全依赖于开发完成并递交测试版本的时间。如果开发提交测试版本发⽣了延误,那么在不裁剪测试需求的情况下,产品整体的上线时间就同样会延期。然⽽在敏捷模式下,测试活动贯穿于整个开发过程,很多测试⼯作会和开发⼯作同步进⾏,⽐如采⽤⾏为驱动开发(Behavior-Driven Development)模式,这样测试进度就不会完全依赖于开发递交可测试版本的时间。测试风险预估俗话说,计划赶不上变化,对于测试也是⼀样的道理,很少有整个测试过程是完全按照原本测试计划执⾏的。通常需求变更、开发延期、发现重⼤缺陷和⼈员变动是引⼊项⽬测试风险的主要原因。在敏捷开发与测试中,对于需求的频繁变更(如新加需求、删减需求、修改优化需求等),⼀定要重新进⾏测试需求分析,确定变更后的测试范围和资源评估,并与项⽬经理和产品经理及时沟通因此引起的测试进度影响。测试经理/测试负责⼈切忌不能有⾃⼰咬⽛扛过去的想法,否则⽆论是对测试团队还是对产品本⾝都不会有任何好处。另外,随着测试的开展,你可能会发现前期对于测试⼯作量的预估不够准确,也可能发现需要增加更多的测试类型,也可能发现因为要修改测试架构的严重缺陷⽽导致很多的测试需要全回归,还有可能出现开发递交测试版本延期,或者⼈员变动等各种情况。所以,在制定测试计划时,你就要预估整个测试过程中可能存在的潜在风险,以及当这些风险发⽣时的应对策略。09 | 软件测试⼯程师的核⼼竞争⼒是什么?

2023年6月21日发(作者:)

软件测试52讲-笔记(持续更新中...)软件测试52讲01 | 你真的懂测试吗?从“⽤户登录”测试谈起在测试⼯作当中,设计测试⽤例⽅法包括很多种:等价类划分、边界值分析、错误推测、因果图、判定表驱动、正交试验设计、功能图、场景等。但是作为测试⼯程师,我们的⽬标是要保证系统在各种应⽤场景下的功能是符合设计要求的,所以我们就要考虑⽤例内容就需要更多、更全⾯。当我们拿到“⽤户登录”的功能需求时,可以结合等价类划分和边界值分析⽅法来设计测试⽤例:⼊门级别的测试⽤例:1. 输⼊已注册的⽤户名和正确的密码,验证是否登录成功;2. 输⼊已注册的⽤户名和不正确的密码,验证是否登录失败,并且提⽰信息正确;3. 输⼊未注册的⽤户名和任意密码,验证是否登录失败,并且提⽰信息正确;4. ⽤户名和密码两者都为空,验证是否登录失败,并且提⽰信息正确;5. ⽤户名和密码两者之⼀为空,验证是否登录失败,并且提⽰信息正确;6. 如果登录功能启⽤了验证码功能,在⽤户名和密码正确的前提下,输⼊正确的验证码,验证是否登录成功;7. 如果登录功能启⽤了验证码功能,在⽤户名和密码正确的前提下,输⼊错误的验证码,验证是否登录失败,并且提⽰信息正确。有了些许经验的会增加测试点的⽤例:1. ⽤户名和密码是否⼤⼩写敏感;2. 页⾯上的密码框是否加密显⽰;3. 后台系统创建的⽤户第⼀次登录成功时,是否提⽰修改密码;4. 忘记⽤户名和忘记密码的功能是否可⽤;5. 前端页⾯是否根据设计要求限制⽤户名和密码长度;6. 如果登录功能需要验证码,点击验证码图⽚是否可以更换验证码,更换后的验证码是否可⽤;7. 刷新页⾯是否会刷新验证码;8. 如果验证码具有时效性,需要分别验证时效内和时效外验证码的有效性;9. ⽤户登录成功但是会话超时后,继续操作是否会重定向到⽤户登录界⾯;10. 不同级别的⽤户,⽐如管理员⽤户和普通⽤户,登录系统后的权限是否正确;11. 页⾯默认焦点是否定位在⽤户名的输⼊框中;12. 快捷键Tab和Enter等,是否可以正常使⽤。其实上述都是根据明显的功能上的需求来设计⽤例的,但在软件测试的维度来看,除了这些显性的功能需求,⾮功能性需求也很重要,它涉及到安全性、性能及兼容性三⼤⽅⾯,这些容易被我们遗漏忽视的,往往也是决定软件质量的关键因素。安全性测试⽤例包括:1. ⽤户密码后台存储是否加密;2. ⽤户密码在⽹络传输过程中是否加密;3. 密码是否具有有效期,密码有效期到期后,是否提⽰需要修改密码;4. 不登录的情况下,在浏览器中直接输⼊登录后的URL地址,验证是否会重新定向到⽤户登录界⾯;5. 密码输⼊框是否不⽀持复制和粘贴;(补充:右键⽅式和热键⽅式)6. 密码输⼊框内输⼊的密码是否都可以在页⾯源码模式下被查看;7. ⽤户名和密码的输⼊框中分别输⼊典型的“SQL注⼊攻击”字符串,验证系统的返回页⾯;8. ⽤户名和密码的输⼊框中分别输⼊典型的“XSS跨站脚本攻击”字符串,验证系统⾏为是否被篡改;9. 连续多次登录失败情况下,系统上是否会阻⽌后续的尝试以应对暴⼒破解;10. 同⼀⽤户在同⼀终端的多种浏览器上登录,验证登录功能的互斥性是否符合设计预期;11. 同⼀⽤户先后在多台终端的浏览器上登录,验证登录是否具有互斥性。性能压⼒测试⽤例包括:1. 单⽤户登录的响应时间是否⼩于3秒;2. 单⽤户登录时,后台请求数量是否过多;3. ⾼并发场景下⽤户登录的响应时间是否⼩于5秒;4. ⾼并发场景下服务端的监控指标是否符合预期;5. ⾼集合点并发场景下,是否存在资源死锁和不合理的资源等待;6. 长时间⼤量⽤户连续登录和登出,服务器端是否存在内存泄漏。兼容性测试⽤例包括:1. 不同浏览器下,验证登录页⾯的显⽰以及功能正确性;2. 相同浏览器的不同版本下,验证登录页⾯的显⽰以及功能正确性;3. 不同移动设备终端的不同浏览器下,验证登录页⾯的显⽰以及功能正确性;4. 不同分辨率的界⾯下,验证登录页⾯的显⽰以及功能正确性。由于在整个项⽬周期迭代中,测试因受限于时间成本与经济成本,是⽆法去穷尽测试所有满⾜前提条件的数据组合的,⽽是采⽤基于风险较⼤的驱动模式,侧重选择测试范围和设计测试⽤例,以寻求缺陷风险和研发成本之间的平衡。其他补充:1. ⽹络延迟或者弱⽹或者切换⽹络或者断⽹时是否正常登录;2. 是否⽀持第三⽅登录;3. 是否可记住密码,记住的密码保存是否加密,记住密码是否有有效期,过期之后是否会清空密码;4. 密码强弱性校验,数据库设计和数据操作时是否合理;5. ⽤户登录过程中log是否对个⼈信息及密码明⽂打印;6. 登录⽤户限制:⽐如同时⽀持10个⽤户登录,同时9个或者11个⽤户登录是否正常或者提⽰信息正确;7. 未激活的⽤户登录;8. 被停⽤的⽤户登录;9. 涉及资产风险的,对登录设备和地区检测;10. 为空和输⼊空字符串时的校验;11. 使⽤中⽂键盘输⼊字母时和使⽤英⽂键盘输⼊字母时传给后端的字符串长度是否⼀致;(补充:全⾓与半⾓符号的区分,软键盘的输⼊)12. 登录成功后的session时效设置;13. 密码⼀栏是否需要设置明暗码切换按钮;14. 输⼊栏是否设置快速删除按钮;15. 是否⽤到缓存;16. ⽤户名和密码是否对空格敏感;17. 更改密码后是否还能⽤之前的密码登录;18. ⼀个⽤户是否具备多种登录⽅式(⽤户名,⼿机号,邮箱等);19. 第三⽅登录修改密码的影响(解绑后是否能正常登录和登出);20. 是否可以使⽤登录的API发送登录请求,并绕开验证码校验;21. 是否可以⽤抓包⼯具抓到的请求包直接登录;22. 截取到的token等信息,是否可以在其他终端上直接使⽤,绕开登录。Token过期时间校验;23. 除了前端校验格式长度,后端是否也校验;24. 登录后输⼊登录URL,是否还能再次登录?如果能,原登录⽤户是否变得⽆效25. 其他终端修改密码后,原记住密码终端是否提⽰密码已更改;26. 检查HTTP头的refer URL是否为登录起始页的URL,如果不同是否给出正确的提⽰并做⽇志记录和报警;27. 对某些系统,还要验证客户端证书是否与⽤户名匹配,不匹配时、或者客户端证书过期以及即将过期三种情况是否正确处理和提⽰;28. 已登录⽤户,杀死APP进城后,再次打开APP是否依然为登录状态;29. 对于银⾏系统,密码输⼊框是否可以正常调⽤密码控件;(补充:在不同安装证书的环境下)02 | 如何设计⼀个“好的”测试⽤例?其实在实际项⽬⼯作当中,软件⽣命周期内都会有不同的类型测试。⽐如,传统软件的开发阶段通常会有单元测试,软件模块集成阶段会有代码级集成测试,打包部署后悔有⾯向终端⽤户的GUI测试;再⽐如,电商⽹站的测试会分为服务端基于API的测试、中间件测试、前端GUI测试等。那么⼀个“好的”测试⽤例必须具备哪些特征?1. 整体完备性:“好的”测试⽤例⼀定是⼀个完备的整体,是有效测试⽤例组成的集合,能够完全覆盖测试需求;2. 等价类划分的准确性:是对于每个等价类都能保证只要其中⼀个输⼊测试通过,其他输⼊也⼀定测试通过;3. 等价类集合的完备性:需要保证所有可能的边界值和边界条件都已经正确识别;但对于⼤多数软件测试⽽⾔,综合使⽤等价类划分、边界值分析和错误推测这三⼤类⽅法就⾜够了。第⼀、等价类划分⽅法等价类中任意⼀个输⼊数据对于揭露程序中潜在错误都具有同等效果。后续我们只要从每个等价类中任意选取⼀个值进⾏测试,就可以⽤少量具有代表性的测试输⼊取得较好的测试覆盖结果。有效等价类:年按⼈类最⾼年龄120岁推算,有效年份应为2019~1899年中间;⽉应为1~12⽉;⽇应为1~31⽇;⽆效等价类:年⼩于1899年或⼤于2019年;⽉等于00或⼤于12;⽇等于00或⼤于31⽇;第⼆、边界值分析⽅法是对等价类划分的补充,从⼯程实践经验中可以发现,⼤量的错误发⽣在输⼊输出的边界值上,所需要对边界值进⾏重点测试,通常选取正好等于、刚刚⼤于或刚刚⼩于边界的值作为测试数据。选取闰年⾮闰年20040229以及20050228;⼤⼩⽉⽇期20000630以及2000731;第三、错误推测⽅法是基于对被测软件系统设计的理解、过往经验以及个⼈直觉,推测出软件可能存在的缺陷,从⽽有针对性的设计测试⽤例的⽅法。这个⽅法强调的是对被测试软件的需求理解以及设计实现的细节把握,当然还有个⼈的能⼒。⾝份证号不可重复;数据库链接失败;在具体设计⽤例时,⾸先需要搞清楚每⼀个业务需求所对应的的多个软件功能需求点,然后分析每个软件功能需求点对应的多个测试需求点,最后再针对每个测试需求点来设计测试⽤例。具体到测试⽤例本⾝的设计,还有两个关键点需要注意:1. 从软件功能需求出发,全⾯地、⽆遗漏地识别出测试需求是⾄关重要的,这将直接关系到⽤例的测试覆盖率。(⽐如,如果你没有出⽤户登录功能的安全性测试需求,那么后续设计的测试⽤例就完全不会涉及安全性,最终造成重要测试漏洞。)2. 对于识别出的每个测试需求点,需要总和运⽤等价类划分、边界值分析和错误推测⽅法来全⾯地设计测试⽤例。需要注意的是,要综合运⽤这三种法法,并针对每个测试需求点的具体情况,进⾏灵活选择。以“⽤户登录”的功能性测试需求为例,我们⾸先应该对“⽤户名”和“密码”这两个输⼊项分别进⾏等价类划分,列出对应的有效等价类和⽆效等价类,对于⽆效等价类的识别可以采⽤错误推测法(如⽤户名包含特殊字符等),然后基于两者可能的组合,是基础第⼀批测试⽤例。等价类划分完后,我们还需要补充“⽤户名”和“密码”这两个输⼊项的边界值的测试⽤例,⽐如⽤户名为空(NULL)、⽤户名长度刚好⼤于允许长度等。设计测试⽤例的其他经验:1. 需要深⼊理解被测试软件的架构,对内部的架构有清楚的认识,⽐如数据库连接⽅式、数据库的读写分离、消息中间件的配置、缓存系统的层级分布、第三⽅系统的集成等。2. 必须深⼊理解被测软件的设计与实现细节,深⼊理解软件内部的处理逻辑。3. 单单根据测算需求点设计的⽤例,只能覆盖“表⾯”的⼀层,往往覆盖不到内部的处理流程、分⽀处理,⽽没有覆盖到的部门就很可能出现缺陷遗漏。在具体实践中,你可以通过代码覆盖率指标找出可能的测试遗漏点。4. 切忌不要以开发代码的实现为依据设计测试⽤例。因为开发代码实现的错误会导致测试⽤例也出错,所以你应该根据原始需求设计测试⽤例。5. 在实际测试⼯作当中我们还可以建⽴常见缺陷知识库,那么在⽤例设计的过程中,会使⽤缺陷知识库作为检查点列表,去帮助优化补充测试⽤例的设计。03 | 什么是单元测试?如何做好单元测试?单元测试是指,对软件中的最⼩可测试单元在与程序其他部分相隔离的情况下进⾏检查和验证的⼯作,这⾥的最⼩可测试单元通常是指函数或者类。如何做好单元测试?⾸先必须要弄清楚单元测试的对象是代码,以及代码的基本特征和产⽣错误的原因,然后我们必须要掌握单元测试的基本⽅法和主要技术⼿段,⽐如,什么事驱动代码、桩代码和Mock代码等。第⼀,代码的基本特征与产⽣错误的原因⽆论是开发语⾔还是脚本语⾔,都会有条件分⽀、循环处理和函数调⽤等最基本的逻辑控制,如果抛开代码需要实现的具体业务逻辑,仅看代码结构的话,所有的代码都是在对数据进⾏分类处理,每⼀次条件判定都是⼀次分类处理,嵌套的条件判定或者循环执⾏,也是在做分类处理。如果有任何⼀个分类遗漏,都会产⽣缺陷;如果有任何⼀个分类错误,也会产⽣缺陷;如果分类正确也没有遗漏,但是分类时的处理逻辑错误,也会产⽣缺陷。在具体⼯程实践中,开发⼯程师为了设计并实现逻辑功能正确的代码,通常会有如下的考虑过程:1)如果要实现正常的功能逻辑,会有哪⼏种正常的输⼊;2)是否有需要特殊处理的多种边界输⼊;3)各种潜在⾮法输⼊的可能性以及如何处理;⽽现在很多公司都省略了单元测试这⼀过程。主要原因在于敏捷开发阶段,周期短、迭代快,开发诵读也要快的情况下,省略单元测试可以节约很⼤的时间成本以及⼈⼒成本。但放在长远的时间线上来看,因为不停的在迭代会让原先成⽴的接⼝出现⼀些隐患的bug,⽽导致不知道是那⾥出了问题,再去查找定位难免就会多浪费时间,这时候单元测试的作⽤就体现了,每次迭代的功能代码与测试代码对应,跑⼀遍测试代码就知道哪⾥出了问题,可及时修改。04 | 为什么要做⾃动化测试?什么样的项⽬适合做⾃动化测试?⾃动化测试,是把⼈对软件的测试⾏为转化为由机器执⾏测试⾏为的⼀种实践,对于最常见的GUI⾃动化测试来讲,就是由⾃动化测试⼯具模拟之前需要⼈⼯在软件界⾯上各种操作,并且⾃动验证其结果是否符合预期。⾃动化测试本质是先写⼀段代码,然后去测试另外⼀段代码,所以实现⾃动化测试⽤例本⾝是属于开发⼯作,需要投⼊⼤量时间和精⼒,并且已经开发完成的⽤例还必须随着被测对象的改变⽽不断更新,还需要为此付出维护测试⽤例的成本,⽽当维护成本⾼于其节省的测试成本时,⾃动化也就失去了价值与意义,我们也就需要在是否使⽤⾃动化测试上做权衡取舍了。为什么需要⾃动化测试?优势:1. 可代替⼤量⼿⼯机械重复性操作;2. ⼤幅度提升回归测试效率,适合敏捷开发过程;3. 更好的利⽤⽆⼈值守时间,去频繁的执⾏测试;4. 可以⾼效实现某些⼿⼯测试⽆法完成或者代价巨⼤的测试类型(如关键业务要7*24⼩时持续运⾏的系统稳定性和测试⾼并发场景的压⼒测试等);5. 可以保证每次测试执⾏的操作以及验证的⼀致性和可重复性,避免⼈为的遗漏和疏忽;劣势:1. ⽆法取代⼿⼯测试,它只能替代⼿⼯测试中执⾏频率⾼、机械化的重复步骤;2. ⽐⼿⼯测试要脆弱,⽆法应对被测系统的变化,它并不‘智能’,只按部就班的执⾏事先定义好的测试步骤并验证测试结果。对于执⾏中出现的明显错误和意外事件,⾃动化测试没有任何处理能⼒;3. ⾃动化测试⽤例的开发⼯作量远⼤于单次的⼿⼯测试,所以只有当开发完成的测试⽤例的有效执⾏次数⼤于5次时,才能收回⾃动化测试的成本;4. ⼿⼯测试发现bug数量通常⽐⾃动化测试的要多,并且⾃动化测试仅仅能发现回归测试范围的bug;5. 实⾏⾃动化测试的初期,⽤例开发效率通常都很低,⼤量初期开发的⽤例通常会在整个⾃动化测试体系成熟,和测试⼯程师全⾯掌握测试⼯具后,需要重构。什么样的项⽬适合⾃动化测试?1. 需求稳定,不会频繁变更;2. 研发和维护周期长,需要频繁执⾏回归测试;3. 需要在多种平台上重复运⾏相同的场景4. 某些测试项⽬通过⼿⼯测试⽆法实现,或者⼿⼯成本太⾼;5. 被测软件的开发较规范,能够保证系统的可测试性总之,对于⼀些中长期项⽬,对⽐较稳定的软件功能进⾏⾃动化测试,对变动较⼤或者需求暂时不明确的功能进⾏⼿⼯测试,最终⽬标是⽤20%的精⼒去覆盖80%的回归测试。05 | 你知道软件开发各阶段都有哪些⾃动化测试技术吗?其实在软件研发⽣命周期的各个阶段都有⾃动化测试技术的存在,对提升测试效率都有很⼤的作⽤。单元测试的⾃动化技术⾸先,单元测试本⾝就是⾃动化的,因为它根据软件详细设计采⽤等价类划分和边界值分析⽅法设计测试⽤例,在测试代码实现后再以⾃动化的⽅式统⼀执⾏。但这仅仅是⼀部分,并没有完整地描述单元测试“⾃动化”的内涵。从⼴义上讲,单元测试阶段的“⾃动化”内涵不仅仅指测试⽤例执⾏的⾃动化,还应该包含以下五个⽅⾯:1. ⽤例框架代码⽣成的⾃动化;2. 部分测试输⼊数据的⾃动化⽣成;3. ⾃动桩代码的⽣成;4. 被测代码的⾃动化静态分析;5. 测试覆盖率的⾃动统计与分析;代码级集成测试的⾃动化技术代码级集成测试是指将已经开发完成的软件模块放在⼀起测试。从测试⽤例设计和测试代码结构来看,它和单元测试⾮常相似,都是对被测试函数以不同的输⼊参数组合进⾏调⽤并验证结构,只不过代码级集成测试的关注点,更多的是软件模块之间的接⼝调⽤和数据传递。⽽与单元测试最⼤的区别只是,代码级集成测试中被测函数内部调⽤的其他函数必须是真实的,不允许使⽤桩代码代替,⽽单元测试汇总允许使⽤桩代码来模拟内部调⽤的其他函数。代码级集成测试对测试框架的要求⾮常⾼,这个框架除了可以顺利装载⾃⼰的软件模块外,还必须能装载其他相互依赖的模块,做到被测软件模块可运⾏(Runnable)。由于代码级集成测试主要应⽤在早期⾮互联⽹的传统软件企业,那时候的软件以“单体”应⽤居多,⼀个软件内部包含⼤量的功能,每⼀个软件功能都是通过不同的内部模块来实现的,那么这些内部模块在做集成的时候,就需要做代码级集成测试。⽽现在的开发理念追求的是系统复杂性的解耦,会去尽量避免“⼤单体”应⽤,采⽤Web Service或者PRC调⽤的⽅式来协作完成各个软件功能。所以现在的软件企业,尤其是互联⽹企业,基本不会去做代码级集成测试,在这⾥也就不再进⼀步展开了。Web Service测试的⾃动化技术Web Service测试,主要是指SOAP API和REST API这两类API测试,最典型的是采⽤SoapUI或Postman等类似的⼯具。但这类测试⼯具基本都是界⾯操作⼿动发起Request并验证Response,所以难以和CI/CD集成,于是就出现了API⾃动化测试框架。对于基于代码的API测试⽤例,通常包含三⼤步骤:1. 准备API调⽤时需要的测试数据;2. 准备API的调⽤参数并发起API的调⽤;3. 验证API调⽤的返回结果;GUI测试的⾃动化技术GUI测试的⾃动化技术可能是我们最熟悉的,也是发展时间最长、应⽤最⼴的⾃动化测试技术。核⼼思想是,基于页⾯元素识别技术,对页⾯元素进⾏⾃动化操作,以模拟实际终端⽤户的⾏为并验证软件功能的正确性。⽬前,GUI⾃动化测试主要分为两⼤⽅向,传统Web浏览器和移动端原⽣应⽤(Native App)的GUI⾃动化。虽然⼆者采⽤的具体技术差别很⼤,但是⽤例设计的思路类似。对于传统Web浏览器的GUI⾃动化测试,业内主流的开源⽅案采⽤Selenium,商业⽅案采⽤Micro Focus的UFT(前⾝是HP的QTP);对于移动端原⽣应⽤,通常采⽤主流的Appium,它对iOS环境集成了XCUITest,对Android环境集成了UIAutomator和Espresso。06 | 你真的懂测试覆盖率吗?测试覆盖率通常被⽤来衡量测试的充分性和完整性,从⼴义的⾓度来讲,测试覆盖率主要分为两⼤类,⼀类是⾯向项⽬的需求覆盖率,另⼀类是更偏向技术的代码覆盖率。需求覆盖率需求覆盖率是指测试对需求的覆盖程度,通常的做法是将每⼀条分解后的软件需求和对应的测试建⽴⼀对多的映射关系,最终⽬标是保证测试可以覆盖每个需求,以保证软件产品的质量。通常采⽤ALM,Doors和TestLink等需求管理⼯具来建⽴需求和测试的对应关系,并以此计算测试覆盖率。但是需求覆盖率的统计⽅式不在适⽤于现在的敏捷开发模式,所以现在谈到测试覆盖率,⼤多指的是代码覆盖率。代码覆盖率代码覆盖率是指,⾄少被执⾏了⼀次的条⽬数占整个条⽬数的百分⽐。如果“条⽬数”是语句,对应的就是代码⾏覆盖率;如果“条⽬数”是函数,对应的就是函数覆盖率;如果“条⽬数”是路径,那么对应的就是路径覆盖率。依此类推,可以得到绝⼤多数常见的代码覆盖率类型的定义。⾏覆盖率⼜称为语句覆盖率,指已经被执⾏到的语句占总可执⾏语句(不包含类似C++的头⽂件声明、代码注释、空⾏等等)的百分⽐。这是最常⽤也是要求最低的覆盖率指标。实际项⽬中通常会结合判定覆盖率或者条件覆盖率⼀起使⽤。判定覆盖⼜称为分⽀覆盖,⽤以度量程序中每⼀个判定的分⽀是否都被测试到了,即代码中每个判定的取真分⽀和取假分⽀是否各被覆盖⾄少各⼀次。⽐如,对于if(a>0&&b>0),就要求覆盖“a>0&&b>0”为TRUE和FALSE各⼀次。条件覆盖是指,判定中的每个条件的可能取值⾄少满⾜⼀次,度量判定中的每个条件的结果TRUE和FALSE是否都被测试到了。⽐如,对于if(a>0&&b>0),就要求“a>0”取TRUE和FALSE各⼀次,同时要求“b>0”取TRUE和FALSE各⼀次。代码覆盖率的价值统计代码覆盖率的根本⽬的是找出潜在的遗漏测试⽤例,并有针对性的进⾏补充,同时还可以识别出代码中那些由于需求变更等原因造成的不可达的废弃代码。代码覆盖率的局限性⾼的代码覆盖率不⼀定能保证软件质量,因为代码覆盖率的计算是基于现有代码的,并不能发现那些“未考虑某些输⼊”以及“未处理某些情况”形成的缺陷。07 | 如何⾼效填写软件缺陷报告缺陷报告是测试⼯程师与开发⼯程师交流沟通的重要桥梁,也是测试⼯程师⽇常⼯作的重要输出。⼀般我们会觉得这并不是什么难事,毕竟软件企业通常都有缺陷管理系统,⽐如典型的ALM(以前的Quality Center)、JIRA、Bugzilla、BugFree和Mantis等。当使⽤这类系统递交缺陷时,会⾃动⽣成模板,你只要按照其中的必填字段提供缺陷的详细信息就可以了。缺陷报告的组成1)缺陷标题:缺陷标题通常是别⼈最先看到的部分,是对缺陷的概括性描述,通常采⽤“在什么情况下发⽣了什么问题”的模式。⾸先,对“什么问题”的描述不仅要做到清晰简洁,最关键是要⾜够具体,切忌不能采⽤过于笼统的描述。(如:“⽤户不能正常登陆”“搜索功能有问题”和“⽤户信息页⾯的地址栏位置不正确”等,这样的描述会给⼈“说了等于没说”的感觉,再如,当你发现了⼀个菜单栏上某个条⽬缺失的问题,在递交缺陷报告前,通常会去缺陷管理系统搜索⼀下是否已经有⼈递交过类似的缺陷。当你以“菜单栏”为关键字搜索时,你可能会得到⼀堆“菜单栏有问题”的缺陷,如果缺陷标题的描述过于笼统,你就不得不点击进⼊每个已知缺陷点去看细节描述,这就会⼤⼤降低你的⼯作效率。所以,如果缺陷标题本⾝就能概括性地描述具体问题,你就可以通过阅读标题判断类似的缺陷是否被提交过,⼤⼤提⾼测试⼯程师提交缺陷报告的效率。所以,描述“什么问题”的同时还必须清楚地表述发⽣问题时的上下⽂,也就是问题出现的场景。)其次,标题应该尽可能描述问题本质,⽽避免只停留在问题的表⾯。(如,“商品⾦额输⼊框,可以输⼊英⽂字母和其他字符”这个描述就只描述了问题的表⾯现象,⽽采⽤诸如“商品⾦额输⼊框,没有对输⼊内容做校验”的⽅式,就可以透过标题看到缺陷的本质,这样可以帮助开发⼈员快速掌握问题的本质。).最后,缺陷标题不宜过长,对缺陷更详细的描述应该放在“缺陷概述”⾥。2)缺陷概述缺陷概述通常会提供更多概括性的缺陷本质与现象的描述,是缺陷标题的细化。这部分内容通常是开发⼯程师打开缺陷报告后最先关注的内容,所以⽤清晰简短的语句将问题的本质描述清楚是关键。缺陷概述还会包括缺陷的其他延展部分,⽐如你可以在这部分列出同⼀类型的缺陷可能出现的所有场景;再⽐如,你还可以描述同样的问题是否会在之前的版本中重现等。在这⾥,你应该尽量避免以缺陷重现步骤的形式来描述,⽽应该使⽤概括性的语句。3)缺陷影响缺陷影响描述的是,缺陷引起的问题对⽤户或者对业务的影响范围以及严重程度。缺陷影响决定了缺陷的优先级和严重程度,开发经理会以此为依据来决定修复该缺陷的优先级;⽽产品经理会以此为依据来衡量缺陷的严重程度,并决定是否要等该缺陷被修复后才能发布产品。4)环境配置5)前置条件前置条件是指测试步骤开始前系统应该处在的状态,其⽬的是减少缺陷重现步骤的描述。合理地使⽤前置条件可以在描述缺陷重现步骤时排除不必要的⼲扰,使其更有针对性。⽐如,某个业务操作需要先完成⽤户登录,你在缺陷重现步骤⾥就没有必要描述登录操作的步骤细节,可以直接使⽤“前置条件:⽤户已完成登录”的描述⽅式。6)缺陷重现步骤缺陷重现步骤是整个缺陷报告中最核⼼的内容,其⽬的在于⽤简洁的语⾔向开发⼯程师展⽰缺陷重现的具体操作步骤。通常测试⼯程师在写缺陷重现步骤前,需要反复执⾏这些步骤3次以上:⼀是,确保缺陷的可重现性;⼆是,找到最短的重现路径,过滤掉那些⾮必要的步骤,避免产⽣不必要的⼲扰。对于缺陷重现步骤的描述应该尽量避免以下3个常见问题:1. 笼统的描述,缺乏可操作的具体步骤。2. 出现于缺陷重现不相关的步骤。3. 缺乏对测试数据的相关描述。7)期望结果和实际结果期望结果和实际结果通常和缺陷重现步骤绑定在⼀起,在描述重现步骤的过程中,需要明确说明期待结果和实际结果。期待结果来⾃于对需求的理解,⽽实际结果来⾃于测试执⾏的结果。通常来讲,当你描述期望结果时,需要说明应该发⽣什么,⽽不是什么不应该发⽣;⽽描述实际结果时,你应该说明发⽣了什么,⽽不是什么没有发⽣。8)优先级(Priority)和严重程度(Severity)缺陷优先级是指缺陷必须被修复的紧急程度,⽽缺陷的严重程度是指因缺陷引起的故障对软件产品的影响程度。可见,严重程度是缺陷本⾝的属性,通常确定后就不再变化,⽽优先级是缺陷的⼯程属性,会随着项⽬进度、解决缺陷的成本等因素⽽变动。那么,缺陷的优先级和严重程度⼜有什么关系呢?1. 缺陷越严重,优先级就越⾼;2. 缺陷影响的范围越⼤,优先级也会越⾼;3. 有些缺陷虽然从⽤户影响⾓度来说不算严重,但是会妨碍测试或者是⾃动化测试的执⾏,这类缺陷属于典型的严重程度低,但是优先级⾼;4. 有些缺陷虽然严重程度⽐较⾼,但是考虑到修复成本以及技术难度,也会出现优先级较低的情况。9)根原因分析(Root Cause Analysis)根原因分析就是我们平时常说的RCA,如果你能在发现缺陷的同时,定位出问题的根本原因,清楚地描述缺陷产⽣的原因并反馈给开发⼯程师,那么开发⼯程师修复缺陷的效率就会⼤幅提升,⽽且你的技术影响⼒也会被开发认可。10)附件(Attachment)附件通常是为缺陷的存在提供必要的证据⽀持,常见的附件有界⾯截图、测试⽤例⽇志、服务器端⽇志、GUI测试的执⾏视屏等。对于那些很难⽤⽂字描述清楚的GUI界⾯布局的缺陷,你可以采⽤截图并⾼亮显⽰应该关注的区域的⽅式去提交缺陷报告。08 | 以终为始,如何才能做好测试计划?对于很多⾮产品型的互联⽹公司,由于采⽤了敏捷开发模式,的确很少去制定传统意义上的测试计划了,但这并不是说它们就不再制定测试计划了。其实,测试计划依旧存在,只是从原来的⼀次性集中制定测试计划,变成了以迭代的⽅式持续制定测试计划。⽆论对于早期最具典型的瀑布开发模型,还是现在的敏捷开发模型,测试计划的重要性始终没有发⽣变化。那么,没有测试计划会怎么样?1. 很难确切地知道具体的测试范围,已经应该采取的具体测试策略;2. 很难预估具体的⼯作量和所需要的测试⼯程师数量,同时还会造成各个测试⼯程师的分⼯不明确,引发某些测试⼯作被重复执⾏⽽有些测试则被遗漏的问题;3. 测试的整体进度完全不可控,甚⾄很难确切知道⽬前测试的完成情况,对于测试完成时间就更难预估准确的时间节点了;4. 整个项⽬对潜在风险的抵抗能⼒很弱,很难应对需求的变更以及其他突发事件。所以,⼀份好的测试计划要包括:测试范围、测试策略、测试资源、测试进度、和测试风险预估,这五⼤⽅⾯,并且每⼀部分都要给出应对可能出现的问题的解决办法。测试范围测试范围描述的是被测对象以及主要的测试内容。⽐如,对于⽤户登录模块,功能测试既需要测试浏览器端⼜需要测试移动端,同时还考虑登录的安全和并发性能相关的⾮功能性需求的测试等。测试范围的确定通常是在测试需求分析完成后进⾏,所以确定测试范围的过程在⼀定程度上也是对测试需求分析的进⼀步检验,这将有助于在早期阶段就发现潜在的测试遗漏。同时,由于不可能进⾏穷尽测试,⽽且测试的时间和资源都是有限的,所以必须有所取舍,进⾏有针对性的测试。因此,测试范围中需要明确“测什么”和“不测什么”。测试策略测试策略简单来讲就是需要明确“先测什么后测什么”和“如何来测”这两个问题。重要的项先测,⽽不重要的项要后测。测试策略会要求我们明确测试的重点,以及各项测试的先后顺序。⽐如,对⽤户登录模块来讲,“⽤户⽆法正常登录”和“⽤户⽆法重置密码”这两个潜在问题,对业务的影响孰轻孰重⼀⽬了然,所以,你应该按照优先级来先测“⽤户正常登录”,再测“⽤户重置密码”。测试策略还需要说明,采⽤什么样的测试类型和测试⽅法。这⾥需要注意的是,不仅要给出为什么要选⽤这个测试类型,还要详细说明具体的实施⽅法。第⼀,功能测试对于功能测试,我们应该根据测试需求分析的思维导图来设计测试⽤例。主线业务的功能测试由于经常需要执⾏回归测试,所以需要考虑实施⾃动化测试,通常应该先实现主⼲业务流程的测试⾃动化。实际操作时,你通常需要先列出主要的功能测试点,并决定哪些测试点适合采⽤⾃动化测试,并且决定具体使⽤说明样的框架和技术。对于需要⼿⼯测试的测试点,你要决定采⽤什么类型的测试⽤例设计⽅法,以及如何准备相关的测试数据。另外,我们还要评估被测软件的可测试性,如果有可测试性的问题,需要提前考虑切实可⾏的变通⽅案,甚⾄要求开发⼈员提供可测试性的接⼝。第⼆,兼容性测试对于兼容性测试来说,Web测试需要确定覆盖的浏览器类型和版本,移动设备测试需要确定覆盖的设备类型和具体iOS/Android的版本等。如果是既有产品,你可以通过⼤数据技术分析产品的历史数据得出Top30%的移动设备以及iOS/Android的版本列表,那么兼容性测试只需覆盖这部分即可。如果是⼀个全新的产品,你可以通过TalkingData这样的⽹站来查看⽬前主流的移动设备,分辨率⼤⼩、iOS/Android版本等信息来确定测试范围。兼容性测试的实施,往往是在过年测试的后期,也就是说需要等功能基本都稳定了,才会开始兼容性测试。当然也有特例,⽐如,对于前端引⼊了新的前端框架或者组件库,往往就会先在前期做兼容性评估,以确保不会引⼊后期⽆法解决的兼容性问题。兼容性测试⽤例的选取,往往来⾃于已经实现的⾃动化测试⽤例。因为兼容性测试往往要覆盖最常⽤的业务场景,⽽这些最常⽤的业务场景通常也是⾸批实现⾃动化测试的⽬标。所以,我们的GUI⾃动化框架,就需要能够⽀持同⼀套测试脚本在不做修改的前提下,运⾏于不同的浏览器。第三,性能测试对于性能测试,需要在明确了性能需求(并发⽤户数、响应时间、事务吞吐量等)的前提下,结合被测系统的特点,设计性能测试场景并确定性能测试框架。⽐如,是直接在API级别发起压⼒测试,还是必须模拟终端⽤户⾏为进⾏基于协议的压⼒测试。再⽐如,是基于模块进⾏压⼒测试,还是发起全链路压测。如果性能是背景数据敏感的场景,还需要确定背景数据量级与分布,并决定产⽣背景数据的技术⽅案,⽐如是通过API并发调⽤来产⽣测试数据,还是直接在数据库上做批量insert和update操作,或者是两种⽅式的结合。最后,⽆论采⽤哪种⽅式,都需要明确待开发的单⽤户脚本的数量,以便后续能够顺利组装压测测试场景。性能测试的实施,是⼀个⽐较复杂的问题。⾸先,需要根据你想要解决的问题,确定性能测试的类型;然后,根据具体的性能测试类型开展测试。1. 性能测试的实施,往往先要根据业务场景来决定需要开发哪些单⽤户脚本,脚本的开发会涉及到很多性能测试脚本特有的概念,⽐如思考时间、集合点、动态关联等等。2. 脚本开发完成后,你还要以脚本为单位组织测试场景(Scenario),场景定义简单来说就是百分之多少的⽤户在做登录、百分之多少的⽤户在做查询、每个⽤户的操作步骤之间需要等待多少时间、并发⽤户的增速是5秒⼀个,还是5秒2个等等。3. 最后,才是具体的测试场景执⾏。和⾃动化功能测试不同,性能测试执⾏完成后性能测试报告的解读,是整个测试过程中最关键的点。测试资源测试资源通常包括测试⼈员和测试环境,这两类资源都是有限的。测试计划的⽬的就是,保证在有限资源下的产出最⼤化。所以,测试资源就是需要明确“谁来测”和“在哪⾥测”这两个问题。测试⼈员是最重要的,直接关系到整个测试项⽬的成败和效率。测试⼈员的资源通常有两个维度:⼀是,测试⼯程师的数量;⼆是,测试⼯程师的个⼈经验和能⼒。你会发现,测试⼯程师的经验和能⼒不⾜,很难通过测试⼈员的数量来弥补。相反地,测试⼯程师的经验和能⼒都⾮常强的情况下,测试⼈员的数量可以适当地减少。通常在测试团队中,测试⼯程师既有资深,也会有初级,那么你就必须针对团队的实际情况去安排测试计划。⽐如,难度较⼤的⼯作,或者⼀些新⼯具、新⽅法的应⽤,⼜或者⾃动化测试开发⼯作,通常由资深的测试⼯程师来承担;⽽那些相对机械性、难度较⼩的⼯作,则由初级⼯程师完成。可见,你想要规划好测试资源,除了要了解项⽬本⾝外,还必须对测试团队的⼈员特点有清晰的把控。另外,我强烈建议你把具体的任务清晰地落实到每个⼈的⾝上,这将有利于家⾥清晰的责任机制,避免后续可能发⽣的扯⽪。相对于测试⼈员,测试环境就⽐较好理解了。不同的项⽬,可能会使⽤共享的测试环境,也可能使⽤专⽤的测试环境,甚⾄还会直接使⽤⽣产环境。另外,对于⽬前⼀些已经实现容器化部署与发布的项⽬,测试环境就会变得更简单与轻量级。测试进度在明确了测试范围、测试策略和测试资源之后,我们就要考虑具体的测试进度了。测试进度主要描述各类测试的开始时间,所需⼯作量,预计完成时间,并以此为依据来建议最终产品的上线发布时间。⽐如,版本接收测试(Build Acceptance Test)的⼯作量,冒烟测试(Smoke Test)的⼯作量,⾃动化脚本开发的⼯作量,缺陷修复的验证⼯作量,需要⼏轮回归测试、每⼀轮回归测试的⼯作量等等。在传统瀑布模型中,测试进度完全依赖于开发完成并递交测试版本的时间。如果开发提交测试版本发⽣了延误,那么在不裁剪测试需求的情况下,产品整体的上线时间就同样会延期。然⽽在敏捷模式下,测试活动贯穿于整个开发过程,很多测试⼯作会和开发⼯作同步进⾏,⽐如采⽤⾏为驱动开发(Behavior-Driven Development)模式,这样测试进度就不会完全依赖于开发递交可测试版本的时间。测试风险预估俗话说,计划赶不上变化,对于测试也是⼀样的道理,很少有整个测试过程是完全按照原本测试计划执⾏的。通常需求变更、开发延期、发现重⼤缺陷和⼈员变动是引⼊项⽬测试风险的主要原因。在敏捷开发与测试中,对于需求的频繁变更(如新加需求、删减需求、修改优化需求等),⼀定要重新进⾏测试需求分析,确定变更后的测试范围和资源评估,并与项⽬经理和产品经理及时沟通因此引起的测试进度影响。测试经理/测试负责⼈切忌不能有⾃⼰咬⽛扛过去的想法,否则⽆论是对测试团队还是对产品本⾝都不会有任何好处。另外,随着测试的开展,你可能会发现前期对于测试⼯作量的预估不够准确,也可能发现需要增加更多的测试类型,也可能发现因为要修改测试架构的严重缺陷⽽导致很多的测试需要全回归,还有可能出现开发递交测试版本延期,或者⼈员变动等各种情况。所以,在制定测试计划时,你就要预估整个测试过程中可能存在的潜在风险,以及当这些风险发⽣时的应对策略。09 | 软件测试⼯程师的核⼼竞争⼒是什么?