Skip to content

[TEST] Key operator-test skipping and selection off the manifest and the run's scope - #1515

Merged
LLMZhangYC merged 3 commits into
tile-ai:example_testfrom
dlaerbinjwy:20260731v1/manifest-scoped-collection-and-routing
Jul 31, 2026
Merged

[TEST] Key operator-test skipping and selection off the manifest and the run's scope#1515
LLMZhangYC merged 3 commits into
tile-ai:example_testfrom
dlaerbinjwy:20260731v1/manifest-scoped-collection-and-routing

Conversation

@dlaerbinjwy

@dlaerbinjwy dlaerbinjwy commented Jul 31, 2026

Copy link
Copy Markdown

背景

算子测试迁移(#1489 / #1497)落地后发现三个问题,共同点是判断依据用错了:该看登记表的地方看了文件名,该看本次运行范围的地方读了整张登记表。

三处修改互相独立,分三个 commit。

# 问题 影响 改在哪
1 四条"判定全量"的规则没有清空 #1489 新加的三个变量,循环外又把它们写回 test_dirs_array 改核心文件时若同时改了已迁移算子,全量 examples 静默缩水成一个目录,CI 仍全绿 ci_cd.yml
2 兜底算子测试读整张登记表,不看本次跑了哪些目录 改一个 example 会把所有已登记的算子测试跑一遍 ci_cd.ymlbench_test.sh
3 find-not -name "test_*.py" 按文件名排除所有测试 未登记的测试谁都不跑;主仓现有三个这样的文件合并后会静默停跑;check-orphans 还会让别人的 PR 直接失败 bench_test.shresolve_operator_tests.py

1. 保证全量运行是全量

detect_changes 的循环里,四条判定全量的规则都是"清空已收集的数组 + break"。#1489 加的 routed_tests / routed_example_dirs / routed_experiment_dirs 不在清理清单里,break 之后仍带着值,循环外的归并把它们写回了 test_dirs_array,于是 test_dirs 从空(= 跑全部)变成了单个目录。

git diff --name-only 按字典序输出,examples/ 永远排在 tilelang/src/requirements*install_ascend.sh 前面,所以算子总是先被收集、再撞上全量规则——必然触发,不是偶发。

改法是把这三个变量加进四处清理清单,与相邻写法一致,没有引入新机制。

 test_dirs_array=()
 experiment_dirs_array=()
 pytest_files_array=()
 pytest_dirs_array=()
+routed_tests=()
+routed_example_dirs=()
+routed_experiment_dirs=()
 break

主仓原有的四条全量规则、examples 增量规则、check_skip_pytest 未做任何修改。


2. 算子测试跟随运行范围

run_examples 末尾补跑已迁移算子测试是必要的(它们的源文件被 runner 全局跳过),但不该无视范围。TEST_DIRS_ARG 本身就是字面的 --dirs a b c(全量时为空串),让 list-tests 认同样的参数即可原样传下去。

-done < <(python ../scripts/ci/resolve_operator_tests.py list-tests)
+done < <(python ../scripts/ci/resolve_operator_tests.py list-tests $TEST_DIRS_ARG $EXPERIMENT_DIRS_ARG)

bench_test.sh 里手工跑覆盖率的那段同样处理,否则 --coverage --dirs foo 会产出"一个目录的 examples + 全部算子"的混口径报告。

list-tests 新增 --dirs / --experiment-dirs:两个都不给是全量;只给一个时另一个视为空集;按根目录下第一层目录匹配(算子可能更深一层,如 examples/tile_kernels/moe/…tile_kernels)。


3. 跳过依据改为登记表

find 按文件名排除 test_*.py 是随迁移加进来的,主仓没有,而且与算子的处理方式不对称——算子查登记表,测试看名字。

改成与算子一致:新增 MIGRATED_TESTS,在 should_skip_python_script 里查一次,然后删掉那两行按名字的排除。四个收集点原本就都经过该函数,无需另加调用。

登记过的测试交给 Pytest,没登记的照旧由 runner 当脚本收集执行——这是登记表出现之前的行为。名字写错的测试也不会再无声消失:它会被当脚本执行,而 runner 要求输出中出现 KERNEL OUTPUT MATCHTEST PASSED!,Pytest 风格的文件什么都不打印,直接判 [FAILED]

check-orphans 随之从报错降级为提示。它原来的理由是"未登记的测试跑不到任何地方",改完之后不再成立;而且登记表是本分支的内部约定,不应该让其他人的 PR 因此失败。


测试

改动前后各跑一次 bash bench_test.sh --coveragedocs/coverage_guide.md 里的原样命令),在一棵 48 条登记生效的树上:

