mcpField
M
mcore-testing

mcore-testing

github.com/nvidia测试与质量3.8k1.8k 次安装今天更新
代码仓库

关于 mcore-testing

mcore-testing 是面向 NVIDIA/Megatron-LM 贡献者的测试指南,说明分布式单元测试、功能测试和 CI 配方的操作方式,并介绍如何保留测试记录以便重新启用。

主要功能

  1. 01分布式 pytest 单元测试流程
  2. 02端到端功能测试配置
  3. 03YAML 配方结构与控制
  4. 04易失败测试标记和跳过规则
  5. 05CI 重试与产物位置

适用场景

  1. 01按 CI 环境在本地运行单元测试
  2. 02添加功能测试和基准值
  3. 03暂时停用测试并保留配方

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nvidia/skills --skill mcore-testing

安装后在 Claude Code 中输入/mcore-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

BENCHMARK.md
skill-card.md
skill.oms.sig
evals/
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 下查找测试数据,若缺失则尝试下载。在规范容器之外运行时,请手动提供数据,或跳过依赖数据的测试。

添加单元测试

  1. 创建 tests/unit_tests/<category>/test_<name>.py。
  2. 使用 tests/unit_tests/conftest.py 中的 fixtures。
  3. 根据需要应用标记:
    • @pytest.mark.internal — 在 legacy 标签下跳过
    • @pytest.mark.flaky_in_dev — 在 dev 环境中跳过(CI 默认环境;使用此标记可禁用不稳定测试,同时不阻塞标准流水线)
    • @pytest.mark.flaky — 在 lts 环境中跳过
    • @pytest.mark.experimental — 仅适用于 latest 标签
  4. 在本地验证(参见上文“在本地运行单元测试”)。
  5. 如果测试需要专用 CI 分桶,请在 tests/test_utils/recipes/h100/unit-tests.yaml 中添加一个条目。

添加功能/集成测试

  1. 创建 tests/functional_tests/test_cases/<model>/<test_name>/。

  2. 编写 model_config.yaml,包含 MODEL_ARGS、ENV_VARS 和 TEST_TYPE。

  3. 在 tests/test_utils/recipes/h100/ 下添加 YAML 配方(如有需要,也在 gb200/ 下添加)。必填字段:scope、environment、platform、n_repeat、 time_limit。

  4. 推送 PR,添加标签 "Run functional tests" 以触发完整运行。

  5. 成功运行后,下载黄金值:

    python tests/test_utils/python_scripts/download_golden_values.py \
      --source github --pipeline-id <run-id>
    
  6. 提交下载的黄金值。


常见问题

问题原因修复方法
测试在本地通过,但在 CI 中失败环境或数据路径不同检查 DATA_PATH、DATA_CACHE_PATH 和 environment 标签(dev 与 lts)
代码更改后黄金值不匹配数值回归在干净运行后,通过 download_golden_values.py 下载新的黄金值
未触发 cicd-integration-tests-gb200GB200 作业要求维护者身份请维护者触发,或添加 Run functional tests 标签

评论

支持 Markdown