Skip to Content
附录D · 测试与演进

D · 测试与演进

测试目录不只是质量工具,也是架构证据:它告诉我们哪些边界被认为需要独立验证、哪些行为跨平台、哪些历史漏洞必须永久回归。

快照中的测试规模

1,197test functions
114tests Python files
3execution CI OS
3unit CI OS

pytest.ini 把 tests 与 tests-unit 都设为 testpaths,并定义:

  • inference marker:需要真实推理条件的测试;
  • execution marker:完整执行引擎测试;
  • 默认 -s 保留输出。
pytest.iniL1-9测试根、markers 与默认参数。

两个测试世界

tests-unit/

强调小范围、可替换依赖和边界逻辑:

  • app managers 与 migrations;
  • Assets query/service/API;
  • V3 input/video 类型;
  • folder paths;
  • schema type validation;
  • server cache control、WebSocket flags;
  • 用户目录;
  • 安全回归;
  • feature flags 与工具函数。

tests/

强调系统行为:

  • execution graph;
  • async nodes;
  • jobs/cancel;
  • preview method;
  • progress isolation;
  • public API;
  • inference;
  • output quality comparison;
  • asset seeder。

Execution 测试使用专门节点包

tests/execution/testing_nodes/testing-pack/ 内有:

stubs.py 可预测基础节点 conditions.py 条件与 lazy 行为 flow_control.py expand / blocker / 图控制 async_test_nodes.py 异步节点 api_test_nodes.py public API 边界 specific_tests.py 针对回归的节点 tools.py / util.py 测试辅助

这是一种很好的 runtime 测试策略:不要用巨大真实模型才能验证 scheduler;构造“行为可控的微型节点”,让 cache hit、列表映射、PENDING、环和错误都可确定重现。

执行器需要覆盖的不变量

能力最重要的断言
output-driven孤立节点不执行,目标闭包执行
cache输入/祖先未变命中,任一语义依赖变更失效
list mapping短列表重复最后值,OUTPUT_IS_LIST 正确展平
lazy未选分支不执行,请求输入后节点能恢复
async只提交一次,完成/异常能解除 external block
expand临时 ID 唯一、父节点恢复、subcache 隔离
blocker不当异常处理,消息与静默传播区分
errornode ID、display/real ID、inputs 和 traceback 准确
progress并发/连续 Prompt 上下文不串线
cancelwaiting 原子删除、running 协作中断

安全回归测试是一张威胁地图

tests-unit/security_test/ 的文件名直接记录 GHSA 修复面:

测试保护什么
...preview_traversal.pypreview/view 路径逃逸
...annotated_traversal.py[input]/[output] annotation 穿越与 symlink
...userdata_xss.py用户文件同源脚本执行
...dangerous_content_types.pyMIME 变体、参数、XML 家族
...inline_svg_image_dest.pySVG <img> 特例与导航/缓存边界

这类测试不应在重构时合并成一个“危险文件被拒绝”的泛化用例。每个变体代表不同绕过手法,细粒度名字本身是安全知识。

Assets 测试为何很多

Assets 需要同时维护数据库与真实文件系统事实:

  • 内容 hash 去重;
  • reference owner/name/path;
  • cursor/keyset pagination;
  • metadata filter 与 tag refine;
  • missing / prune / resync;
  • upload/download;
  • seeder pause/cancel;
  • output prompt/job ID 关联;
  • loader path 映射。

这是一类典型“双写/索引”系统,最危险的是中断中间态和重复操作。测试数量反映的不是 UI 复杂,而是一致性状态多。

模型测试分层

model detection unit

用 key/shape 或最小 state dict 验证模型配置选择,不必跑完整采样。

dtype / quant unit

验证 mixed precision、设备条件和转换规则,避免用“能出图”掩盖隐式高精度 fallback。

inference marker

真实构造与 forward,成本高、环境依赖强,应与普通 PR 单元测试区分。

quality comparison

输出数值/图像质量回归与功能正确性不同:一次重构可能不 crash,却改变结果分布。比较测试承接这一层。

CI 划分

Execution Tests

Ubuntu、Windows、macOS,Python 3.12,安装 CPU torch 与项目/测试依赖,执行:

python -m pytest tests/execution -v --skip-timing-checks

跳过 timing check 避免共享 CI 机器的调度噪声导致功能测试不稳定。

Unit Tests

同样三平台,执行全部 tests-unit。跨平台矩阵对 folder paths、MIME、设备 fallback 和文件 locking 特别重要。

本快照两个 workflow job 都标记 continue-on-error: true。这意味着它们提供可见信号,但单独看 workflow 不能假设是强制合并门禁;还要查看聚合 CI / 仓库保护规则。

其他工作流

  • Ruff;
  • launch/build 测试;
  • OpenAPI lint;
  • line endings;
  • release/package 的多平台工作流;
  • API stubs 更新。

从测试反推模块边界

一个改动应落在最低足够层:改链接类型验证先写 unit;改 async PENDING 写 execution;改 attention 数值再加 inference/quality。所有问题都用完整 GPU workflow 测,会慢且难定位。

读源码时怎样用测试

  1. 先找到目标函数的直接 unit test,确认显式契约。
  2. 再搜测试节点,观察运行时如何驱动该能力。
  3. 搜 bug/GHSA 命名回归,理解代码中看似多余的 guard。
  4. 看跨平台 workflow,区分 POSIX 假设与公开行为。
  5. 找不到测试时,把源码注释和调用点视为较弱证据,不擅自补成稳定承诺。

扩展作者的最小测试组合

schema registration test pure execute unit test list/batch shape test cache fingerprint test external error/redaction test path traversal test (if files) async cancel/idempotency test (if async) expand graph + cache test (if dynamic) one small end-to-end Prompt test

可迁移的设计方法

  • 为复杂运行时建立专用微型测试插件,不让模型成本绑架调度测试。
  • 安全漏洞按攻击变体保留命名回归,代码 guard 才不容易被“简化”掉。
  • 数值正确、系统正确与输出质量分层测试。
  • 跨平台文件/设备策略必须在 CI 矩阵出现,而不是靠条件分支自证。
  • CI 的“运行了”与“阻止合并”是两件事,审核时同时看 workflow 和 branch protection。
Last updated on