改动前 改动后
退出码 / 用时 / OOM 0 / 44m50s / 0 0 / 45m09s / 0
算子测试 95 passed / 48 files 95 passed / 48 files
收集脚本数 98 98
Pytest 1535 passed, 2 xfailed 1535 passed, 2 xfailed
coverage 数据文件 142 142
coverage.json 28899324 字节 28899324 字节
Python 覆盖率 74.34% 74.34%

coverage.json 字节级相同 —— 不带 --dirs 时覆盖数据无任何变化。

路由决策:抽出 detect_changes 原样跑 29 组改动组合。六种"核心文件 + 已迁移算子"的组合从 test_dirs=[batch_gemm] 恢复为 [];其余 23 组决策不变(新增 example、改未登记算子、只改 testing/python、只改 docs、算子与其测试同改去重成一个、跨两个根目录混合改动等)。

范围过滤:

传入 选中
无参数(全量) 48
--dirs batch_gemm 1
--dirs elementwise(无已登记算子) 0
--dirs tile_kernels(算子在两层子目录) 2
--dirs HISA flash_attention 9
--experiment-dirs cumsum_kda 1

收集与执行:

结果
未登记的测试被收集 0 → 1
已登记的测试混进收集清单(跑两遍) 0
未登记的测试当脚本跑 [PASSED]
名字写错的 Pytest 风格测试当脚本跑 [FAILED]
全量 --skip-pytest 98 脚本 / 98 通过 / 跳过 48 源 + 44 测试 / 重复 0

另:登记表 140 条的源文件在 ascendc_pto 当前 HEAD 上全部存在,合并不会导致 validate 失败。


对其他贡献者的影响

登记表 140 条中目前仅 3 条生效(测试文件已落地),其余 137 条为占位,对应算子仍走原有 runner。

动作 变化
新增 example,或新增 example 及其测试
修改任一未迁移的算子
修改 tilelang/ 等核心文件 无(本 PR 修复后恢复为全量)
修改 testing/python/ 或文档
提交未登记的测试 不再被 check-orphans 拦下,且会被当脚本执行
修改 3 个已迁移算子之一 改由其 Pytest 测试覆盖

需要留意:登记表中列出的算子源文件如被改名或删除,需同步修改 ci/operator_test_manifest.yaml 对应条目,否则 validate 会在 runner 启动时报 source does not exist。修改文件内容不受影响。

Two faults in how the migrated operator tests reach CI, both from the same
oversight: the routing added state the surrounding code does not know about.

The loop that classifies changed files has four rules that decide on a full
run, and each clears what was collected before it. Three arrays added later
were not on that list, so a change to a core file alongside a migrated
operator cleared the directories, kept the operator, and wrote it back after
the loop. A full run then narrowed to that one directory, silently. Since
git diff sorts its output, examples/ always precedes tilelang/, src/,
requirements* and install_ascend.sh, so the operator was always seen first
and the narrowing was not occasional.

The fallback that runs those tests took every registered entry regardless of
what the run was scoped to, so editing one example ran all of them. It now
takes the two arguments the runner just took and means the same by them.
The runner dropped every test_*.py from what it collects. That rule arrived
with the migration and is not how the operators themselves are handled: those
consult the manifest. Three tests already upstream match no entry, and by name
alone they stopped running here while continuing to run in the repository they
came from. Nothing reported it, since a script that is never collected cannot
fail.

Skipping by manifest instead leaves a registered test to Pytest and hands the
rest back to the runner, which is what ran them before any of this. A name
that was meant to match an entry and does not now fails loudly: it is
collected, produces no passing line, and is reported failed.

check-orphans reported that case by refusing to run at all, which is no longer
the situation it describes and was never a condition this repository could
place on other people. It says what it found and lets the run proceed.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the TileLang project.

Please remember to run bash format.sh in the root directory of the project to ensure your changes are properly linted and formatted. This will help ensure your contribution passes the format check.

We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work!

🚀

This block was reading the whole manifest while the examples around it were
narrowed to the directories passed in, so a scoped invocation produced a
report covering one directory of examples and every operator. What that
report measured could not be told from looking at it.

It takes the two options this script already parses and hands them on
unchanged, as the workflow does with the same two.
@dlaerbinjwy dlaerbinjwy changed the title 20260731v1/manifest scoped collection and routing [TEST] Key operator-test skipping and selection off the manifest and the run's scope Jul 31, 2026
@LLMZhangYC
LLMZhangYC merged commit 0b72e3a into tile-ai:example_test Jul 31, 2026
6 checks passed
dlaerbinjwy added a commit to dlaerbinjwy/tilelang-ascend that referenced this pull request Jul 31, 2026
dlaerbinjwy added a commit to dlaerbinjwy/tilelang-ascend that referenced this pull request Jul 31, 2026
dlaerbinjwy added a commit to dlaerbinjwy/tilelang-ascend that referenced this pull request Jul 31, 2026
dlaerbinjwy added a commit to dlaerbinjwy/tilelang-ascend that referenced this pull request Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants