本文首发于泊浮目的专栏:https://segmentfault.com/blog/camile
背景
在笔者目前的项目中,大部分业务跑在基于kvm的vm上。鉴于对项目质量的追求及尽可能节省人力资源的目的,着手调研高测试覆盖率的解决方案。
由于项目基于ZStack,所以架构与其较为相似,但在vm上添加了相应的agent,通过其来控制vm中的操作系统与软件。
众所周知,ZStack管理节点部分有一套较为完善的自动化测试框架,可以满足大多数场景。而Utility并非如此,只能通过黑盒测试来保证其质量,且许多测试场景需要start up一个真实的ZStack的环境,测试成本较高。
如果一部分测试可以设计在agent端,也就说是agent端的测试可以自举。这样就可以少设计一部分黑盒测试实例,降低潜在成本。
从业务看测试
从vm agent的业务逻辑来看,大多数业务都是修改DB配置、读DB配置,start, stop DB等。而为了case之间不受到影响,我们在跑完测试之后,需要重置当前的测试环境。
方案选择
Docker
放弃。其无状态的特性简直完美契合上述需求。但是docker里只能跑单进程,对于oracle相关的业务,可能无法满足。且部分版本oracle对Docker的镜像支持上可能有问题。
在docker中可以通过一些hack的手段去做到在一个容器中起多进程,比如systemd或supervisord。但是笔者对docker并不是非常的了解,所以没有继续研究下去。
Pouch
放弃。阿里自研的富容器技术,可以完美解决docker里单进程的问题——其实本质上也是在容器镜像起来时运行了一个init进程指定为1号进程,而不是像docker里在命令行中指定的进程。
在实践过程中发现有各种莫名其妙的报错,且相关文档不齐全。
VM By ZStack
目前的方案。通过ZStack来管理环境vm的生命周期,通过快照机制来还原环境。缺点也非常的明显,仅仅一个case生命周期就需要1min+,生命周期大致如下:
- 使用vm跑测试
- 停止vm
- 恢复快照
- 启动vm
让人感到舒服的是,ZStack提供了一套Java SDK,可以直接通过SDK完成上述操作。
基于ZStack的自动化测试
对接ZStack根本没有什么困难之处。更多的是要从成本这个点去考虑整个测试系统的设计。
这里的成本则又可以分为两种成本:
- 物理资源成本:产品线上目前能够投入进测试的host较少,故在资源稀缺的情况下,得尽量用较少的vm去完成这件事。
- 时间成本:一个开发人员跑测试的时间越短越好,而不是花大量时间去等待测试环境准备、清理等。举个列子,如果我搭建一个mysql 主备库,需要两台vm,如果串行去完成生命周期相关的操作,那么就是2min+;如果并行的去做,便是1min+。同理,如果这些测试能够尽量并行的去跑,则可以省下更多的时间。
角色
角色示意图如下:
TestCase
一个测试实例,含有测试代码。同时它会向ResourcePool申请所需的vm。
TestGroup
根据当前的策略组织TestCase去并行的跑这些Case。在这里可以控制并发粒度,最后将会提交给Junit的跑测试。
JUnitCore.runClasses(new ParallelComputer(true, true)
, testGroup.toArray(arrayTestGroup));
ResourcePool
资源池的概念其实有点像云。比如组内有4个开发,那么4个开发几乎是不可能同时跑测试的,同时有2个开发在跑测试也是小概率事件。与其每个人都申请几台测试vm放在那边(一天可能就跑1、2小时的测试),还不如大家都共享一个池内的vm,避免资源的浪费。就像公有云卖你1core512m,你去架个网站,但是它料到你用不了这么多,所以它就会超分超卖。
这个类会根据配置文件或者网络请求存入相应测试用的vm,并记录这些vm是否被使用,为了防止其他开发者一起跑测试的时候共用同一台vm,会给使用中的vm打上一个user tag,避免冲撞。另外,SessionId等常量也是从这里刷新而来。
小结
通过本文,向大家介绍了一下笔者目前在项目中设计的一个基于ZStack的自动化测试系统。基于各方各面的成本限制,故此设计的较为简单。如果后续有些较大的改动或显著的改进,笔者还会与大家继续分享。如果大家对于这方面的自动化测试有较好的实践或者建议,也欢迎在留言中一起交流学习。**