☰
ComfyUI-Impact-Pack 通配符系统全量测试套件:7 个测试脚本的运行方法、判定逻辑与源码实现解析
2026/10/14 15:35:12 网站建设 项目流程
  • AI 应用
  • 计算机视觉
  • 图像处理

【免费下载链接】ComfyUI-Impact-Pack

Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more.

项目地址:https://gitcode.com/gh_mirrors/co/ComfyUI-Impact-Pack
点击查看免费下载

本文围绕 tests/RUN_ALL_TESTS.md 展开,完整继承其中的快速运行命令、7 个独立测试脚本及其用例规模、测试基础设施约定与日志位置,并结合仓库源码深入解析每个测试套件背后验证的 HTTP API 端点、惰性加载(on-demand loading)、循环引用防护(100 次迭代上限)与配置引号剥离等实现细节。读完本文,你可以独立完成 Impact Pack 通配符(wildcard)系统的全部回归测试,理解每个套件的通过判定标准,并能将测试脚本适配到自己的 ComfyUI 环境。

一、测试套件总览与运行环境

RUN_ALL_TESTS.md描述的是 ComfyUI-Impact-Pack 的wildcard 系统完整测试套件。套件由 7 个独立的 Bash 测试脚本组成,全部位于 tests/ 目录下,合计86 个测试用例(15+10+20+17+8+5+11),文档声明的预期结果为100% 通过率。

每个测试脚本的运行模式一致:

  • 在专属端口上启动一个独立的 ComfyUI 服务(避免测试之间互相干扰);
  • 生成一份指向测试通配符样本目录的impact-pack.ini配置;
  • 通过 HTTP API 逐条执行测试用例并校验返回文本;
  • 结束后自动清理:杀掉测试服务器进程、删除临时配置文件。

1.1 快速运行(Quick Run)

原文档给出的完整运行命令如下(注意原文中cd路径为作者本机环境,实际使用时请替换为你自己的仓库路径):

cd /mnt/teratera/git/ComfyUI/custom_nodes/comfyui-impact-pack/tests bash test_encoding.sh && \ bash test_error_handling.sh && \ bash test_edge_cases.sh && \ bash test_deep_nesting.sh && \ bash test_ondemand_loading.sh && \ bash test_config_quotes.sh && \ bash test_dynamic_prompts_full.sh echo "" echo "==========================================" echo "Test Suite Complete" echo "==========================================" echo "Total: 86 tests across 7 suites" echo ""

也可以逐个独立运行:

# UTF-8 Encoding (15 tests) bash test_encoding.sh # Error Handling (10 tests) bash test_error_handling.sh # Edge Cases (20 tests) bash test_edge_cases.sh # Deep Nesting (15 tests) bash test_deep_nesting.sh # On-Demand Loading (8 tests) bash test_ondemand_loading.sh # Config Quotes (5 tests) bash test_config_quotes.sh # Dynamic Prompts Full (11 tests) bash test_dynamic_prompts_full.sh

1.2 运行前提

从测试脚本源码可以看到两个必须了解的环境依赖:

  1. 脚本内COMFYUI_DIR为硬编码路径。以 tests/test_encoding.sh 为例:

    PORT=8198 COMFYUI_DIR="/mnt/teratera/git/ComfyUI" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" IMPACT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" CONFIG_FILE="$IMPACT_DIR/impact-pack.ini" LOG_FILE="/tmp/encoding_test.log"

    IMPACT_DIR由脚本自身位置自动推导(脚本目录的上一级,即插件根目录),但COMFYUI_DIR写死为/mnt/teratera/git/ComfyUI。在其它环境运行时,需要把每个脚本里的这一行改成本机 ComfyUI 的实际路径,再执行bash run.sh --listen 127.0.0.1 --port $PORT才会指向正确的宿主程序。

  2. ComfyUI 服务必须可正常启动。每个脚本都会以--listen 127.0.0.1 --port $PORT启动服务,并通过curl -s http://127.0.0.1:$PORT/轮询最多 60 秒等待就绪;超时则打印日志尾部并退出。

