Skip to content
Go back

用 Meziantou.ShardedTest 加速 .NET CI 测试分片

CI 里测试慢是个常见的痛点。一个项目测试越来越多,单次 dotnet test 要跑十几分钟,PR 等反馈的时间也跟着拉长。解决这个问题的一个思路是测试分片(test sharding):把整个测试集切成几份,每份在一个独立的 CI Job 上并行执行,总耗时降到最慢那个分片的时间。

Meziantou.ShardedTest 是 Gérald Barré 写的一个 .NET 全局工具,专门做这件事。它自动完成测试枚举、分片分配、过滤参数生成,你只需要告诉它分片序号和总分片数,它帮你运行对应那一份测试。

封面:测试分片并行执行示意

工具做了什么

从用法看,sharded-test 的执行流程很清晰:

  1. 调用 dotnet test --list-tests 枚举全部测试(仍可搭配 --filter 限定范围)
  2. 对测试列表做确定性排序
  3. --shard-index--total-shards 选出当前分片对应的那批测试
  4. dotnet test 加上相应的过滤参数运行这批测试,其他参数原样透传

一个细节:当测试数量很多时,过滤参数可能超出命令行长度限制。工具会自动把这种情况拆成多次 dotnet test 调用,不需要手动处理。

分片结果的确定性依赖 dotnet test --list-tests 输出的稳定性——只要测试程序集和框架版本不变,枚举结果就是固定的。

分片和框架内并行有什么区别

两者经常被混淆,但解决的层面不同:

两者可以叠加使用。比如开 3 个分片,每个分片内部再开并行,这样既减少了 CI 总 Job 数,又利用了单机的多核能力。

什么情况下值得用分片

适合的场景:

不太适合的场景:

原文也特别提到:分片主要对 CPU 密集型测试有明显提速效果,IO 密集型测试更适合在框架层面做并行。引入分片前先测量一次当前的实际瓶颈,再决定要不要做。

成本与局限

并行分片会增加 CI Job 数量,相应地会增加计算成本。具体要根据平台的并发配额和预算来决定开几个分片。

对于 IO 密集型测试,分片带来的加速可能有限,在这种情况下框架内并行可能更有效。实际效果建议实测对比,不要假设分片一定有效。

安装和基本用法

安装为全局工具:

dotnet tool install --global Meziantou.ShardedTest

在本地或 CI 里运行一个分片:

sharded-test --shard-index 1 --total-shards 4 tests/MyTests.csproj --configuration Release

--shard-index 从 1 开始计数,--total-shards 是总分片数,后面可以跟任何 dotnet test 支持的参数。

GitHub Actions 配置

用 matrix 策略拉起多个并行 Job,每个 Job 运行一个分片:

on:
  push:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shard-index: [1, 2, 3]
    steps:
      - uses: actions/checkout@v4
      - name: Install sharded-test
        run: dotnet tool install --global Meziantou.ShardedTest
      - name: Run tests (shard ${{ matrix.shard-index }}/3)
        run: sharded-test --shard-index ${{ matrix.shard-index }} --total-shards 3 tests/MyTests.csproj

fail-fast: false 确保一个分片失败时其他分片不会被取消,能看到全部失败信息。

GitLab CI 配置

GitLab 用 parallel 关键字自动拉起多个 Job,并设置 CI_NODE_INDEXCI_NODE_TOTAL 环境变量。sharded-test 会自动读取这两个变量作为默认值,不需要显式传 --shard-index--total-shards

stages:
  - test

test:
  stage: test
  parallel: 3
  before_script:
    - dotnet tool install --global Meziantou.ShardedTest
    - export PATH="$PATH:$HOME/.dotnet/tools"
  script:
    - sharded-test tests/MyTests.csproj

GitLab 的这个集成让配置更简洁,不需要手动绑定 Job 序号。

小结

Meziantou.ShardedTest 做的事情并不复杂:枚举测试、确定性分组、按分片运行。但它把这个流程封装成一个好用的命令,省去了自己写脚本处理测试过滤、命令行长度溢出等细节。如果你的 .NET CI 测试阶段已经成为反馈瓶颈,这个工具值得试一试。

参考


Tags


Previous

Copilot Coding Agent 在 dotnet/runtime 的 10 个月:878 个 PR 告诉我们什么

Next

解决 Ghostty SSH 连接时 xterm-ghostty unknown terminal 报错