一、背景
因为全量用例的数量比较庞大,每一次版本迭代之后,想完全执行一遍全量用例,几乎是不可能的,其实是一定不可能的,只能把一些核心的P0级别的执行。
但是其实每一次迭代中,并非是影响全量,我们目前只能凭借开发依据代码“进行推测”可能影响的业务范围,特别的交代进行回归测试。这种“经验”往往是不可靠的。
如何“科学”的评估此次迭代中影响到的业务范围呢?甚至具体到该执行那条用例呢?怎么样才能做到真正的降本增效。这就是我想解决的问题。
二、一期目标
开发周结束,可以通过系统报告自动了解本期改动(或新增) 影响到的历史业务。
三、设计思路
目前我们服务端常见的一些改动都有哪些呢?
- 数据库(mysql、es、redis...):修改字段(类型或名称),新增表,新增列
- 接口(RPC或HTTP)层面:新增接口,新增(删除)字段
- 方法层面(包含MQ消费、生产):逻辑优化
- 定时任务:逻辑修改,任务新增
这些地方改动一处,就是影响整个调用链路。如:方法内部逻辑优化,调用这个方法的地方一定是受到“潜在”影响的
那么。建模!
如果将这些“逻辑分层”,抽象为一个个节点,一层之间内部的调用链路,就形成了一张图,不同层之间就形成了,多层的“图”。这个三维立体的“层次分明”的图,如果节点之间有一个具有一定权重的线连接起来,整个服务就被模拟出来了。
当我们对整个系统设置一个“最大影响数”,修改其中一个节点,就可以理解为,与之有关联的所有受影响节点,都是需要关注(标记)的。
随之而来的有几个问题:
- 什么样的级别可以当成一个节点?:一个节点要足够原子,我们并不会关注节点的内部,一个方法(不管是路由方法、逻辑处理方法、工具方法)就可以作为一个节点,一张表就可以当成一个节点,一个缓存key可以当成一个节点
- 按照水平优先(广度)还是垂直优先(深度)标记?答:垂直的层与层之间关联强度远大于同一层级之间的,每一个业务是必然要从顶层(接口)贯穿至底层,因为我们需要按照水平优先进行,层与层之间,往往是强关联。
- 同层级采用无向图,还是有向图?答:有向图好一些,因为一个节点发生变化,调用这个节点的“风险”才会更大,这个节点依赖的下一个节点处,风险小,甚至没有风险。
- 什么是最大影响数?答:每一条标记的路线上权重总和等于最大影响数。这个是影响最终结果的最大因素。因为我们知道节点与节点之间有一定的权重,我们通过直接影响点(此次迭代中修改的这个节点),来“辐射”这个节点带来的影响,当我们顺藤摸瓜去给影响点做标记的过程中,每走一步,需要根据权重“扣除”一定的数值。 因此,我们设计权重并非是数值越大,权重越大。而是数值越小,权重越大。
因此,最大影响数太大,导致回归的内容会越多,漏测的风险就越小。最大影响数太小,漏测的风险就越大。这个数值需要根据当前版本修改的内容来动态规定。
后续可以考虑,根据 最大影响数 = 线上故障数(正相关)/ 当前版本缺陷数
即:最大影响数 与 线上故障数正相关,与当前版本缺陷数 负相关(缺陷越少,漏测风险越大)
- 权重如何设计才科学?有何依据?答:权重的本质是为了标记节点与节点之间的关联关系。有一部分节点我们知道,他们之间强关联。如:新增一个用户,从接口,到逻辑,到数据库,这一路过去都是强关联,改动中间的任何一块,这条路上的所有节点都会受到影响。因此,这种节点之间的权重数值是0级别。
1级别:方法-调用关系
2级别:方法-被调用关系
- 关于依赖第三方的如何标记权重和“线”呢?答:对于第三方的服务能力,系统默认是按照完全信赖的逻辑进行,不做校验。另一类,我们给到其他域信息(短链或消息队列),其他域处理后会通过MQ的方式进行返回的,我们就需要将处理MQ消息的方法,与我们给予其他域信息的方法,两个方法进行横向关联。
- 如何维护系统?答:我们只关注节点的新增、修改、删除,节点之间的关系维护,并不关注节点内部的逻辑。
- 微服务下适用吗?答:适用。并不关注服务划分,关注的是方法级别的调用。即,原子节点之间的调动
- 代码覆盖率是不是也可以完成这个任务呢?有什么区别呢?答:代码覆盖率是执行过这个方法就算覆盖到,但是这个方法影响到的业务可能有很多,这个时候极其容易导致漏测情况发生。
四、预期收益
- 节省回归时间,提高回归精准度,降低线上冒烟风险
- 能第一时间罗列出所有的影响面。便于开发review
五、设计方案
1、节点实现方案
- 考虑是多层图的模型,我们最直观的考虑就是使用三维空间节点来实现,即(x,y,z)作为一个节点唯一标识,x表示节点编号,y表示层级编号。z表示一个节点名称(类名+方法名),便于系统前端进行手动直观的进行配置
通过指针来确定引用信息。指针表,增加权重列。
- 使用一维数组来实现逻辑“立体”。这样做的好处是存储空间小。但是会增加比较多的查找节点的算法
2、层级设计
- 业务层 y = 0
- api层 y = 1
- service层 y = 2
- db层 y = 3
- entity层 y = 4
六、系统代码实现
1、后端代码
-
层级预划分
-
新增节点与关联关系(第一层节点必须是前端业务层,业务层也可以是提供给其他域的)
2、前端代码
-
查看某一层节点信息
-
查看某一个节点的引用节点信息
-
编辑某一个节点,新增一个下层级调用/同层级调用
-
设置最大影响数,生成版本影响报告 - 根据时间段查询,这个时间段内,影响的业务内容都有哪些。
七、后续展望
- 根据gitlab diff直接同步节点信息
- 做发布卡点
- 支持做流量模拟,查看哪些节点承受的压力大(存在并发风险),处理时间长,就需要对哪些节点进行性能优化
- 智能化测试探索
需要确认的点:
- 影响路径的搜索算法选择
- 节点设计是否合理?符合后端架构?是否真的适用?
- 有没有遗漏的情况没有覆盖到
市场现有的系统调研:
市面现有基本上都是基于接口层面,重点在于对用例进行标注,用于后续计算出diff后,进行推荐操作,并且对推荐算法进行降噪和优化:
劣势:以上几种都是针对围绕用例进行重点工作开展。但其实很多业务用例,修改得太快,如,各种报表搜索的用例,而用例编写成本是比较低的