此外仓库提供了一个辅助工具 tests/restart_test_server.sh:bash restart_test_server.sh [PORT](默认 8188)会先pkill现有python.*main.py进程再重启测试服务器,并输出到/tmp/comfyui_test_${PORT}.log,适合手动调试时快速拉起服务。

二、7 个测试脚本的端口、规模与覆盖点

7 个脚本各占一个端口,从 tests/README.md 与脚本源码可汇总为如下结构(测试数量以脚本实际用例与 tests/README.md 的统计口径为准):

测试脚本端口用例数验证目标
test_encoding.sh819815UTF-8 多语言编码支持
test_error_handling.sh819710错误场景的优雅处理
test_edge_cases.sh819620边界条件与特殊字符
test_deep_nesting.sh8194177 层传递式展开、深度无关匹配
test_ondemand_loading.sh81938按需惰性加载与缓存上限
test_config_quotes.sh81925配置文件中路径引号处理
test_dynamic_prompts_full.sh818811动态提示词全功能统计验证

2.1 test_encoding.sh(15 个用例,端口 8198)

验证多语言文本在通配符系统中的完整保真:韩文 Hangul、Emoji、中文、阿拉伯文 RTL、数学/货币符号、混合多语言,以及 UTF-8 字符出现在动态提示词、量词(quantifier)、多选(multi-select)语法中的情况。

其判定函数 test_encoding() 通过POST /impact/wildcards发起替换请求,然后检查返回结果中是否包含非 ASCII 字节:

