一、背景
接口测试自动化脚本主要作用是在业务代码反复迭代过程中验证历史系统功能以及新特性功能正确性的,主要在持续集成过程中具有重大意义。
而测试脚本在执行时,都需要进行测试数据准备,测试主体执行,测试数据销毁这三个步骤。其中,数据准备和数据销毁对于海量的测试脚本来说具有重复性,比如我们执行一个用例,都需要先创建用户、而后执行完成之后注销用户,这些都往往为用例的复用步骤。
这种方式执行用例会导致以下问题:
- 重复步骤执行占用大量测试时间。
- 全量测试时大批量的并发用例执行会导致用户服务 cpu 使用率激增,有服务崩溃的风险。
本文主要介绍如何通过资源池的方式统一管理用例测试数据的使用,减少用例执行时间,提高测试效率。
二、方案介绍
为了解决以上问题,在每个用例执行时,我们不再重新创建本次用例需要用到的前置测试数据,而是直接从资源池中拿取数据。同理,用例执行完成时,我们也不再执行资源的销毁接口,而是请求到资源池服务中处理,进行异步的回收。
这样相当于把数据准备步骤前置,数据销毁步骤后置。同时节省了用例前置和后置步骤的时间,提高了用例执行效率。
2.1 用例执行过程
以用户资源为例,对比资源池方式和原方式用例执行流程。
2.1.1 原用例执行方式
原方式执行用例需要保证用户可用,存在使用老用户执行用例和新用户执行用例两种情况。所以需要先检查用户是否存在,存在说明是老用户执行,直接登录即可。不存在,说明需要创建新增用户,重新走注册登录流程。
2.1.2 资源池用例执行方式
资源池方式执行用例的过程较为简单,只需要新增两个资源管理的接口:申请资源和回收资源。用来替代整个用例的前置和后置。
整体流程为:申请资源 → 测试主体执行 → 回收资源
申请资源:根据执行用例的测试数据需要,请求资源池服务需要的测试资源的过程。
回收资源:用例执行完成之后,归还资源到资源池中的过程。
相比之下,资源池方式主要把前置创建用户的过程预置到资源池服务中进行管理,减少了这部分的用例执行时间。
2.2 资源池服务
资源池服务中统一对所有需要进行资源管理的资源进行分类和集中管理。大致架构为
按资源特点将资源进行分类,每一个不同类型的资源集合组成一个小资源池,请求资源时携带能唯一标识该资源类型的数据,获取到特定资源池中的资源进行返回。
比如对于用户资源来说,时区1的用户集形成一个资源类型集合,时区2的用户集形成一个资源类型集合,这样就实现了资源的个性化,使不同的用例能申请到不同特性的资源。
下面将介绍资源池中的关键流程。
2.2.1 初始化
目前资源池中的所有资源都需要在数据库中进行存储并维护其使用状态,通过内存缓存机制,减少数据库访问过程中消耗的时间。
资源池服务启动时,会加载数据库中所有的可用资源到缓存中,并将资源进行分类存储,形成上述存储结构。
2.2.2 申请资源
资源中申请资源的过程关键需要监控资源的使用状态,同时注意并发问题,同一个资源同一时刻只能由一个用例申请。
大致流程为:申请资源请求 → 资源个数检查 → 资源合法性检查 → 更新资源状态 → 返回资源
资源个数检查:申请资源时检查资源池中的资源是否大于申请资源需要的个数,否则就需要新建资源。
检查资源是否合法:对于有时效性的资源需要进行资源合法性检查,保证资源在申请时是可用的。
2.2.3 回收资源
资源池中回收资源为异步接口,因为用例执行完成之后不需要关心数据的回收结果,只需要关心测试结果,这样可以一定程度上减少用例执行时间。
同时需要检查过往未回收的遗留资源,如果申请时间超过1小时,则强制回收。
申请资源时会标记此次申请的资源是否可重复利用。是否可重复利用对于回收资源来说,回收的方式不同
- 重复利用资源:在回收时会重新添加到资源池中,供下次申请使用,
- 不可重复利用资源:直接销毁,删除。
未回收资源数据:检查数据库中申请资源超过1小时且仍还未回收的资源,认定为过期资源,添加到回收队列中进行强制回收,防止数据无限膨胀。
异步处理资源回收:提交回收资源异步任务。
资源是否重复利用:根据申请时标记的资源是否重复利用字段来决定,资源回收方式是回收还是销毁。
三、结语
3.1 效益
在业务增长过程中,用例数呈稳步增长趋势,对比资源池使用之前和使用之后一次全量测试接口数量和接口请求次数的关系,我们可以分析出资源池带来的效率提升。
经过分析发现,平均一个接口经过全量测试需要调用接近 36016 / 347 ≈ 104 次完成测试。
在8月份上线资源池之后,平均一个接口只需要调用 48637 / 755 ≈ 64 次即可完成测试,降低了约 39 个百分点。对于接口调用次数的减少具有显著效益。
3.2 总结
- 通过业务的不断扩大,我们可以持续评估脚本中利用率比较高的测试数据,达到一定量的冗余之后,可以将这种类型扩充到资源池中进行资源管理。
- 资源池的思想其实随处可见,线程池,进程池,缓冲区,其实都使用了资源池的思路。它提高了资源使用效率。使其应用在用例执行层面时,大大减少了用例执行时间,同时使其一定程度上减少了前置服务的cpu压力。
- 在脚本设计时,我们也可以通过抽象出来的资源池方法论,在小的业务范围内实现一个小型资源池,来解决有关前置数据接口冗余调用的问题,比如社区的圈子,标签等。