APP下载

一种基于DevOps 的自动化测试及CI/CD流程的设计与实现

2022-07-24卞中杰

科学技术创新 2022年20期
关键词:测试环境测试数据后台

卞中杰

(上海甚解信息技术有限公司,上海 200235)

随着交通运输行业的飞速发展,道路货物运输量逐年上升,为了帮助运输企业降低运输过程中的事故率,出现了由第三方企业开展的针对道路货物运输的风险控制业务;然而由于风控软件的特殊性,软件发布需要做全套的单元测试、集成测试、系统测试、回归测试,传统的人工测试无法在有限时间和资源内确保测试的全面性和准确性,同时伴随长链路的业务流程越来越多,人工测试在数据准备和业务验证方面效率低下[1]。因此,自动化测试是一种能够保证测试正确执行的可行方法,只有保证自动化测试的正确性,才能实现系统后续的自动部署和快速迭代。

1 基于容器的DevOps

持续集成和持续部署(CI/CD)作为关键内容,包含多种实现方式,比如通过Jenkins 和Ansible 实现软件的自动化编译和部署[1];通过GitLab 的Pipeline 功能和Terraform 结合实现基础设施的自动化创建和部署[3];基于容器的DevOps 实施方案和实践[4]。

容器(指Docker、Podman 等容器技术)的出现使得DevOps 更容易被实现,DevOps 往往需要多种软件协同实现,由于容器天生具备隔离性,可使得不同版本的软件互不影响地在同一宿主机上运行,相比虚拟机而言,启动速度更快、资源占用更小。此外,容器的打包方式可实现开发环境和生产环境的软件版本、依赖项等高度统一,打包完成的镜像易于分发。

Kubernetes 的出现改变了容器编排方式,能从更高维度管理容器的生命周期,将服务器作为一整个集群统一管理,使得容器可灵活地在集群中被启动和调度。Kubernetes 可以帮助基于容器分发的软件获得高可用、可扩展、可漂移的能力,并具备细粒度的容器管理能力。本文探讨的CI/CD 以及自动化测试的实现均基于Kubernetes,充分利用容器的能力和特性,实现从开发到部署的自动化。

2 DevOps 中CI/CD 总体流程设计

对于CI/CD 流程而言,触发整个流程开始的事件通常是开发人员提交代码或者代码被合并到测试或生产分支。一旦代码提交,如果GitLab 发现代码仓库根目录中存在.gitlabci.yml 文件,GitLab 会通知独立部署的GitLab Runner 组件,依次运行该文件内定义的流程任务,CI/CD 的整体流程见图1。

图1 CI/CD 整体流程设计

CI/CD 流程脚本都写在.gitlab-ci.yml 文件中,在文件的开头往往会定义一些变量为后续步骤服务,同时该文件也定义了运行每个步骤默认使用的容器(文本使用docker:stable 镜像)以及整个流程的3 个流程节点(又称Stage):test、build 和deploy。

在流程的第一步中,编译测试会被首先执行,可确保新的代码能够被编译通过。在这之后,会根据不同项目类型执行单元测试、集成测试、系统测试等,在所有测试通过以后,到下一步镜像打包阶段,如果测试失败,则流程终止。

镜像打包阶段软件需要被打包成Docker 镜像,由于每一步流程都是在一个容器中启动,此方式被成为DinD(Docker in Docker)。运行DinD 需要priveleged 权限,出于安全考虑,选用kaniko 镜像来实现镜像打包且无需额外权限即可使用。

镜像打包并上传到镜像仓库以后,在测试环境或预发布环境中进行部署,而Kubernetes 中,部署方式通常有两种:使用原生部署配置文件或Helm 工具。Helm 通过向模板注入不同的配置和参数,来生成不同的部署文件,其灵活性优于Kubernetes 原生部署文件;并且Helm 具备部署的版本管理功能,便于版本切换,故使用Helm 进行部署,配置如下:

