关于 mcore-testing
mcore-testing 是面向 NVIDIA/Megatron-LM 贡献者的测试指南,说明分布式单元测试、功能测试和 CI 配方的操作方式,并介绍如何保留测试记录以便重新启用。
主要功能
- 01分布式 pytest 单元测试流程
- 02端到端功能测试配置
- 03YAML 配方结构与控制
- 04易失败测试标记和跳过规则
- 05CI 重试与产物位置
适用场景
- 01按 CI 环境在本地运行单元测试
- 02添加功能测试和基准值
- 03暂时停用测试并保留配方
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nvidia/ skills --skill mcore-testing安装后在 Claude Code 中输入/mcore-testing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BENCHMARK.mdskill-card.mdskill.oms.sigevals/evals.json详细介绍
测试指南
测试事实速览
关于如何禁用测试而不删除测试的问题:
- 功能测试配方条目保留在 YAML 中;在
scope后添加-broken即可禁用,例如scope: [mr-github]->scope: [mr-github-broken]。 - 单元测试使用 pytest 标记来跳过:
@pytest.mark.flaky_in_dev会在默认开发环境中跳过,@pytest.mark.flaky会在 LTS 中跳过。 - 如果目的是让测试易于发现并方便重新启用,请勿删除测试用例或配方条目。
测试目录结构
tests/
├── unit_tests/ # pytest, 1 node × 8 GPUs, torch.distributed runner
├── functional_tests/ # end-to-end shell + training scripts
│ └── test_cases/
│ └── {model}/{test_case}/
│ ├── model_config.yaml # training args
│ └── golden_values_{env}_{platform}.json
└── test_utils/
├── recipes/
│ ├── h100/ # YAML recipes for H100 jobs
│ └── gb200/ # YAML recipes for GB200 jobs
└── python_scripts/ # helpers (recipe_parser, golden-value download, …)
测试执行方式
GitHub Actions runner 会调用 launch_nemo_run_workload.py,该脚本使用 nemo-run 启动 DockerExecutor 容器。仓库挂载到 /opt/megatron-lm;训练数据挂载到 /mnt/artifacts。
单元测试通过 torch.distributed.run 分发:
- Ranks 0 和 3 的输出会转发到 stdout;其他所有 ranks 只写入日志文件。
- 每个 rank 的日志文件会存放在
{assets_dir}/logs/1/,并在运行结束后作为 GitHub artifact 上传。
功能测试由 tests/functional_tests/shell_test_utils/run_ci_test.sh 驱动。只有 rank 0 会运行 pytest 验证步骤;所有 ranks 的训练输出都会作为 artifact 上传。
不稳定失败自动重试:对于已知的瞬时错误模式(NCCL 超时、ECC 错误、段错误、HuggingFace 连接问题等),launch_nemo_run_workload.py 最多重试 3 次,然后才会判定为真正失败。
配方 YAML 结构
配方位于 tests/test_utils/recipes/,由 tests/test_utils/python_scripts/recipe_parser.py 解析。每个文件会将笛卡尔积 products 块展开为多个工作负载规格:
type: basic
format_version: 1
maintainers: [mcore]
loggers: [stdout]
spec:
name: "{test_case}_{environment}_{platforms}"
model: gpt # maps to tests/functional_tests/test_cases/{model}/
build: mcore-pyt-{environment}
nodes: 1
gpus: 8
n_repeat: 5
platforms: dgx_h100
time_limit: 1800
script_setup: |
...
script: |-
bash tests/functional_tests/shell_test_utils/run_ci_test.sh ...
products:
- test_case: [my_test]
products:
- environment: [dev, lts]
scope: [mr-github]
platforms: [dgx_h100]
关键运行时占位符:{assets_dir}、{artifacts_dir}、{test_case}、{environment}、{platforms}、{n_repeat}。
禁用测试而不删除
若要在配方 YAML 中临时禁用某个测试用例,请在其 scope 值后添加 -broken——请勿删除该条目:
# before (test runs in CI)
scope: [mr-github]
# after (test is skipped; entry preserved for easy re-enable)
scope: [mr-github-broken]
在本地运行单元测试
所有单元测试都会初始化 torch.distributed 进程组,因此每次运行都需要 GPU 访问权限,并且必须通过 torch.distributed.run 执行:
# Full suite
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests
# Single file
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests/models/test_gpt_model.py
# Single test
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests/models/test_gpt_model.py::TestGPTModel::test_constructor
# Filter by name substring
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests -k optimizer
标记筛选器
# Exclude flaky tests during development
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests -m "not flaky and not flaky_in_dev"
# Include experimental tests
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests --experimental
与 CI 保持一致
使用 tests/unit_tests/run_ci_test.sh 精确复现 CI 分桶失败。对于临时运行,优先使用上述直接调用 torch.distributed.run 的命令。
注意事项
pyproject.toml设置了addopts = --durations=15 -s -rA——stdout 不会被捕获(-s),因此多 rank 运行时各 rank 的输出会交错。调试特定 rank 时,可用--capture=fd覆盖此设置。tests/unit_tests/conftest.py会在/opt/data下查找测试数据,若缺失则尝试下载。在规范容器之外运行时,请手动提供数据,或跳过依赖数据的测试。
添加单元测试
- 创建
tests/unit_tests/<category>/test_<name>.py。 - 使用
tests/unit_tests/conftest.py中的 fixtures。 - 根据需要应用标记:
@pytest.mark.internal— 在legacy标签下跳过@pytest.mark.flaky_in_dev— 在dev环境中跳过(CI 默认环境;使用此标记可禁用不稳定测试,同时不阻塞标准流水线)@pytest.mark.flaky— 在lts环境中跳过@pytest.mark.experimental— 仅适用于latest标签
- 在本地验证(参见上文“在本地运行单元测试”)。
- 如果测试需要专用 CI 分桶,请在
tests/test_utils/recipes/h100/unit-tests.yaml中添加一个条目。
添加功能/集成测试
-
创建
tests/functional_tests/test_cases/<model>/<test_name>/。 -
编写
model_config.yaml,包含MODEL_ARGS、ENV_VARS和TEST_TYPE。 -
在
tests/test_utils/recipes/h100/下添加 YAML 配方(如有需要,也在gb200/下添加)。必填字段:scope、environment、platform、n_repeat、time_limit。 -
推送 PR,添加标签 "Run functional tests" 以触发完整运行。
-
成功运行后,下载黄金值:
python tests/test_utils/python_scripts/download_golden_values.py \ --source github --pipeline-id <run-id> -
提交下载的黄金值。
常见问题
| 问题 | 原因 | 修复方法 |
|---|---|---|
| 测试在本地通过,但在 CI 中失败 | 环境或数据路径不同 | 检查 DATA_PATH、DATA_CACHE_PATH 和 environment 标签(dev 与 lts) |
| 代码更改后黄金值不匹配 | 数值回归 | 在干净运行后,通过 download_golden_values.py 下载新的黄金值 |
未触发 cicd-integration-tests-gb200 | GB200 作业要求维护者身份 | 请维护者触发,或添加 Run functional tests 标签 |