RESULT=$(curl -s -X POST http://127.0.0.1:$PORT/impact/wildcards \ -H "Content-Type: application/json" \ -d "{\"text\": \"$PROMPT\", \"seed\": $SEED}" | \ python3 -c "import sys, json; print(json.load(sys.stdin).get('text','ERROR'))" 2>/dev/null || echo "ERROR") # 结果中包含 [\x80-\xFF] 字节范围则 PASS:UTF-8 字符被保留 if echo "$RESULT" | grep -qP '[\x80-\xFF]'; then echo "Status: PASS - UTF-8 characters preserved"

15 个用例中值得关注的提示词样例(摘自脚本):

用例提示词考察点
01__아름다운색__韩文文件名通配符
03{붉은\|하얀\|노란} __아름다운색__韩文动态提示词 + 通配符组合
06{🌸\|🌺\|🌼\|🌻\|🌷}Emoji 动态选项
08Price: {\$\|€\|£\|¥\|₩} 100货币符号选项
123#__아름다운색__量词语法下的韩文
13{2\$\$, \$\$__아름다운색__\|장미\|벚꽃}多选取 2 项 +$$展开通配符
14{5::🌸\|3::장미\|2::花}加权选择(weight::option)混合多语言

2.2 test_error_handling.sh(10 个用例,端口 8197)

覆盖:不存在的通配符引用、循环引用检测(A→B→A,100 次迭代上限防止死循环)、畸形语法、深嵌套不崩溃、多重循环引用。测试样本的约定记录在 tests/wildcards/samples/README.md:例如test_circular_a.txt与test_circular_b.txt互相引用,期望系统检测环并按上限截断而不是挂起;引用__nonexistent_wildcard__时系统应优雅降级而非崩溃。

2.3 test_edge_cases.sh(20 个用例,端口 8196)

覆盖边界条件:空行/纯空白行过滤、超 1000 字符的超长行、特殊字符原样保留、大小写不敏感匹配、#注释行过滤、模式匹配(__*/name__)、量词(N#__wildcard__)以及复杂语法组合。样本文件约定见 samples README 中对test_edge_empty_lines.txt、test_edge_long_lines.txt、test_edge_special_chars.txt(含正则特殊字符、引号、HTML 转义字符)等的描述。

2.4 test_deep_nesting.sh(17 个用例,端口 8194)

验证传递式通配符展开:test_nesting_level1.txt引用 level2,level2 引用 level3……直到 level7 给出最终选项,即访问__test_nesting_level1__触发 7 层展开,最终结果必须来自 level7。用例还包括各深度(1–7 层)单独访问、混合深度组合、嵌套 + 量词/多选/加权选择,以及深度无关模式匹配__*/name__(匹配任意目录层级下同名的通配符)。

2.5 test_ondemand_loading.sh(8 个用例,端口 8193)

这是与源码中 LazyWildcardLoader 直接对应的套件。该脚本的独特之处在于:

  • 每次测试修改wildcard_cache_limit_mb后重启服务器,验证不同缓存上限下的加载策略:1MB(启用 on-demand)、10MB(渐进加载)、100MB(eager 全量缓存)、0.5MB(激进惰性)、50MB(默认均衡模式)、25MB 边界;
  • 运行时在/tmp/ondemand_test_samples动态生成 50 个各含 100 行选项的大样本文件、韩文样本与 3 级嵌套目录样本;
  • 断言除"返回非 ERROR 文本"外,还会调用GET /impact/wildcards/list/loaded统计实际已加载进内存的通配符数量:
# 获取已加载通配符数量 LOADED_COUNT=$(curl -s http://127.0.0.1:$PORT/impact/wildcards/list/loaded 2>/dev/null | \ python3 -c "import sys, json; print(len(json.load(sys.stdin).get('data',[])))" 2>/dev/null || echo "0")

对应端点在 modules/impact/impact_server.py 中实现,返回体含data(已加载列表)、on_demand_mode(是否处于按需模式)与total_available(可发现的通配符总数)三个字段——从源码结构看,这正是测试"小缓存下只加载被访问过的文件"这一行为的关键观测口。

2.6 test_config_quotes.sh(5 个用例,端口 8192)

验证impact-pack.ini中custom_wildcards路径的引号处理:无引号、双引号、单引号、带空格路径、绝对路径。脚本每轮把不同形态的路径写进配置并重启服务器(见 test_config_format()),通过判据是返回文本既非 ERROR 且不再包含未展开的__残留:

if [ "$RESULT" != "ERROR" ] && [ -n "$RESULT" ] && ! echo "$RESULT" | grep -q "__"; then echo "Status: PASS - Path correctly handled"

其实现依据在 modules/impact/config.py:配置加载时执行custom_wildcards_path = default_conf.get('custom_wildcards', '').strip('\'"')剥离首尾引号;若路径不存在则回退到插件内置的custom_wildcards/目录并打印告警。

2.7 test_dynamic_prompts_full.sh(11 个用例,端口 8188)

这是唯一不自行拉起服务器的脚本:它要求端口 8188 上已有 ComfyUI 服务在运行,否则提示手动启动(脚本 tests/test_dynamic_prompts_full.sh):

# Check server if ! curl -s http://127.0.0.1:$PORT/ > /dev/null 2>&1; then echo "Server not running on port $PORT" echo "Start server with: cd /mnt/teratera/git/ComfyUI && bash run.sh --listen 127.0.0.1 --port $PORT" exit 1 fi

它同时把全部输出tee到/tmp/dynamic_prompt_full_validation.log。覆盖点分为三组:

  • Multiselect(4 个):N$$语法选取 2 项、3 项、单项、最大项,含分隔符校验;
  • Weighted Selection(5 个):10:1 权重比、等权、极端偏斜、多级权重、默认混合;
  • Basic Selection(2 个):简单随机选择、嵌套选择;
  • 每个用例执行100+ 次迭代做统计分布验证,检查重复项检测、选项数量与分隔符正确性。

三、测试基础设施的共性约定

RUN_ALL_TESTS.md的 "Test Summary" 一节对每个套件声明的五项承诺,在脚本源码中一一对应(以 tests/test_encoding.sh 为样本):

声明实现
专属端口启动独立 ComfyUI 服务PORT=819x+bash run.sh --listen 127.0.0.1 --port $PORT > $LOG_FILE 2>&1 &
配置测试通配符路径生成impact-pack.ini,写入custom_wildcards = $IMPACT_DIR/tests/wildcards/samples、wildcard_cache_limit_mb = 50、dependency_version = 24、mmdet_skip = True、sam_editor_cpu = False、sam_editor_model = sam_vit_h_4b8939.pth、disable_gpu_opencv = True
运行测试用例封装的test_*()函数逐条curl调用
校验结果按套件定制:UTF-8 字节检测 / 无__残留检测 / 非 ERROR 检测 / 加载数量统计
自动清理trap cleanup EXIT:pkill -f "python.*main.py.*--port $PORT"并rm -f "$CONFIG_FILE"

另外两点实操细节:

  • 启动前先pkill同端口残留进程并sleep 2,避免端口占用;
  • 服务器就绪判定是 60 秒内curl http://127.0.0.1:$PORT/成功;失败时打印tail -20日志便于定位启动错误。

四、预期结果与日志分析

文档声明全部 86 个测试应通过(100% 通过率)。7 份日志固定写入/tmp/:

套件日志文件
Encoding/tmp/encoding_test.log
Error Handling/tmp/error_handling_test.log
Edge Cases/tmp/edge_cases_test.log
Deep Nesting/tmp/deep_nesting_test.log
On-Demand Loading/tmp/ondemand_test.log
Config Quotes/tmp/config_quotes_test.log
Dynamic Prompts Full/tmp/dynamic_prompt_full_validation.log

失败时的排查路径:各脚本在 FAIL 分支都会给出提示(如 config quotes 套件会grep -i "custom_wildcards\|wildcard" "$LOG_FILE" | tail -5从服务器日志中提取相关行)。服务器日志记录了 Impact Pack 插件的加载告警(例如 modules/impact/config.py 中路径缺失时的custom_wildcards path not found警告),因此先看/tmp/*_test.log中的 FAIL 详情,再翻服务器日志定位插件侧错误,是标准的排障顺序。

五、测试背后的 API 与源码实现

5.1 测试打到的 HTTP 端点

所有套件统一使用 Impact Pack 在 modules/impact/impact_server.py 注册的三个端点:

  • POST /impact/wildcards:请求体为{"text": "...", "seed": N},服务端执行impact.wildcards.process(data['text'], data.get('seed', None))后返回{"text": 展开结果}。这是全部 7 个套件的被测主体。传入seed意味着同一种子下结果应可复现——samples README 也将 "Demonstrate deterministic behavior with same seed" 列为预期行为之一。
  • GET /impact/wildcards/list/loaded:返回已加载通配符列表、on_demand_mode标志与total_available总数,被 on-demand 套件用于观测渐进加载。
  • GET /impact/wildcards/refresh:调用impact.wildcards.wildcard_load()重新加载,可用于修改tests/wildcards/samples/下文件后刷新缓存。

5.2 核心展开算法(wildcards.py)

测试验证的行为全部落在 modules/impact/wildcards.py 的process(text, seed)中(实现入口):

  1. 种子初始化:random.seed(seed)与np.random.default_rng(seed)双通道初始化,保证加权选择、多项选取在同一 seed 下确定性可复现——这解释了动态提示词套件能做 100+ 次迭代的统计分布验证。

  2. 循环引用防护:展开主循环硬编码 replace_depth = 100:

    replace_depth = 100 stop_unwrap = False while not stop_unwrap and replace_depth > 1: replace_depth -= 1 # prevent infinite loop

    每轮先做量词展开(N#__keyword__用正则 RE_WildCardQuantifier 匹配后重复 keyword N 次),再做replace_options({...}动态提示词)与replace_wildcard(__...__通配符)两个 pass;两类替换都不再发生时stop_unwrap退出。error handling 套件验证的"100 次迭代上限防死循环"正是这一机制。

  3. 加权与多选:{weight::option}的权重在前端被解析为normalized_probabilities(实现),多选通过random_gen.choice(..., replace=False)无放回抽样;N$$/N-M$$前缀指定抽取数量,$$后可跟通配符路径展开为选项池。dynamic prompts 套件的统计验证正是针对这段逻辑。

  4. 深度无关模式匹配:__*/name__语法在 replace_wildcard 内部 特判——遍历所有 key,凡key == base_name、key 以 /base_name 结尾、key 以 base_name/ 开头或含 /base_name/者,其选项并入同一候选池随机抽取。deep nesting 套件的__*/test_pattern_match__用例即验证此路径。

5.3 On-demand 加载与缓存上限

ondemand 套件的行为依据在 wildcard_load() 的文档与实现:

  • 启动时调用 calculate_directory_size() 统计custom_wildcards目录下.txt/.yaml/.yml文件总大小(支持提前终止以加速判定);
  • 总大小< 上限:全量缓存模式(full cache),所有数据进内存,/list/loaded等价于全量列表;
  • 总大小≥ 上限:on-demand 模式,scan_wildcard_metadata()只登记"key → 文件路径"元数据(实现),实际数据由 LazyWildcardLoader 代理——它实现了__getitem__/__iter__/__len__/__contains__等 list 接口,首次访问时才带双重检查锁读取文件。这也解释了为什么 0.5MB 激进缓存档位下,list/loaded返回的数量远小于样本总数,而展开结果仍然正确。
  • 一个源码中明确标注的限制:YAML 通配符必须预加载,因为其 key 嵌在文件内容里而非文件路径中(TXT 的 key 即相对路径)。
  • 文件读取的编码策略与 encoding 套件直接相关:LazyWildcardLoader._load_txt() 先按ISO-8859-1读取,遇到UnicodeDecodeError再回退UTF-8 + errors="ignore";同时过滤空行与#注释行——edge cases 套件中"注释行过滤、空行忽略"的用例即验证此清洗逻辑。

wildcard_cache_limit_mb的解析同样在 modules/impact/config.py:非法值会打 warning 并回退默认50MB;该配置正是 ondemand 套件每轮改写impact-pack.ini的字段。

六、实操要点与复用建议

  1. 路径适配是第一步:7 个脚本中COMFYUI_DIR="/mnt/teratera/git/ComfyUI"均为硬编码,移植到本地环境时需逐一替换;IMPACT_DIR/CONFIG_FILE均按脚本位置自动推导,无需改动。

  2. 端口互斥:8188/8192/8193/8194/8196/8197/8198 已被测试套件占用(8188 通常也是 ComfyUI 默认端口),并行跑多套件前先确认端口空闲,或按RUN_ALL_TESTS.md的&&串行方式顺序执行。

  3. 配置文件生命周期:每个脚本在插件根目录写入impact-pack.ini,退出时删除。若测试中途被Ctrl-C打断,trap cleanup EXIT仍会执行清理;手动复测前确认该文件不存在,避免上轮配置(尤其是不同的wildcard_cache_limit_mb)残留。

  4. 单条用例可脱离脚本复现:samples README 给出了标准的 curl 复现方式,例如验证 7 层嵌套:

    curl -X POST http://127.0.0.1:8188/impact/wildcards \ -H "Content-Type: application/json" \ -d '{"text": "__test_nesting_level1__", "seed": 42}'

    量词、循环引用(__test_circular_a__)、模式匹配(__*/test_pattern_match__)等场景同理,方便在 CI 之外做单点调试。

  5. 扩展测试样本:新增通配符测试文件放入tests/wildcards/samples/后,可通过GET /impact/wildcards/refresh热加载,无需重启服务器(on-demand 模式下新文件也会被scan/动态查找机制发现)。

小结

RUN_ALL_TESTS.md定义的这套 7 脚本、86 用例的回归体系,把 Impact Pack 通配符系统的五个关键质量维度——多语言编码保真、错误优雅降级、边界条件、深层传递展开、缓存受控的按需加载——全部锚定在可观测的 HTTP 行为上:POST /impact/wildcards的展开结果、GET /impact/wildcards/list/loaded的加载量、/tmp/下的服务器日志。结合 modules/impact/wildcards.py 中 100 次迭代防护、LazyWildcardLoader双重检查锁、__*/name__深度无关匹配与 50MB 默认缓存上限等源码实现,可以完整回答"每个测试为什么这样判定"。对于贡献者而言,跑通全部 7 个套件并保持 100% 通过,是修改 wildcard 相关代码后的基本验收动作。

延伸阅读(仓库内文档):tests/README.md(套件细节与状态清单)、tests/wildcards/samples/README.md(测试样本约定与 curl 示例)、docs/wildcards/WILDCARD_SYSTEM_PRD.md、docs/wildcards/WILDCARD_SYSTEM_DESIGN.md、docs/wildcards/WILDCARD_TESTING_GUIDE.md。

  • AI 应用
  • 计算机视觉
  • 图像处理

【免费下载链接】ComfyUI-Impact-Pack

Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more.

项目地址:https://gitcode.com/gh_mirrors/co/ComfyUI-Impact-Pack
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询