From 64326bda57b22c5e1b2aa51f33fab8cdd76d35f6 Mon Sep 17 00:00:00 2001
From: Peter Trost
Date: Fri, 28 Aug 2026 17:31:00 +0200
Subject: [PATCH 1/2] feat(test): support sharding tests across CI runners
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add `--shard-index` and `--total-shards` to `very_good test` and
`very_good dart test`, so a test suite can be split across multiple CI
runners with a `strategy.matrix`.
The test optimizer already discovers every test file, so sharding is a
partition of that list rather than new machinery. Files are sorted and
dealt out round-robin, which keeps shards balanced by file count and
makes the partition deterministic across machines — `Directory.listSync`
order is filesystem dependent, so without sorting two runners could
disagree and either skip or duplicate tests.
Tests tagged `skip_very_good_optimization` are sharded as well. They run
as standalone files alongside the optimizer entrypoint, so leaving them
unsharded would re-run all of them on every runner.
Each runner generates its own `.test_optimizer.dart` containing only its
slice, so no shard-specific filenames are needed. A shard with no test
files succeeds instead of failing with "No tests were found", so an
oversized matrix does not break the build.
Sharding is rejected with a usage error when combined with
`--min-coverage`, since each shard only exercises a subset of the
codebase and its coverage is not representative of the whole suite, and
when the optimizer is disabled, which sharding depends on.
Closes #1538
Co-Authored-By: Claude Opus 5
---
bricks/test_optimizer/brick.yaml | 8 +
bricks/test_optimizer/hooks/lib/pre_gen.dart | 77 ++++++--
.../hooks/test/pre_gen_test.dart | 139 +++++++++++++++
lib/src/cli/dart_cli.dart | 4 +
lib/src/cli/flutter_cli.dart | 4 +
.../cli/templates/test_optimizer_bundle.dart | 14 +-
lib/src/cli/test_cli_runner.dart | 22 ++-
.../dart/commands/dart_test_command.dart | 50 ++++++
lib/src/commands/test/test.dart | 105 +++++++++++
site/docs/commands/test.md | 44 +++++
test/src/cli/test_cli_runner_test.dart | 105 +++++++++++
.../dart/commands/dart_test_test.dart | 93 ++++++++++
test/src/commands/test/test_test.dart | 166 ++++++++++++++++++
13 files changed, 812 insertions(+), 19 deletions(-)
diff --git a/bricks/test_optimizer/brick.yaml b/bricks/test_optimizer/brick.yaml
index 07aa58c3d..3c2b80b62 100644
--- a/bricks/test_optimizer/brick.yaml
+++ b/bricks/test_optimizer/brick.yaml
@@ -12,3 +12,11 @@ vars:
default: "."
description: The path to the package root.
prompt: Please enter the path to the package root.
+ shard-index:
+ type: number
+ description: The 1-based index of the shard to generate tests for.
+ prompt: Please enter the shard index.
+ total-shards:
+ type: number
+ description: The total number of shards the test suite is split into.
+ prompt: Please enter the total number of shards.
diff --git a/bricks/test_optimizer/hooks/lib/pre_gen.dart b/bricks/test_optimizer/hooks/lib/pre_gen.dart
index c0348ef02..bc789d217 100644
--- a/bricks/test_optimizer/hooks/lib/pre_gen.dart
+++ b/bricks/test_optimizer/hooks/lib/pre_gen.dart
@@ -33,35 +33,80 @@ Future run(HookContext context) async {
final flutterSdkRegExp = RegExp(r'sdk:\s*flutter$', multiLine: true);
final isFlutter = flutterSdkRegExp.hasMatch(pubspecContents);
- final identifierGenerator = DartIdentifierGenerator();
- final testIdentifierTable =