Helm 从app/test 下载模板文件,并且结合代码仓库下. /deploy / test / values . yaml 的属性更改,会在Kubernetes的test 命名空间(namespace)下,部署一个名为test-app 的应用。至此,测试、预发布程序已经完成部署。对于测试环境则流程结束;而对于正式环境,可在预发布环境做最后的核对和测试,当测试完成后,继续后续的发布到生产环境的流程。

3 自动化测试设计

在整个自动化部署流程中,测试是最为关键的一环。测试方法和用例的设计以及用例是否能被正确执行,决定了能否自动执行后续的发布流程。在测试执行过程中,面临着两类问题:(1)多人提交代码导致测试并发执行,引起数据冲突使得测试失败;(2)由于前一次的测试用例修改了测试数据,再次执行测试导致测试失败。下文将介绍通过容器技术和测试管线设计来解决以上两个问题。

3.1 总体测试执行流程

代码在提交、合并或进入发布通道时均可设置不同的测试环节。当软件通过了所有的测试,流程自动进入到后续的发布阶段,而测试中有某一项未通过,则发布流程终止。如果流程涉及合并请求,可以驳回并自动关闭本次合并请求。自动化的测试流程分为4 个阶段:创建和启动测试环境;导入和初始化测试数据;执行测试;销毁测试环境。当环境和数据准备完成之后,执行所有测试并判断结果;当测试完成以后,销毁测试环境,执行后续流程。

3.2 测试数据准备

高质量、可复用的测试数据除了能够支撑后台软件测试,同样要能够为前端测试提供服务。单一存储的测试数据会被测试样例在运行期间删除、修改,导致测试无法重现,并且在多人并发测试场景下,如果某一方修改了测试数据,会导致其他依赖该测试数据的测试无法进行。因此,测试数据必须被独立抽取出来,在测试流程开始时完整地恢复到测试环境中,形成可复用的测试数据。在该项目中,测试数据按照生产环境要求和格式预先被设计好并存放在MySql 中,使用MySql 的dump 命令将测试数据全部抽取形成文件,并存放到源代码管理系统中。例如对于MySql5.7 版本,把App 数据库中的users 表数据全部导出为users.sql 文件,可使用如下命令:mysql _user USER _password PASSWORD _host HOST dump _database App _tables users > users.sql,其中USER、PASSWORD、HOST 分别需要替换为真实的数据库用户名、密码和数据库服务器地址。要把该导出文件恢复到测试环境数据库中,则对应的恢复命令是:mysql _user USER_password PASSWORD _host HOST < users.sql

在后续的测试指令执行完成后,本次Stage 内启动的所有容器及其中数据都会被删除,不会造成数据和环境残留。

3.3 测试环境启动和执行

由于整个CI/CD 流程均在基于容器的环境中进行,因此可以使用容器在测试环节中启动测试该业务所需的所有配套设施。

3.3.1 后台测试环境配置和启动流程

以测试一个微服务为例,需要启动的依赖设施有MySQL 数据库和Flask 服务器。在Pipeline 中对应的Stage配置如下:

这段配置文件首先修改了默认运行环境为:${TEST_ENV_IMAGE},这是一个变量,指向开头定义的对应的镜像名,该镜像是一个安装了flask 和pytest 的带有python3.7 运行时环境的容器。services 语句定义了除运行主容器以外,在这个Stage 中还需要运行一个MySql5.7 的容器,该容器和主容器之间可进行网络通信。接下来before_script 属性的值描述了容器启动后先运行的脚本,这里是向MySql 导入测试数据的合适时机。再接下来的script属性定义了环境准备完毕后运行测试的指令,在这里运行的是pytest 测试指令,可以根据实际需要定义若干条测试指令。因此,一个完整的测试环境在容器中得以运行,该微服务所依赖的所有外部服务同时也以容器方式启动,在所有测试语句运行完毕以后,这些容器都会被销毁,不会留下数据和配置残留。

3.3.2 前端测试环境配置和启动流程

前端软件的测试会和后台服务软件测试存在差异。除了小游戏、工具型软件等无需和后台交互的程序外,与业务结合的前端软件绝大部分依赖于后台服务才能运行,因此在测试前端的过程中,后台服务环境也要一并启动。单元测试由于不依赖于后台,只需启动一个带有headless 浏览器的容器(本文使用cypress/browsers:node16.13.0-chrome95-ff94 镜像),在该容器内可以运行前端的单元测试代码;但是e2e 测试由于需要最大程度地模拟用户真实使用场景,且为了确保测试可靠性,整个流程需要真实后台数据参与,在e2e-test该环节中的services 中定义了需要额外启动2 个容器,分别是MySql 和后台微服务。通过启动后台微服务确保前端测试匹配对应版本后台逻辑,测试过程中可与真实测试数据进行交互,而MySql 则是运行后台微服务所需要的依赖项。

4 自动化集成和部署设计

在代码通过测试后,自动化流程来到集成和部署阶段。CI/CD 的实现因不同软件打包方式、系统运行环境和部署方式而不同,由于本系统全部运行在基于容器的Kubernetes之上,因此软件的分发需要把软件打包成Docker 镜像,并在Kubernetes 上进行部署。在.gitlab-ci.yml 中,可以分成2 个Stage 来进行:(1)在build 这个stage 中,使用Docker-in-Docker 的方式编译打包微服务的Docker 镜像,并上传到一个私有的镜像仓库。而在build-test-mysql 中,基于MySql 镜像打包了一个带有测试数据的镜像,可作为一个带有初始数据的数据库镜像灵活地运用在所有需要测试数据的环节中。(2)在deploy 这个stage 中,使用kubernetes 原生工具kubectl 通过配置文件部署应用,除了前文提到的Helm,如果不需要每次提交都对部署文件进行改动,而只是进行简单的版本更新操作,则此方式更为便捷。

从图2 可以看出,从代码提交到测试,再从软件打包到部署成功,整个流程并无人工参与,只耗时3 分32 秒(当中还包含每个Stage 的启动耗时)。如果项目使用敏捷开发模式,每天均可发布新的版本,这种方式能极大地提高软件测试和部署效率且避免人工操作错误,从而提高流程可靠性。

图2 GitLab 中后台服务CI/CD 效果图

5 结论

本文通过实现DevOps 以及使用Kubernetes 作为生产环境,软件的测试和发布效率都相比传统方式有了大幅度的提升。在本文中基于容器和自动化脚本的测试环境可以方便地启动和生产环境相同的组件,但这种测试环境追求的是最小化的类生产环境,因此该测试方法适用于测试业务的正确性。由于受限于测试环境所启动的单机资源限制,在自动化Pipeline 中启动的测试环境一般达不到和生产环境等同的资源和性能,如果生产环境是分布式、大数据系统,则启动相同形式的最小测试环境也会占用相当大的资源,会限制可同时进行的测试数量。除此以外,测试环境的特性决定了并不适合进行一些极端的压力测试,因为单机资源存在瓶颈且本地回环网络和真实服务器之间的物理网络吞吐能力都存在很大不同,这就造成性能测试结果无法代表软件在真实的生产环境中的性能表现,对于如何解决以上这些问题,仍需进行更进一步的研究与实践。

猜你喜欢

测试环境测试数据后台
全数字仿真测试环境在航天软件测试中的应用研究
雷达航迹处理测试环境构建方法研究
Wu Fenghua:Yueju Opera Artist
测试数据管理系统设计与实现
网络设备自动化测试设计与实现
后台暗恋
基于自适应粒子群优化算法的测试数据扩增方法
空间co-location挖掘模式在学生体能测试数据中的应用
负离子纺织品检测方法分析
互联网思维下的汽车服务连锁后台支撑系统