TEST_README.md 6.2 KB

MCP Gateway 测试说明

本目录存放 MCP Gateway 的单元测试和集成测试,覆盖本地 stdio 模式、公网 HTTP 模式、Redis session、认证客户端、工具转发和安全工具函数。

测试结构

tests/
├── test_rate_limiter.py               # 简单滑动窗口限流
├── test_gateway_session_store_unit.py # 公网 Gateway Redis session 存储
├── test_request_context.py            # 从 header、Bearer、cookie 解析 gateway_session_id
├── test_scoped_auth_client.py         # 公网模式授权码换票客户端
├── test_scoped_api_client.py          # 公网模式工具转发客户端
├── test_public_gateway_unit.py        # PublicGatewayApp 业务路由和 session 校验
├── test_security.py                   # session ID、hash、常量时间比较
├── test_public_server_integration.py  # HTTP 服务集成测试
├── test_run_coverage.py               # 覆盖率脚本回归测试
└── test_*.py                          # 既有本地 Gateway 测试

运行全部测试

python -m unittest discover -s tests -p "test_*.py"

运行指定测试文件

python -m unittest tests.test_rate_limiter

运行指定测试类

python -m unittest tests.test_rate_limiter.TestSimpleRateLimiter

运行指定测试方法

python -m unittest tests.test_rate_limiter.TestSimpleRateLimiter.test_allows_requests_within_limit

输出详细日志

python -m unittest discover -s tests -p "test_*.py" -v

覆盖范围

单元测试覆盖:

  • 限流器:滑动窗口、清理、多 key 隔离。
  • Gateway session store:Redis CRUD、key hash、TTL。
  • Request context:从 header、Authorization、cookie 解析 session,并验证优先级。
  • Scoped auth client:授权码换票、session 持久化、错误处理。
  • Scoped API client:工具调用、token 校验、header 组装。
  • PublicGatewayApp:工具路由、session 校验、request_id 生成。
  • Security utils:session ID 生成、SHA256 hash、常量时间比较。

集成测试覆盖:

  • HTTP /health
  • MCP initializetools/listtools/call
  • 缺少 session 的错误响应。
  • header、Bearer、cookie 三种 session 传递方式。
  • 404 和未知方法处理。

测试依赖

当前测试使用 Python 标准库:

  • unittest
  • unittest.mock
  • http.client
  • threading

不需要额外安装测试依赖。

新增测试约定

  • 文件名使用 test_<module_name>.py
  • 测试类使用 Test<ClassName>
  • 测试方法使用 test_<scenario>
  • 每个测试尽量只验证一个行为。
  • Redis、HTTP 客户端等外部依赖使用 mock 或 fake 实现。
  • 安全修复必须补回归测试,例如不能记录授权码、不能信任可伪造 header。

常见问题

集成测试提示 Connection refused

HTTP 测试服务可能还未启动完成。可适当增加 setUpClass 中的等待时间:

sleep(1.0)

mock 断言异常

确认每个测试前重置 mock:

def setUp(self):
    self.mock_object.reset_mock()

覆盖率报告

快速开始

使用便捷脚本:

# 运行测试并生成所有覆盖率报告
python run_coverage.py

# 运行并自动在浏览器中打开 HTML 报告
python run_coverage.py --open

手动命令

如需手动生成覆盖率报告,需要额外安装 coverage

pip install coverage

# 运行测试并收集覆盖率数据
coverage run -m unittest discover -s tests -p "test_*.py"

# 生成控制台报告
coverage report

# 生成 HTML 报告
coverage html

# 生成 XML 报告(用于 CI/CD)
coverage xml

报告类型

运行覆盖率测试后,会生成三种报告:

  1. 控制台报告:在终端显示,包含每个模块的覆盖率百分比
  2. HTML 报告:交互式网页界面,位于 htmlcov/index.html
    • 显示逐行覆盖情况,颜色编码
    • 点击文件可查看哪些行被执行
    • 红色 = 未覆盖,绿色 = 已覆盖
  3. XML 报告:机器可读格式,用于 CI/CD 工具(coverage.xml

覆盖率指标说明

  • Stmts: 可执行语句总数
  • Miss: 未执行的语句数
  • Branch: 分支总数(if/else 条件)
  • BrPart: 部分覆盖的分支数
  • Cover: 总体覆盖率百分比

当前覆盖率 (2026-07-08)

模块 覆盖率
新增模块(Public 模式)
constants.py 100% ✅
services/api_client.py 100% ✅
services/gateway_session_store.py 100% ✅
services/scoped_api_client.py 100% ✅
services/scoped_auth_client.py 100% ✅
tools/query_track.py 100% ✅
utils/rate_limiter.py 100% ✅
utils/security.py 100% ✅
services/request_context.py 97.37% ✅
public_gateway.py 95.31% ✅
services/auth_client.py 94.59% ✅
config.py 93.18% ✅
现有模块
public_server.py 83.47%
app.py 74.58%
tools/query_order.py 80.95%
mcp_protocol.py 80.28%
tools/bind_auth_code.py 75.00%
services/token_store.py 52.40%
总体 80.80%

覆盖率配置

覆盖率通过 .coveragerc 配置:

  • 源代码: 项目根目录的所有 Python 文件
  • 排除: 测试文件、缓存、虚拟环境、覆盖率运行器 run_coverage.py
  • 分支覆盖: 已启用(追踪 if/else 路径)
  • 报告精度: 2 位小数
  • 排除规则: # pragma: no cover 注释、调试代码、if __name__ == '__main__'

提高覆盖率

对于低覆盖率的文件:

  1. 在 HTML 报告中识别未覆盖的行
  2. 编写测试来执行这些代码路径
  3. 关注边界情况和错误处理
  4. 继续补充主入口点(app.py)中 serve-public 和异常分支的集成测试

CI/CD 集成

GitHub Actions 工作流示例:

- name: Run tests with coverage
  run: |
    pip install coverage
    coverage run -m unittest discover -s tests -p "test_*.py"
    coverage report --fail-under=80

- name: Upload coverage to Codecov
  uses: codecov/codecov-action@v3
  with:
    file: ./coverage.xml

coverage html 会在 htmlcov/ 目录生成 HTML 报告。