基于Docker的接口测试平台构建

勿忘初心2018-10-19 18:42


此文已由作者吴桐授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。



引言

本文主要讲解开发人员、测试人员、运维人员如何围绕API接口测试这个点相互协作。提到协作,我们现在想到的更多是团队内部资料文档,项目进度管理等的云协作,在测试领域协作的概念可能还没有完全被推广开。文章涉及到项目中遇到问题,解决问题的方法及思路,最后重点讲讲最佳实践。

项目中遇到的问题

最近所在的项目组要开发一个移动端APP,本身APP的功能并不复杂,但是与服务端和与移动端交互的API接口非常多,因此有必要做完整的接口测试。但是从项目的进度规划来看,只有两个迭代,从设计、开发到上线只有两个月的时间,进度十分紧张。有必要想一个高效的方法来解决这个现状。

反思API接口开发测试流程

同一件事情被多人重复做了:

开发人员完成一个API接口开发,部署到开发环境中,通过自己写自动化脚本或者利用POSTMAN工具验证API接口是否符合预期,这时候其实已经做过一个简单的API测试了。提测给测试人员后,测试人员又将同样的事情做了一遍,有没有可能开发人员做完的接口测试用例,测试人员就可以直接拿来在测试环境里面用呢?

开发提测的质量不可度量:

测试人员缺少客观的数据来评估接口的质量是否符合预期,从而导致后期因为质量问题出现版本回退的现象,拖延了开发周期。有没有什么办法来客观地度量开发的提测质量呢?

API接口的变动引起的叠加效应:

API接口变动是常有的事情,但是现有的流程中,一个接口的变动会牵扯出一系列的变动---文档、用例、测试代码、持续集成等......,时间成本瞬间提高。有没有一个中心化的接口测试用例管理方案呢?

我们需要什么

根据上面提出的三点反思,思路开始清晰起来,要解决团队不同角色围绕API接口测试相互协作的问题,需要一个可协作的接口自动化测试平台。 这个平台大概需要具备这些特征:

1)开发阶段在平台上做的接口测试,测试阶段可以直接拿来用

2)开发人员自测结果在这个平台上面可以可视化的看到

3)平台上修改会被下游调用感知到

调研现成的工具

表1  现成工具调研


工具 评估 满足需求
NEI 网易自研,非常优秀的接口用例管理平台,但是和我们上面提出的三个需求有偏差
POSTMAN Chrome的扩展应用,本地验证API接口非常方便快捷,但是局限于单机版,不符合我们的需求
外面其他商业化平台 公司内部接口不适合放到外面平台上

尝试自己造轮子

虽然身在云时代,这种做法是不被鼓励的,但评估了一下开发成本和我们已有的技术积累,觉得这件事在短期内是能够做成的,所以就决定自己来开发这样一个平台。下图是该平台最终做出来的样子:


图1  URS接口测试平台


从架构谈起



图2  系统架构


从架构图中可以看出,平台主要分为四个主要模块:web前台服务、调度服务、docker编排系统、API请求执行器。对于一个小组内部使用的测试服务,性能不是我们要考虑的首要问题,能快速投入使用才是首要目的,所以我们的技术选型都是围绕Python快速开发来展开的。下面列出了我们所用到的一些技术,可以看出都是领域内轻量级的框架。

技术选型


表2  技术选型


模块 框架 描述
web前台服务 Django, bootstrap, vue 负责前端页面,用户操作,API用例维护管理,向后端发送任务请求等
调度服务 flask, celery 1、接受前端任务,组装API请求
2、发送任务到执行器上面去执行,并将执行结果入库
 3、创建新的执行器
执行器 docker, flask 将任务中具体的API请求发送到具体的测试环境,执行并收集相关结果参数
其他 redis, RDS 消息队列和数据库

主要功能

1)接口测试用例的创建与管理

2)接口测试用例的执行

3)对接持续集成和自动化运维

一、接口测试用例创建与管理



图3 接口测试用例创建


该功能是web前台服务模块完成的,用户在页面上需要输入以下信息:url信息、请求方法(post/get)、请求header、请求body、校验header、校验body,这六个信息能够反应一条完整的Http API请求的测试用例。

用例的执行的结果如下图所示:




图4 执行结果


上图展示了用例执行的返回值,包括header和boy的内容,这是我们平时API测试过程中需要获得的两个重要信息,只要校验这两个内容中有没有符合预期的值,就可以判断接口是否通过。但是我们发现这种单一的http请求无法解决所有的API接口。

平时的API接口分为这几种:

1)请求参数固定

2)参数需要经过加工计算,例如请求参数中带有时间戳,md5值等

3)参数依赖其他方式获得,例如参数中的token需要依赖其他接口获得,短信验证码需要从缓存中捞取等

