Ansible 测试实战:用 ansible-test 运行 Sanity、单元与集成测试
在 ansible-core 仓库中,所有测试工作都通过 ansible-test 这一统一入口完成,它覆盖三类测试:静态检查类的 sanity 测试、基于 pytest 的单元测试(unit tests),以及面向真实环境的集成测试(integration tests)。本文基于仓库内的 context/running-tests.md 编写,在完整保留其中全部命令与约束的基础上,结合 ansible-test 自身的实现源码,讲清每类测试的适用场景、容器选择规则和测试隔离选项,帮助你在改动 Ansible 代码后准确、可靠地验证自己的修改。
一、测试体系总览:一切以 ansible-test 为中心
context/running-tests.md 开宗明义:
All testing uses
ansible-test, which supports sanity tests (linting/static analysis), unit tests, and integration tests.
即三类测试各有分工:
| 测试类型 | 关注点 | 是否需要容器 | 典型实现位置 |
|---|---|---|---|
| Sanity tests | lint、静态分析、文档/元数据校验 | 不需要(--docker 可选) |
test/lib/ansible_test/_internal/commands/sanity/ |
| Unit tests | 函数级行为,pytest 风格 | 推荐 --docker |
test/lib/ansible_test/_internal/commands/units/ |
| Integration tests | 插件/模块的公开 API 端到端行为 | 需要发行版容器 | test/lib/ansible_test/_internal/commands/integration/ |
从源码结构看,ansible-test 的命令行解析层位于 test/lib/ansible_test/_internal/cli/,每类测试的子命令注册在独立的模块中,例如 sanity 子命令的参数定义就在 test/lib/ansible_test/_internal/cli/commands/sanity.py。这意味着下文中出现的所有 --test、--list-tests 等选项,都不是约定俗成的写法,而是有明确的 argparse 定义可以查证。
二、Sanity 测试:不依赖容器的静态检查
2.1 核心约束
原文档给出两条关键规则:
- Sanity 测试不需要
--docker; - 若本地缺少某些依赖(如额外的 Python 版本、shellcheck、PowerShell),对应测试可能被跳过——但对你验证自己的改动而言,"这通常无关紧要";
- 要对整个变更集的所有文件运行 sanity,而不只是你正在编辑的文件。
2.2 完整命令集(继承自原文档)
# Run all sanity tests
ansible-test sanity -v
# List available sanity tests
ansible-test sanity --list-tests
# Run specific sanity tests
ansible-test sanity -v --test pep8 --test pylint
# Run sanity on specific files (paths relative to repo root)
ansible-test sanity -v lib/ansible/modules/command.py
# Run all sanity tests in a container (for full coverage)
ansible-test sanity -v --docker
对应关系说明:
--test可重复使用,且取值受校验约束。在 test/lib/ansible_test/_internal/cli/commands/sanity.py#L49-L63 中,--test与--skip-test均为action='append',并且choices直接来自sanity_get_tests()返回的测试清单,因此写错测试名会在参数解析阶段立即报错;--list-tests定义于同一文件的 #L71-L75,用于先枚举可用测试再挑选运行;- 针对特定文件运行时,路径以仓库根目录为基准(如
lib/ansible/modules/command.py)。
2.3 原文档的容器参数警告(务必注意)
[!NOTE]
--docker不带参数时默认使用default容器。不要把非容器名参数紧跟在--docker之后,否则它会被解析为镜像名。
也就是说,ansible-test sanity --docker ubuntu 并不是"在 ubuntu 容器里跑 sanity",而是试图使用名为 ubuntu 的镜像——sanity/unit 场景下应直接使用裸 --docker。
2.4 更多可用选项(源码级补充)
除原文档涉及的选项外,sanity 子命令在 test/lib/ansible_test/_internal/cli/commands/sanity.py#L65-L112 中还注册了以下选项,按帮助文本原义列出:
--allow-disabled:允许运行默认被禁用的测试;--enable-optional-errors:启用可选错误级别;--lint:lint 输出写 stdout,其余写 stderr;--junit:测试失败结果输出为 junit XML 文件;--failure-ok:测试失败也返回成功退出码(保存结果后);--prime-venvs:只准备虚拟环境而不实际运行测试;--fix(仅 ansible 内容):能自动修复的问题直接修复,而不是仅报告。
另外,sanity 测试对历史遗留问题的豁免集中记录在 test/sanity/ignore.txt,排查"为什么某文件没有被检查到"时值得查看该文件。
三、单元测试:pytest 风格的单元验证
3.1 命令(继承自原文档)
# Run all unit tests
ansible-test units -v --docker
# Run a specific unit test (paths relative to repo root, targets in test/units/)
ansible-test units -v --docker test/units/modules/test_command.py
# Run with coverage
ansible-test units -v --docker --coverage
要点:
- 单元测试目标位于
test/units/目录下,路径同样相对仓库根目录; - 单元测试默认需要容器执行(原文档给出的示例统一带
--docker); --coverage开启覆盖率收集,其底层由 test/lib/ansible_test/_internal/coverage_util.py 支持。
3.2 本仓库中的真实单元测试示例
单元测试目录 test/units/modules/ 中按模块组织了对应测试文件,例如 test/units/modules/test_apt.py、test/units/modules/test_get_url.py、test/units/modules/test_systemd.py 等,均可直接作为单文件运行 ansible-test units 的参数。单元测试的运行依赖由 test/units/requirements.txt 声明。
配套的测试编写约定见 context/writing-tests.md:单元测试应为 pytest 风格、以功能行为为导向而不是与 mock 强耦合;几乎所有的插件改动都要求集成测试覆盖公开 API。
四、集成测试:在发行版容器中验证端到端行为
4.1 命令(继承自原文档)
# Run all integration tests
ansible-test integration -v --docker ubuntu
# Run a specific integration target (directory name in test/integration/targets/)
ansible-test integration -v --docker ubuntu ping
- 单个集成目标对应
test/integration/targets/下的一个目录名; - 例如
ping目标就是一个真实存在的目录 test/integration/targets/ping/,其中包含aliases文件(声明该目标的别名与运行环境要求)和tasks/(具体任务),这展示了集成目标的物理结构。
4.2 容器选择规则(原文档核心结论)
- Sanity/Unit 测试:
--docker(默认落到default容器); - 集成测试:
--docker ubuntu、--docker fedora等发行版容器,不能使用 default/base; base与default容器仅用于 sanity/unit 测试;- 集成测试应依据被测模块选择合适的发行版容器;
- 各命令支持的容器清单及其支持的 Python 版本,可查看对应测试命令的
--help输出。
从实现角度看,容器解析逻辑位于 test/lib/ansible_test/_internal/containers.py 与 test/lib/ansible_test/_internal/docker_util.py,因此 --help 中列出的可用容器并非文档约定,而是由这份代码动态给出。
五、测试隔离选项:--docker 与 --venv
原文档对执行环境的隔离给出了两个选项:
--docker(支持 Docker 或 Podman)——首选,提供可靠、隔离的测试环境;--venv——容器不可用时的回退方案,但由于宿主机环境差异,单元测试在--venv下可能不可靠。
选择建议:只要本机具备容器运行时,三类测试都优先走 --docker;仅在容器环境缺失时用 --venv 快速验证,并把最终结论保留到容器环境(或 CI)中确认。
六、把命令落到实际改动上的推荐工作流
结合本文各节,对一次典型的 ansible-core 改动,建议的验证顺序为:
ansible-test sanity -v --list-tests先确认要跑的测试项;ansible-test sanity -v <改动文件...>对整个变更集跑静态检查(本地缺依赖导致的个别跳过可接受);ansible-test units -v --docker <目标文件>运行相关单元测试;ansible-test integration -v --docker <发行版容器> <目标名>验证插件/模块的公开行为;- 需要留档或接入 CI 时,追加
--junit之类的输出选项(见 sanity.py 源码中的定义)。
需要留意的两个边界:其一,--docker 后误跟非容器参数会被当作镜像名,集成测试务必显式指定发行版容器;其二,路径一律以仓库根目录为基准书写,避免相对路径歧义。
参考位置(便于继续深入)
- 本文主文档:context/running-tests.md
- 测试编写预期:context/writing-tests.md
- sanity 子命令参数定义:test/lib/ansible_test/_internal/cli/commands/sanity.py
- 三类测试的执行实现:test/lib/ansible_test/_internal/commands/
- 容器与 Docker 工具:test/lib/ansible_test/_internal/containers.py、test/lib/ansible_test/_internal/docker_util.py
- sanity 豁免清单:test/sanity/ignore.txt
- 单元测试示例:test/units/modules/test_apt.py
- 集成目标示例:test/integration/targets/ping/
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00