ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Dokku 测试体系完全指南:从 Bats 单元测试到应用部署测试的本地与 CI 实践

Dokku 测试体系完全指南:从 Bats 单元测试到应用部署测试的本地与 CI 实践 Dokku 测试体系完全指南从 Bats 单元测试到应用部署测试的本地与 CI 实践【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku本文以 docs/development/testing.md 为骨架结合仓库内 tests.mk、Makefile、tests/unit、tests/apps 等源码与配置系统梳理 Dokku 的测试分层、本地执行方式、单测定位技巧与 CI 集成细节帮助开发者在二次开发 Dokku 插件或核心功能时快速建立可复现的测试工作流。一、测试体系总览三层测试各司其职Dokku 是一个基于 Docker 的 PaaSPlatform-as-a-Service其插件系统由大量 Shell 脚本与 Go 代码构成。为了保证迭代速度与质量Dokku 在仓库中维护了一套完整的测试体系分为三个层次层次工具/形式作用范围存放位置静态检查Lintershellcheck、shfmtShell 脚本的语法、规范与常见反模式仓库全部 Shell 脚本不含 docs/debian/tests 等目录功能单元测试BatsBash Automated Testing System单个命令、单个插件、单个触发器的行为tests/unit/*.bats应用部署测试示例应用 git push 全流程端到端验证代码推送到 Dokku 后能否成功部署并响应请求tests/apps/从文档原文与仓库结构看测试脚手架被统一维护在tests目录下tests/unit/*.batsBats 单元测试文件每个文件通常对应一个插件或一组相关命令如apps_1.bats、certs.bats、nginx-vhosts_1.batstests/apps/覆盖 Go、Java、Node.js、Python、Ruby、PHP、Clojure、Scala 等主流语言与框架的示例应用每个应用目录内带有check_deploy脚本用于断言部署结果。三个层次的测试通过 Makefile 目标统一暴露详见下文核心 Makefile 目标小节开发者既可以一键跑全量也可以按需单独执行某一层。二、本地执行环境Vagrant VM 与 VSCode Dev ContainerDokku 的测试会对真实 Docker 守护进程、SSH 配置、网络与端口做操作因此需要在完整的 Dokku 环境中执行。官方文档给出了两种受支持的本地环境。2.1 方式一Vagrant VM先在 docs/getting-started/install/vagrant.md 的指引下通过 Vagrant 启动一个预装了 Dokku 的虚拟机然后进入虚拟机初始化测试依赖并执行vagrant ssh sudo su - cd ~/dokku make ci-dependencies setup-deploy-testsmake ci-dependencies安装测试运行所需的依赖。在 tests.mk 中可以看到它聚合了bats shellcheck xmlstarlet docker-apt-repo四个子目标——bats-core、shellcheck、xmlstarlet 均按需安装docker-apt-repo则在设置了INSTALL_DOCKER_REPO时额外安装 docker-buildx 与 docker-compose 插件make setup-deploy-tests为部署测试准备运行环境。从 tests.mk 的实现看它完成了一系列关键初始化将dokku.me及*.dokku.me、www.test.app.dokku.me解析写入/etc/hosts域名通过DOKKU_DOMAIN变量覆盖默认dokku.me生成测试用 SSH 密钥对/root/.ssh/dokku_test_rsa并写入~/.ssh/config的Host dokku.me与Host 127.0.0.1端口22333两个条目修改 sshd 配置监听22333端口并重启 SSH 服务确保测试推送可并行、可隔离通过sshcommand acl-add dokku test将公钥授权给dokku用户设置默认 VHOST 为dokku.me通过prime-ssh-known-hosts预先建立 SSH 连接将目标主机写入 known_hosts避免测试中途被主机指纹校验卡住。2.2 方式二VSCode Dev Container在 VSCode 中打开 Dokku 仓库仓库自带.devcontainer相关配置后直接在 VSCode 终端执行make ci-dependencies setup-deploy-tests即可完成同样的环境初始化。两种方式后续的测试命令完全一致。2.3 修改代码后同步到测试环境修改本地 Dokku 克隆后测试环境中运行的仍是旧代码需要把改动同步过去# 将本地 git 克隆安装/更新到环境中的 Dokku make copyfiles # 仅重新构建并安装某个特定插件 make go-build-plugin copyplugin PLUGIN_NAMEappsmake copyfiles在 Makefile 中定义为先cp dokku /usr/local/bin/dokku更新主二进制再对全部 Go 插件执行go-build随后通过plugn init初始化插件目录并遍历plugins/下每个子目录调用copyplugin把插件源码复制到${CORE_PLUGINS_PATH}/available并建立符号链接、启用插件最后生成 man 手册make go-build-plugin copyplugin PLUGIN_NAMEapps则只针对plugins/apps一个插件做构建与安装适合在只改动某个插件时加速迭代。注意go-build-plugin需要显式指定PLUGIN_NAME否则 Makefile 会直接报错退出。三、执行测试从全量到单条的四级粒度3.1 核心 Makefile 目标目标作用底层实现tests.mkmake test全量测试环境准备 lint 单元测试 部署测试tests.mktest: setup-deploy-tests lint unit-tests deploy-testsmake lint运行全部静态检查tests.mklint: lint-shfmt lint-cimake unit-tests运行全部 Bats 单元测试 Go 插件单元测试tests.mkunit-tests: go-tests后接bats tests/unitmake deploy-tests运行全部示例应用部署测试tests.mk 顺序调用一系列deploy-test-*目标3.2 全量与分层执行make test # 全量lint unit-tests deploy-tests前面自动带上 setup-deploy-tests make lint # 只跑静态检查 make unit-tests # 只跑单元测试 make deploy-tests # 只跑应用部署测试其中make lint实际上包含两条线见 tests.mklint-shfmt用shfmt -l -bn -ci -i 2 -d .检查 Shell 脚本的格式化规范缩进 2 空格、花括号换行等lint-ci先用lint-setup扫描仓库中所有文本型 Shell 文件排除debian、docs、tests、vendor等目录再调用shellcheck逐个检查最终通过 tests/shellcheck-to-junit 将结果转换为 JUnit XML 输出到test-results/shellcheck/results.xml便于 CI 展示。被抑制的检查项清单维护在.shellcheckrc中。另外仓库的 Go 插件也带独立单元测试make unit-tests会先执行make go-teststests.mk对certs、common、config、cron、docker-options、logs、network、ps、buildpacks、scheduler-k3s、storage、traefik-vhosts等插件逐个运行go test -v -p 1 -race -modreadonly。3.3 执行单个应用部署测试部署测试以deploy-test-应用名命名。例如要单独部署并验证nodejs-express应用make deploy-test-nodejs-express对应的目标定义在 tests.mkdeploy-test-nodejs-express: echo deploying nodejs-express app... cd tests ./test_deploy ./apps/nodejs-express $(DOKKU_DOMAIN)tests/test_deploy脚本tests/test_deploy是整个部署测试的驱动器其工作流大致为将示例应用复制到临时目录并git init以gitdokku.me:test-app-随机数为 remotegit push到 Dokku触发完整的 build release deploy 流程若测试预期失败如go-fail-predeploy、go-fail-postdeploy断言 push 必须失败成功后通过dokku url拿到访问地址调用应用自带的 check_deploy 脚本发起 HTTP 请求验证应用确实响应了预期内容例如 nodejs-express 的 check_deploy 断言响应体为nodejs/express失败则重试一次后判定整体失败最后apps:destroy清理测试应用并关闭事件跟踪。完整的部署测试清单可在make deploy-tests的依赖列表tests.mk中查看覆盖checks-root、main-branch、config、clojure、dockerfile、dockerfile-noexpose、dockerfile-procfile、gitsubmodules、go、java、multi、nodejs-express含 noprocfile、worker 变体、php、python-flask、ruby、scala、static等。更完整的 make 目标清单请直接查阅仓库根目录的 tests.mk。3.4 执行单个 Bats 测试套件开发某个插件时往往只想跑与该插件相关的套件。Bats 支持直接指定套件文件路径bats tests/unit/apps_1.bats也可以一次指定多个套件bats tests/unit/apps_1.bats tests/unit/certs.bats从 tests/unit 的目录内容看套件文件按插件/功能域组织例如apps_1.bats、apps_2.bats、certs.bats、config.bats、domains.bats、git_1.bats~git_7.bats、nginx-vhosts_1.bats~nginx-vhosts_16.bats、ps-general-*.bats、scheduler-k3s-*.bats等文件名后缀数字用于将大套件拆分为多文件以适配 CI 并行分片。注意直接运行bats tests/unit/apps_1.bats前环境应已通过make setup-deploy-tests完成初始化SSH 密钥、VHOST、hosts 等因为每个套件都会通过 tests/unit/test_helper.bash 的global_setup/global_teardown清理既有应用与容器并依赖dokku命令与测试域名。3.5 执行单条测试用例为了进一步提升迭代速度仓库提供了基于 Bats--filter参数的包装用法先列出套件内的全部测试Bats 会将test ...声明的测试名打印出来bats --filter list tests/unit/apps_1.bats然后按正则匹配测试名来执行所有匹配的用例都会运行bats --filter apps:list tests/unit/apps_1.bats例如 apps_1.bats 中声明了(apps) apps:list、(apps) apps:create等用例用bats --filter apps:create即可只执行与apps:create相关的测试。--filter采用正则匹配因此也支持更宽泛的模式一次命中多条用例。四、Bats 测试的编写范式从套件到断言了解如何阅读与编写 Bats 套件能帮助开发者快速定位失败原因或为插件补充测试。以 tests/unit/apps_1.bats 为例套件的基本骨架是#!/usr/bin/env bats load test_helper setup() { global_setup } teardown() { global_teardown } test (apps) apps:list { run /bin/bash -c dokku apps:list 21 echo output: $output echo status: $status assert_success assert_output_contains You havent deployed any applications yet ... }关键约定load test_helper引入 tests/unit/test_helper.bash 中定义的大量辅助函数每个套件统一在setup/teardown中调用global_setup/global_teardown前者在文件级.skip标记存在时跳过剩余用例即前一个测试失败则跳过后续测试并清理残留应用与容器后者在测试未完成时落盘.skip标记。这种设计保证了套件内测试的快速失败与状态隔离run /bin/bash -c ...是 Bats 捕获命令输出与退出码的标准姿势$output、$status、$lines由 Bats 注入断言层通过assert_success、assert_failure、assert_output、assert_output_contains、assert_line、assert_equal等函数完成全部定义在 test_helper.bash 中并且大量测试使用echo output: ...输出上下文方便失败时在 CI 日志中定位辅助函数还封装了create_app/destroy_app应用生命周期、deploy_app通过 git remote 推送真实部署、assert_http_success/assert_http_localhost_responseHTTP 探测、setup_test_tls解包预生成证书证书 tar 位于 tests/unit 的server_ssl*.tar以及run_plugn_trigger/run_plugin_script直接调用单个插件的 trigger 脚本绕过其他插件的处理器用于插件级隔离测试等能力。五、CI 集成与平台支持5.1 GitHub Actions 上的自动化测试所有 Pull Request 都会在 GitHub Actions 上跑测试其 CI 环境为 Ubuntu Noble 24.04 并提供 Docker 支持。仓库中的 .github/workflows/ci.yml 展示了具体做法check-commit作业检查最近一次提交信息若包含[ci skip]或docs:前缀则跳过后续全部测试作业needs: check-commitif: skip ! true这印证了文档中关于[ci skip]标记的说明主build作业在ubuntu-24.04上运行设置了INSTALL_DOCKER_REPO: 1环境变量对应 tests.mk 中docker-apt-repo的安装逻辑并通过 matrix 策略分发测试任务timeout-minutes: 45单元测试在 CI 中通过test-ci目标tests.mk执行用 CircleCI CLI 的tests glob/tests split --split-bytimings对tests/unit/*.bats做按历史耗时的智能分片然后以 JUnit 报告格式输出到test-results/bats便于 CI 聚合展示仓库还提供了tests-ci-retry-failed目标利用 bats-retry 重跑失败用例tests.mk。5.2[ci skip]标记的语义如果某次提交不需要跑测试例如纯文档修改可以在提交信息中写入[ci skip]。需要特别注意的是本应测试却携带该标记的提交不会被合并——这是项目对 CI 把关的强制性约定避免开发者借跳过标记绕过回归验证。5.3 平台支持边界虽然 Dokku 官方为多种平台提供安装包但由于测试套件目前运行在 Ubuntu Noble 24.04 上官方只对**该平台以及受支持的 Ubuntu LTS 版本当前为 22.04 与 24.04**提供官方安装支持。也就是说测试覆盖范围直接决定了官方支持矩阵其他发行版可以自行安装体验但不在官方 CI 保障之内。六、常见工作流速查场景推荐命令首次搭建本地测试环境Vagrant/DevContainermake ci-dependencies setup-deploy-tests修改后同步到环境make copyfiles全量或make go-build-plugin copyplugin PLUGIN_NAME插件名单插件全量回归make test仅静态检查make lint仅单元测试make unit-tests仅部署测试make deploy-tests单个应用部署测试make deploy-test-nodejs-express应用名可替换单个 Bats 套件bats tests/unit/apps_1.bats单条/多条用例bats --filter list tests/unit/apps_1.bats列出bats --filter 正则 tests/unit/apps_1.bats执行提交时跳过 CI提交信息中包含[ci skip]注意应测未测的提交不会被合并七、相关资源索引官方测试文档docs/development/testing.md测试 Makefile 目标全集tests.mk文中所有命令的最终定义均以此为准测试公共辅助库tests/unit/test_helper.bash部署测试驱动器tests/test_deploy 与示例应用目录 tests/apps/每个应用的check_deploy脚本即验证断言Bats 套件目录tests/unitCI 工作流.github/workflows/ci.yml、.github/workflows/lint.ymlVagrant 环境搭建docs/getting-started/install/vagrant.md【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表