我一直认为,新系统的测试是最容易的测试,因为测试范围只需要围绕未来使用。而系统结构优化的测试,则复杂得多。老的系统往往会因为以前的设计思路和技术陈旧的原因遗留很多坑点,在做这部分优化时,除了要对这部分逻辑或技术做更新,还需要保证其原有功能的可用性。举个例子,如果准备修改登录逻辑代码由20位缩减为16位,则方案不仅包含16位密码的逻辑还需要兼容老的账号设置的20位密码的情况。所以往往系统优化的测试,需要包含原有功能的回归和新增功能的测试。而本文要讲到便是这样一个样例的测试。
项目背景:
产品设置之初未定义用户登录数据存储有效期概念。业务量日益增加,这些持久化在缓存和数据库中的数据越来越多。为了保证系统的可用性,需要对存储数据这部分功能做优化,而涉及调整的代码块正是产品日调用量最高的核心业务,下面便是讲述在做这部分功能测试过程中的辛酸史。
手机账号登录数据(下文统称为token)现状为:用户每登录一次,会记录下这条token数据,token数据会保留在数据库和缓存中。后续客户端或服务端可以通过check token的方式实现自动登录的功能。用户做退出操作则删除对应的token,不做退出token则永久保留。产品希望改成,用户token生成后,XX天未做过登录或自动登录的功能,check token时候则删除此token。如果用户在XXday<token<XXday期间的用户,check token时则做token创建时间的更新。
坑点一:需求漏洞需谨慎,功能重构看数据
刚拿到这一手需求,其实就已经有一处坑点,check token接口是整个业务系统里面调用量非常巨大的接口日调用成功的用户上千万,其提供用户自动登录的功能。如果说直接使用此方案设计测试策略,便没有考虑到对原有功能的兼容。首先需要知道现在调用量里面有多少token>XX天的数据,如果这部分数据很多,都将会退出登录,那么毋容置疑这种方案肯定是不行的。所以QA需要有对数据强烈的敏感性,尤其是涉及到用户场景体验的情况,一定要和产品一样保证用户的体验为先。果然一周的数据采集其中大于XX天的数据请求有1亿多条,占比15%左右。可想而知如果没有先进行数据采集分析,上线后的影响一定是非常大的。
于是在得到数据后,开发对方案做进一步改进,大于XX天的数据,添加一个开关,由开关控制大于XX天的数据是执行删除还是更新。接下来QA测试开始开展,这里基本上需要按照修改的内容做对应的用例设计,其中对于这种用户基数较大的场景,设计思路一定要尽可能的发散,你所面对的用户可能会是各种各样的状态(测试中真实发现的)。这里推荐一种用户模型遍历的方式,基于业务做各种用户模型的遍历,然后用例设计完成后,在各个模型下进行测试,检查业务场景在每个模型下是否合理。尽量在用例设计之初提出风险地方和极限情况下业务的情况,防止开发逻辑重新调整,导致测试返工。
坑点二:性能风险很可怕,结果分析是关键
系统大的变更,需要由QA来评估性能测试的必要性。这里我通常会根据下面几点来评估本次的版本是否需要进行性能测试,
1、根据系统本次修改的变更量的大小,如果一个接口变更超过20%,我一般不论是改动的哪里都会进行相应的性能测试;
2、变更处是否是与外部依赖的新增或修改,如果变更的地方是外部依赖有关的东西,尤其是新增外部依赖,是一定要做性能测试的;
3、接口逻辑调整导致调用数据库、缓存服务或消息队列等次数变多,也是有必要做性能测试;
4、最后一点也是大家都知道但是容易忽视的一点,接口调用数量增多的情况需要做性能测试。
性能测试的方案制定也需要花费一些心思,往往有的时候我们会直接把一个修改或新增的接口直接提测给性能测试组,而方案和测试指标由他们提供。这样做一般情况可行,但有些情况下,我们需要提供给他们更多的信息,
首先,测试范围的制定:有些时候接口A做了修改,接口B未做修改。我们往往只测试接口A,但却忽略了接口A和B的关联关系。如我们本次的接口,本次接口修改的为check token接口,登录接口未修改。但是仔细分析业务场景,很明显两者之间是存在着很重要的关系的。如果check token数据大于XX天,则会退登用户账号,用户只能再次做登录操作,那么登录接口的请求必然会增多。所以登录接口尽管未修改,却仍然需要进行性能测试。
其次,测试的指标,这里比较灵活。我们可以自己整理数据对比,给出最大并发和tps指标评估系统是否支持。也可以数据分层逐渐加压的方式压测系统支持的最高并发来评估系统。
最重要的部分是,性能测试的执行和结果分析,这里面需要知道一点,如果性能测试的机器的系统及依赖的db或其他配置配置和线上配置不一样,或不是等比计算,那么测试结论可评估的意义并不大。在配置等同的情况下,注意一定要评估任何捕获的的异常日志,以及最大支持的并发数,及tps为多少时,系统表现不稳定的情况。
这里有一点说明,在计算接口tps时一定要按照接口的峰值请求数来算,不能取平均值的方式。如我这个check token的接口取均值单台tps只有8点多,但是如果接口峰值的请求计算的话会达到56。这个相差是非常多的,而正是这个,也为上线出事埋下伏笔(从性能报告中可以看出压测时DB出现问题的)。
最后果然在错误的估算tps后,上线后出现了数据库连接池打满的问题,最终此次上线以失败告终。
坑点三:线上操作最恐怖,严格评审很必要
上线出问题后,紧接着功能全部开关关闭(感谢有开关配置,这里也建议。重要的功能上线,且回滚代价较高的系统,可以尝试用开关控制功能),一时间看起来好像整个方案都要推到重做,但却有点不那么甘心。最后大家觉得,既然一次行20多台机器全开放这个功能,会报数据库连接池满,那么我只配置两台机器,数据库肯定能抗的住啊。然后在事故第二天只配置2台机器,这次数据库并没有报错,但是线上却出现了一批错误处理的数据。这里有必要再细说下当时业务逻辑,系统部署在一批负载均衡的机器上,配置项可以控制哪几台机器走token删除或修改的逻辑,而删除或修改的逻辑则是由推送服务控制,以域名再反指定到这些负载均衡的机器上去处理token(如图),推送时应该只推送到开启服务的那两台,结果全集群推送,所以导致业务处理错误。
实际上出现这种问题的原因主要是未进行方案验证。上线安排的配置中并不包括这种部分机器上线的配置。也并未做这种方式的测试和演练。最终在准备不充分的情况下,仓促上线导致这次上线的内容失败告终。所以任何一次得线上操作,都应该是有测试和演练过的。这样才能高质量的保证线上的系统的可用