跳转到内容

07 - 测试策略与 CI

学习目标

本章聚焦 Hermes Agent 的测试策略与 CI 架构。你将了解:

  • ~17k 测试如何通过 per-file 隔离高效运行
  • 技能测试的规范要求(仅 stdlib + pytest + mock)
  • GitHub Actions CI 的 SHA 固定依赖与审计
  • 发布流程自动化

前置知识

无特定前置知识。


项目实践

测试规模

截至 2026-05,Hermes 拥有:

  • ~17k 测试用例
  • ~900 测试文件

这种规模的测试集需要高效的运行策略。

测试运行器架构

scripts/run_tests.sh 自动探测虚拟环境并调用并行运行器:

Terminal window
# 自动探测 .venv / venv
# 调用 scripts/run_tests_parallel.py

run_tests_parallel.py 关键设计

策略实现
Per-file 隔离每个测试文件在独立子进程中运行
干净环境env -iTZ=UTCLANG=C.UTF-8PYTHONHASHSEED=0
虚拟环境优先 .venv,回退 venv,再回退 ~/.hermes/hermes-agent/venv
Live Gateway可选通过 ~/.hermes/pytest_live_guard.py 加载 live gateway 插件

Per-file 隔离确保单个测试文件的崩溃或污染不影响其他测试文件。

技能测试规范

tests/skills/test_<skill>_skill.py 是技能测试的规范文件:

规范要求

  • 仅使用 stdlib + pytest + mock
  • 禁止实时网络调用:所有外部 API 调用必须 mock
  • 技能测试必须在干净环境中通过

为什么不用实时网络? 技能测试需要可重复、快速、离线可运行。实时网络调用导致测试不稳定且慢。

测试目录结构

tests/ 目录按功能组织:

目录测试内容
tests/skills/技能功能测试
tests/tools/工具功能测试
tests/agent/Agent 核心循环测试
tests/gateway/网关测试
tests/cron/Cron 调度器测试

CI:GitHub Actions

关键策略

策略实现
SHA 固定依赖GitHub Actions 使用 SHA 而非 tag 引用 action,防止供应链攻击
审计CI 日志记录所有依赖版本

发布流程

scripts/release.py 自动化发布:

  1. 版本号递增
  2. CHANGELOG 生成
  3. Git tag 创建
  4. 发布到 PyPI(如果适用)

问题与规避

大规模测试运行时间长

问题:~900 个测试文件顺序运行需要很长时间。

对策run_tests_parallel.py 将测试文件分发到多个子进程并行运行。Per-file 隔离确保并行安全。

技能测试的网络 mock 不完整

问题:技能需要调用外部 API,但测试中 mock 可能不完整。

对策:技能测试标准禁止实时网络调用。所有外部依赖必须 mock。如果技能确实在真实环境中测试,使用 live gateway 插件(pytest_live_guard.py)在 CI 中可选运行。


设计取舍

Per-file 隔离 vs 进程内运行

方案优势代价
Per-file 隔离(Hermes)测试间完全隔离、一个测试崩溃不影响其他子进程启动开销
进程内运行启动快、资源共享测试间可能互相干扰、状态泄漏

Hermes 选择 per-file 隔离,因为 ~17k 测试中任何单个测试的崩溃都不应该导致整个测试套件失败。隔离带来的开销在 CI 环境中是可接受的。


参考来源

  • 源码验证:tests/ 目录结构、scripts/run_tests.shscripts/run_tests_parallel.pyAGENTS.md 测试策略章节