上面的方式只能解决第一种API接口类型,为了满足后面两种接口的需求,利用微服务来帮助我们解决这个问题,微服务负责生成这些需要外部获得的参数,调用的时候,只要向这个微服务发送一个请求,获取需要的参数填充到当前的请求里面,那么就可以像使用固定参数一样使用。

具体实现如下图所示:  


图5 获取外部参数


说明:图中参数BizInfo是从微服务http://10.165.124.29:8040里面取的,后台组装BizInfo参数时会判断一下这个参数的类型,如果是ufo(外部参数)类型的,那就自动去指定的微服务去获取参数,填到当前的请求中去,这就解决了参数依赖的问题。

详细流程如下图所示:



图6 使用微服务流程


微服务用docker作为载体,使用微服务的好处有:

1)将外部依赖参数作为一个完全独立的组件管理起来,拥有更高的敏捷性、可伸缩性和可用性

2)微服务可以被平时手工测试和单元测试利用起来,不必自己写代码来实现微服务已经提供的功能,最大化的实现了代码复用

接口测试测试用例执行

测试用例的执行是通过执行器来完成的,执行器是一个微型的docker容器,通过在容器里跑一个flask服务,安装了一个requests包,来执行http请求,这里可以有些人会担心创建太多的容器会不会消耗过多的主机资源,这点可以完全需要担心,我们使用了alpine镜像构建容器,alpine是一个非常轻量的镜像,大概只有5M左右。

执行器和测试环境之间的关系是怎样的?

执行器可以看作成一个HttpClient,可以指向不同的测试环境来发送http请求,所以执行器和测试环境是一对多的关系,在实际的使用中,是通过动态的修改执行器(docker容器)的hosts来让他指向不同的测试环境的。

创建执行器的过程是怎样的?

前端服务发送创建请求给调度器,调度器调用swarm API,swarm会根据集群节点机的资源利用状态,挑选一个宿主机里面创建容器,然后将创建好的ContainerID返回给执行器。

执行器(docker容器)管理:

docker容器的管理主要是搭建了一个swarm集群,和一个可视化的web管理服务-shipyard

SWARM集群搭建:

step1 在需要加入swarm集群的宿主机上开启docker deamon监听端口

# 第一种方法docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock#第二种方法在/etc/default/docker启动项配置项DOCKER_OPTS里面加上:-H 0.0.0.0:2375 -H unix:///var/run/docker.sock, 然后重启docker

step2 启动自动发现服务

docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap

step3 启动swarm集群管理服务

# manager_ip是启动swarm管理容器的宿主机IP, consul_ip是上面启动的发现服务的宿主机IP
docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise <manager_ip>:4000 consul://<consul_ip>:8500

step4 将节点加入swarm集群

# node_ip节点机的IP,consul_ip是上面启动的发现服务的宿主机IPdocker run -d swarm join --advertise=<node_ip>:2375 consul://<consul_ip>:8500

step5 启动shipyard服务:

# 启动rethinkdb(shipyard依赖的一个db服务)docker run -ti -d --restart=always --name shipyard-rethinkdb rethinkdb# 启动shipyard webui容器,link到rethinkdb,swarm_manage_ip是前面启动的swarm管理服务的地址,shipyard通过调用swarm的API来管理docker集群docker run -ti -d --restart=always --name shipyard-controller --link shipyard-rethinkdb:rethinkdb \
-p 8080:8080 shipyard/shipyard:latest server -d tcp://<swarm_manage_ip:2375>

搭建完成的效果是这样的:



图7  shipyard web UI


对接持续集成和自动化运维

持续集成目前的困境:

大部分项目的接口持续集成都是围绕Jenkins+TestNG来展开的,Jenkins虽好,但是在迭代快的项目中还是略显笨重,主要体现在测试任务创建和任务变更的灵活性方面,例如:无法动态的下掉或者新增接口测试用例。

自动化运维目前的困境:

目前的运维上线流程基本已经做的一键构建+发布+拉起服务,但是其中少了一个重要环节就是验证环节,运维将代码发布到预发环境的时候,需要通知测试或者开发去跑一下接口测试用例,通过了才发线上环境,这样做很不敏捷。

解决的办法是:

1)平台支持创建用例集

  将多个接口测试用例组合成一个用例集,可以按用例集来执行,用例集可以自由增删用例,执行的时候可以制定执行策略,比如一个小时执行一次等。



图8 创建用例集


2)开放API接口

  运维在部署完成后调用接口测试API执行接口测试,执行结束后,如果通过就接着自动化上线,整个流程一气呵成。具体流程图如下:



图9  上线流程


总结:

做接口测试的方式很多,测试技术也成熟,但是如何在已有的框架体系提高测试效率是每个测试人员应该思考的问题。



网易云容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能,点击可免费试用


网易云免费体验馆,0成本体验20+款云产品! 

更多网易技术、产品、运营经验分享请点击


相关文章:
【推荐】 微服务监控探索