执行摘要
- 一句话:verifiers 三个测试按 example 目录归档,纯移动无内容变更
- 推荐动作:不值得精读,属于低风险、高确定性的测试组织维护。值得留意的是其确立的目录镜像原则——“
tests/fast/ 下的目录应镜像被测代码的包结构”,以及 PR body 中展示的“纯移动安全性论证”模板(包路径访问、无 __file__、无外部引用、CI list-only 对比),可作为后续同类测试迁移 PR 的参照。
功能与动机
PR body 明确指出:tests/fast/rollout/ 镜像 miles/rollout/,其中其他测试(test_fully_async_rollout.py、test_checkpoint_eval.py、generate_hub/、rm_hub/、session/)都覆盖 miles 自有 rollout 代码,而 verifiers 的两个测试是仅有的覆盖 example 的文件;同时 launcher 测试松散放在 experimental/ 根目录,与仓库惯例(swe_agent_harbor_docker/、p2p_weight_transfer/ 均有独立目录)不符。作者还特别论证了安全性:三个测试全部通过包路径 examples.experimental.verifiers... 访问被测对象,无需 conftest 或 sys.path 引导,且无文件引用 __file__,仓库内也无其他文件引用旧路径。
实现拆解
- 确定目标目录:新建
tests/fast/examples/experimental/verifiers/ 目录,并新增空 __init__.py,使该目录成为可导入的测试包,与 swe_agent_harbor_docker、p2p_weight_transfer 等既有 example 测试目录保持一致。
- 迁移两个 rollout 相关测试:将
tests/fast/rollout/test_verifiers_rollout.py 与 tests/fast/rollout/test_verifiers_runtime.py 原样移动到新目录,文件名不变。这两个文件均导入 examples.experimental.verifiers.verifiers_rollout,属于 example 测试而非 miles 自有 rollout 代码测试,移除后 tests/fast/rollout/ 恢复为纯镜像 miles/rollout/ 的职责。
- 重命名并迁移 launcher 测试:将
tests/fast/examples/experimental/test_verifiers_run.py 移动到新目录并重命名为 test_run.py,去掉 verifiers 冗余前缀,使测试文件名与 run.py 对应,遵循 p2p_weight_transfer 的既有命名先例。
- 验证 CI 收集结果:PR body 使用
run_suite.py --hw cpu --suite stage-a-cpu --list-only 对比,确认套件收集仅差三个测试名,且每个仍为隐式 CPU entry,无需改动 tests/ci/run_suite.py 或任意 CI workflow 配置。
关键文件:
tests/fast/examples/experimental/verifiers/test_run.py(模块 启动器;类别 test;类型 rename-or-move;符号 test_adapter_and_ray_runtime_use_the_same_legacy_flag, _rollout_config, LEGACY_ROLLOUT_ENV): launcher 测试,从 experimental/ 根目录移入并去掉 verifiers 冗余前缀,重命名后与 run.py 对应,是最能体现本 PR 组织意图的文件。
tests/fast/examples/experimental/verifiers/test_verifiers_rollout.py(模块 rollout;类别 test;类型 rename-or-move;符号 VerifiersRolloutFn, MilesSGLangTransport, trace_to_samples, _validate_args): 覆盖 VerifiersRolloutFn 及 trace 转换逻辑的测试,从 tests/fast/rollout/ 移入,是本次迁移的核心对象之一。
tests/fast/examples/experimental/verifiers/test_verifiers_runtime.py(模块 运行时;类别 test;类型 rename-or-move;符号 test_minimal_env_config_uses_the_v1_environment_contract): 验证 verifiers v1 runtime 契约(EnvConfig、Environment、renderer 等)的测试,同样从 tests/fast/rollout/ 移入,使该目录不再混入 example 测试。
tests/fast/examples/experimental/verifiers/__init__.py(模块 测试包;类别 test;类型 test-coverage): 新增空包标记文件,使新目录成为可导入的测试包,与仓库其他 example 测试目录保持一致。
关键符号:test_adapter_and_ray_runtime_use_the_same_legacy_flag, _rollout_config, test_minimal_env_config_uses_the_v1_environment_contract
关键源码片段
tests/fast/examples/experimental/verifiers/test_run.py
launcher 测试,从 experimental/ 根目录移入并去掉 verifiers 冗余前缀,重命名后与 run.py 对应,是最能体现本 PR 组织意图的文件。
import json
import shlex
import pytest
from examples.experimental.verifiers import run
from tests.fast.utils.command_recorder import record_commands
import miles.utils.external_utils.command_utils as U
LEGACY_ROLLOUT_ENV = "MILES_USE_LEGACY_ROLLOUT_V1"
def _rollout_config(submit_command: str) -> tuple[str, dict[str, str]]:
# 从最终提交给 Ray 的 submit 命令中反向解析出 rollout 函数路径与 runtime 环境变量,
# 用于断言 adapter 侧与 Ray runtime 侧使用的是同一个 legacy 开关。
argv = shlex.split(submit_command)
rollout_fn = argv[argv.index("--rollout-function-path") + 1]
runtime_env_arg = next(arg for arg in argv if arg.startswith("--runtime-env-json="))
runtime_env = json.loads(runtime_env_arg.split("=", 1)[1])["env_vars"]
return rollout_fn, runtime_env
@pytest.mark.parametrize(
("ambient_value", "extra_env_vars", "expected_rollout_fn", "expected_runtime_value"),
[
(None, "", "verifiers_rollout.VerifiersRolloutFn", None),
("1", "", "verifiers_rollout.generate_rollout", "1"),
("0", f"{LEGACY_ROLLOUT_ENV}=1", "verifiers_rollout.generate_rollout", "1"),
("1", f"{LEGACY_ROLLOUT_ENV}=0", "verifiers_rollout.VerifiersRolloutFn", "0"),
],
)
def test_adapter_and_ray_runtime_use_the_same_legacy_flag(
monkeypatch,
tmp_path,
ambient_value,
extra_env_vars,
expected_rollout_fn,
expected_runtime_value,
):
# 四种环境变量组合交叉验证:无设置、仅环境变量、环境变量与 extra_env_vars 冲突等场景,
# 期望最终选中的 rollout 函数与 runtime 环境变量始终一致,避免 adapter 与 runtime 行为分叉。
commands = record_commands(monkeypatch)
monkeypatch.setattr(U, "check_has_nvlink", lambda: False)
monkeypatch.setenv("MILES_SCRIPT_EXTERNAL_RAY", "1")
monkeypatch.setenv("MILES_SCRIPT_ENABLE_RAY_SUBMIT", "1")
monkeypatch.setenv("MASTER_ADDR", "127.0.0.1")
monkeypatch.delenv("RAY_ADDRESS", raising=False)
monkeypatch.delenv("NCCL_NVLS_ENABLE", raising=False)
if ambient_value is None:
monkeypatch.delenv(LEGACY_ROLLOUT_ENV, raising=False)
else:
monkeypatch.setenv(LEGACY_ROLLOUT_ENV, ambient_value)
# 构造最小 ScriptArgs 并执行 run.py 的入口,monkeypatch 会录制最终提交的命令。
run.execute(
run.ScriptArgs(
verifiers_config=str(tmp_path / "verifiers.toml"),
extra_env_vars=extra_env_vars,
)
)
rollout_fn, runtime_env = _rollout_config(commands[-1])
assert rollout_fn == expected_rollout_fn
if expected_runtime_value is None:
assert LEGACY_ROLLOUT_ENV not in runtime_env
else:
assert runtime_env[LEGACY_ROLLOUT_ENV] == expected_runtime_value
评论区精华
该 PR 的 review 讨论较少且无争议,核心是 claude[bot] 的自动审核与人工批准。
风险与影响
- 风险:技术风险极低。变更纯为文件移动与重命名,无逻辑改动,四个文件的
additions 与 deletions 均为 0。作者已主动验证三点安全性:旧路径无外部引用、无 __file__ 依赖、均通过包路径导入。潜在残余风险仅在于若仓库外部工具(不在本仓库内的脚本)硬编码旧测试路径,可能在收集时遗漏用例,但这不属于仓库内可见风险。另外,test_run.py 重命名后若有人按旧名称 test_verifiers_run.py 在 CI 配置中显式引用会失效,但 PR 已确认 tests/ci 无此类引用。
- 影响:影响范围限于测试代码组织层面:
tests/fast/rollout/ 目录的职责回归纯粹(仅覆盖 miles 自有 rollout 代码),verifiers example 的测试集中在独立目录下,降低后续维护者寻找用例的心智负担。对用户功能无影响,对 CI 收集结果仅三个测试名的路径变化,无执行行为变化。对团队而言,确立了“example 测试按 example 路径归档”的组织惯例,为后续 swe_agent_harbor、p2p_weight_transfer 之外的 example 测试提供先例。
- 风险标记:纯测试移动无逻辑变更, 旧路径无外部引用已确认, 目录镜像原则可复用
关联脉络
- PR #2558 (作者在 PR body 中提及的前置 PR,已合并): 本 PR 基于 #2558 的移动成果 rebase 到 main,将相邻 suites 移入
tests/fast/ 下的对应目录,本 PR 是其后续整理。
- PR #2577 fix: make the Verifiers E2E self-contained: 后续对 verifiers 测试的配套修复,涉及
examples/experimental/verifiers/verifiers_rollout.py 与 tests/fast/rollout/test_verifiers_rollout.py(在 2561 合并前路径),与本 PR 属同一 verifiers 测试工作线。
- PR #2560 (PR body 中提到的后续工作项): PR body 明确声明 verifiers e2e 固定 legacy rollout 路径、默认
VerifiersRolloutFn 无端到端覆盖的问题属于 #2560,与本 PR 同源但刻意拆分,避免在纯移动 PR 中混入行为变更。
参与讨论