Devops实践——容器化测试环境
前言
文本将介绍在 Devops
流程中的项目单元(集成)测试的容器化构建,并通过一个项目实例来演示。
为什么要容器化测试环境
-
我之前的文章已经介绍过开发环境的容器化。同样,测试环境的容器化也能够尽可能的保证项目运行环境的一致性。
-
声明式环境依赖配置,跟随项目进行版本管理,有利于 CI\CD 任务执行。
-
利用容器编排工具来构建完整的测试环境。例如在 Web后端 项目的开发中,我们编写的接口通常会依赖数据库服务(Redis、MySQL等),而解决方案通常有两种:
- 针对相关依赖编写 Mock 接口(增加工作负担,且要保证 Mock 接口的质量)
- 单独部署项目依赖(脱离了 CI\CD 流程,增加运维负担)
现代的 CI\CD 工具通常对上述问题提供了一种 service
的概念,即在 CI\CD 流程中允许我们显示声明需要的依赖,由 task runner
管理依赖的生命周期,保证我们的测试代码能够运行。
而本文提供了 docker-compose
的解决方案,即通过编写 compose 容器编排文件的方式来解决测试期间的依赖问题。
注:个人认为,目前流行的 CI\CD 工具较多,缺乏统一标准,我们可以尝试通过通用技术来降低自己的学习负担。
项目实践
本例中我们将通过一个 rust
的项目来演示我们如何通过 docker-compose
容器编排技术配合Github Actions 来实现我们项目的自动化测试。
注:文章略去了 rust 的代码细节,详情请参考 这里
假设项目接口的运行依赖 Redis 数据库
环境依赖
- Docker 和 Docker Compose
- Github Actions
构建项目
执行下命令初始化一个 rust
项目:
docker run --rm --workdir=/app --user=$UID -v.:/app rust cargo new testing-rs-demo # 使用容器初始化rust项目,无需本地安装 `rust` 工具链
创建.docker-compose-testing.yaml
文件,内容如下:
version: '3'
services:
redis:
image: redis:7
test-srv:
image: rust
volumes:
- "./:/usr/src/app"
working_dir: "/usr/src/app"
command: env RUST_BACKTRACE=1 cargo test --tests -j 1 -- --nocapture --test-threads=1
这是一个标准的 docker compose 编排配置文件,我们声明了两个服务,一个是项目依赖的 redis ,另一个是实际需要运行的项目
我们通过下命令来运行容器化测试:
docker compose -f .docker-compose-testing.yaml up --build --abort-on-container-exit
--abort-on-container-exit
参数会指定我们的测试容器退出(测试完成)时停止服务注:我们要测试的项目代码可直接通过 dns解析 的方式访问 redis 依赖(详细请参考 Docker Compose Docs)。
然后创建.github/workflows/test.yaml
文件来配置 Github Actions 完成自动化测试:
name: Testing Action
run-name: ${{ github.actor }} is testing out action
on: [push]
jobs:
Test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Test Code
run: "docker compose -f docker-compose-testing.yaml up --build --abort-on-container-exit"
通过声明上述文件,即可在每次推送代码到远程仓库时自动执行项目的单元测试代码。
注:
- 关于 Github Actions 后续会有文章介绍,或者请参考 Github Actions Docs
- 在实际项目中我们可以配置更完善的测试流程,比如发送测试结果的通知等。
总结
本节给大家介绍了容器化测试环境的构建,并使用 Docker Compose 容器编排来解决测试代码依赖问题。
更详细的示例请参考 这里