维基百科:
软件可测试性(Software testability)是指一个软件工件(软件系统、模组、需求文件或设计文件等)在一给定的测试环境下,可支援测试的程度。
前些天开了一个小会,会上有一点让整理一下关于程序可测性的相关文档,想了想这是个大命题。在实施测试的过程中,会遇到各种各样的障碍,其中可测性应该可以排到第一位的,如果在使用工具和自身技能所能及的测试辅助意外,能够得到一些帮助,将会对测试工作有极大的便利性。
下面分享一下工作中遇到过的几种提高程序可测性的几种场景和解决方案,以供各位参考。
验证码
每次提到这个就想到万恶的验证码,这里分两类:页面图形验证码和短信验证码。
图形验证码
这个一般采取的方案就是万能验证码功能,更激进一点的方案就是测试环境取消验证码,我比较赞同第二种方案。
因为如果万能验证码的话,很可能需要多个配置(万能验证码开关,万能验证码内容),而且测试环境和线上环境需要有所区分。代码中处理也需要判断两次。
如果采取第二种方案,只需要维护一个配置,甚至不需要配置即可。配置中心可以设置一个全局的变量,表示当前环境具体的类型。
还有一些方案是通过IP过滤。如果是固定IP(一般是内网)发出的请求,则跳过验证,或者在Nginx
层面添加一个标记什么的。
手机验证码
这个通常在测试环境比较好实现,具体的方案跟图形验证码类似,基本的方案也是通用的,但是在进行性能测试的时候,会需要几万甚至十几万的手机号而且还需要储存对应账号信息,所以涉及的地方比较多。
下面分享一下我们目前的方案。
我们手机号验证码校验的通用规则只验证了前三位,这个就不写具体的正则表达式了。由于批量手机号需求只有我们组内人员有这个需求,所以用了一个12开头的号段,然后每个人分配一个第三位,我的128。
后面的八位数字跟用户的uid
互通,这样一来,再进行用户手机号相关压测的时候,我就不用再去某个地方获取用户当前绑定的手机号。
手机号验证码一般也是需要配置,这里面临图形验证码同样的问题,没办法绕过去,解决办法很多。大家八仙过海各显神通吧。
造数据
在我做接口测试的过程中,遇到的最耗时的地方就是造数据。有一种造数据2小时,写脚本5分钟,运行10秒钟的感觉。对于业务关联性比较多还有一些造数据流程特别长的,都是让人非常头疼的问题。维护测试用户的正确可用的测试数据会耗费很多时间,特别是在业务数据有效期较短,类型变更较大的。
此类问题目前用到最多的两个思路:自动化,暴力方法。
自动化
这个用的比较多,目的就是让手动造数据的过程自动化执行,属于测试自动化的一部分。由于本人专注服务端测试,所以这里只讲接口层面的。
根据现有的接口可以造数据的,就通过现有接口赋值参数调用实现。如果是需要依赖后台接口的,就联合后台项目的接口赋参调用。
对于接口参数复杂得难以实现赋值的,通过手动操作,查看实际参数加以修改。
对于数据需求量比较大的,进行并发造数据,如果遇到某些调用限制,应当协调修改配置,实在不行,就提前准备脚本,长时间执行。
暴力方法
这个经常用的就是改数据库,用的比较多的就是update
,很少用insert
,至于select
看具体情况。针对自己需要的数据,进行状态修改,数据添加,获取参数集合的获取。这个使用的前提就是测试能拿到数据库的对应权限,而且了解数据库中业务存储的不复杂,关联性的表格只有一张或者两张,确实了解整个业务中数据流通情况(部分接口可能先去Redis
或者类似ES
和solr
中获取数据)。
我自己在工作中尽量避免修改数据库,原因除了上面提到的几个前提之外,就是业务较为复杂,我很难控制影响范围,大多数时候用完之后,还需要还原这些信息,不然指不定将来就变成了一个坑。脏数据对于测试影响颇深,尽量保证用的数据是正常业务产生的,虽然有可能依然会出现脏数据。
对于端上的测试工程师来说,还有一些简单的方法,就是使用诸如Fiddler
和Charles
等工具进行抓包、拦截、自定义响应,来完成端上造数据的展示效果验证。
据我不太成熟的了解和实践,还有一种方法可以实现服务端Mock
数据的功能。之所以不成熟是因为目前没有完整Mock
过一个完整项目,因为太特么难了。更多是Mock
第三方接口的功能,特别是在性能测试中,一下文章供参考:
部署测试代码
最近了看一篇腾讯service mesh
的文章,颇有收获。容器化大行其道,但运用到工作中就参差不齐了。如果测试人员有能力完成测试代码的编写,以及运维团队提供部署测试代码的能力,那我只能说太幸运了。
如上文所说,如果我们需要在服务层做假数据或者Mock
其他接口,很难不涉及修改服务代码。修改代码之后,会需要调试,如果服务之间依赖太多,那么工作量就会非常大。
比如某一次我在测试某一个update
属性的接口,其中有某一个参数ID
,接口处理逻辑是先判断ID
对应数据的状态,然后去进行下一步的操作。但是ID
需要的数据量太大,造数据成本较高,而且产生的数据量影响偏大。所以我就想着,能不能修改程序代码,在获取ID
数据状态之后,不管返回结果是否是正确的状态,都进行下一步操作(当然不能影响接下来的处理)。
如果我通过部署测试代码替换造数据,会大大提升工作效率。为了不影响其他人的测试工作,可以通过多版本部署,或者流量管理等平台实现。
还有一种情况需要修改代码,就是在复现典型的BUG
的时候,之前遇到过一次线上反馈一个问题,开发排查原因是某个试题的子题目的答案为空。但是当时开发给的方案是将线上试题信息同步到测试环境,然后找一个对应学科和年级的老师,组套题,发布作业,学生作答复现这个问题。
在我强烈要求下,直接从日志中拿到这道题目的查询结果,写到代码里,为了省事儿,所有题目都返回这个数据,很快就定位解决了这个BUG
。
后门接口
对于一些实在搞不定的,例如之前提到的数据在MySQL
和Redis
,我们就需要一个可以刷新Redis
的功能,但是正常业务是没有这个的接口的,当时就是沟通开发写了一个后门接口实现这个功能,部分时候,测试也可以自己写自己的测试服务,来完成后门接口的功能实现。
对于后门接口的管理,相信有很多方案,这里也就不多说了。
自己曾经写过一个测试服务,写起来是非常快的,因为大部分的功能实现,开发都已经完成了,所以直接抄了过来就可以用,唯一的遗憾就是因为涉及到多个正常服务的后门接口,所以必需是一个单独的服务,导致抄过来的代码本体可能发生变化,而测试却无法感知,导致后门失灵。
- 关于程序可测性的经验暂时分享到这里!