Skip to content

[material_ui, cupertino_ui, go_router] Command to test dart fixes - #12390

Merged
auto-submit[bot] merged 23 commits into
flutter:mainfrom
justinmc:test-dart-fixes
Aug 31, 2026
Merged

[material_ui, cupertino_ui, go_router] Command to test dart fixes#12390
auto-submit[bot] merged 23 commits into
flutter:mainfrom
justinmc:test-dart-fixes

Conversation

@justinmc

@justinmc justinmc commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

This PR creates a new repo-level CI command to run the dart fix tests in relevant packages. Before this PR, go_router had its own script to run its dart fix tests, and material_ui and cupertino_ui had dart fix tests that were not being run. After this PR, all of the above are run via the new command.

Part of flutter/flutter#182568

@justinmc justinmc self-assigned this Aug 6, 2026
@github-actions github-actions Bot added p: go_router triage-framework Should be looked at in framework triage labels Aug 7, 2026
@justinmc justinmc added the CICD Run CI/CD label Aug 7, 2026
@justinmc
justinmc requested a review from stuartmorgan-g August 7, 2026 19:52
@justinmc
justinmc marked this pull request as ready for review August 7, 2026 19:52

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the standalone tool/run_tests.dart script with a new test-dart-fixes command in the repository tooling, implemented in TestDartFixes. This command automates running Dart fix tests for packages containing a test_fixes directory. Feedback on the implementation highlights opportunities to improve testability by using the package's file system and the configured processRunner instead of hardcoded LocalFileSystem and Process.start calls. Additionally, minor typos in string interpolation within error messages were identified.

Comment thread script/tool/lib/src/test_dart_fixes.dart Outdated
Comment on lines +131 to +140
static Future<int> _runProcess(
String command,
List<String> arguments, {
String? workingDirectory,
}) async {
final Process process = await _streamOutput(
Process.start(command, arguments, workingDirectory: workingDirectory),
);
return process.exitCode;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Calling Process.start directly from dart:io bypasses the processRunner passed to the constructor, which prevents mocking process execution in unit tests. Consider making these helper methods non-static and using processRunner to run the processes.

try {
testDirectory = await _createTestDirectory(package);
} catch (error) {
return PackageResult.fail(['Failed to create temporary test directory: $error}']);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is a typo in the string interpolation: $error} has an extra closing brace. It should be $error.

Suggested change
return PackageResult.fail(['Failed to create temporary test directory: $error}']);
return PackageResult.fail(['Failed to create temporary test directory: $error']);

}
result = PackageResult.success();
} catch (error) {
result = PackageResult.fail(['Dart fix tests failed: $error}']);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is a typo in the string interpolation: $error} has an extra closing brace. It should be $error.

Suggested change
result = PackageResult.fail(['Dart fix tests failed: $error}']);
result = PackageResult.fail(['Dart fix tests failed: $error']);

@justinmc

justinmc commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Questions for @stuartmorgan-g in code review:

  • There are only 3 packages that support this, so it leaves a bunch of spam in the terminal saying "skipped x package". Is that ok or is there a way I should be avoiding that?
  • I deleted go_router's script that did this previously, but is there anything else that I should clean up there?

@stuartmorgan-g stuartmorgan-g left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two main high-level things

  • This command needs to be added to the CI so it's actually running. How long does it take to run? If it's fast we could just add it to https://github.com/flutter/packages/blob/main/.ci/targets/dart_unit_tests.yaml. If it's not, we'll need to think about where we can add it without causing issues.
  • We unit test all of the repo tooling, so this needs corresponding tests in script/tool's test directory. See other commands for the common patterns of DI, faking process output/exit codes, etc., and let me know if you have any questions.

There are only 3 packages that support this, so it leaves a bunch of spam in the terminal saying "skipped x package". Is that ok or is there a way I should be avoiding that?

That's a feature :)

(For context, when I started working on this repo, I discovered that we had a significant number of tests that people thought we were running but weren't because of various mistakes that were silently ignored, and it was extremely hard to figure that out because the CI output was just a sea of results for the things that did run. As a result, the tool is now designed for auditability, so that it's very easy to look at a run log and see exactly what did and did not run, to make sure that matches expectations.)

I deleted go_router's script that did this previously, but is there anything else that I should clean up there?

I don't think so; removing run_tests.dart will cause the package to be skipped by the custom-tests command (in the same way that removing test_fixes would cause a package to be skipped by this new command).

'This command requires "flutter" to be in your path.';

@override
PackageLoopingType get packageLoopingType => PackageLoopingType.includeAllSubpackages;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could sub-packages ever have their own dart fixes? If not we only need to look at top-level packages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible but doesn't happen in any of our packages. I'll set it to .topLevelOnly.

return PackageResult.fail(['Failed to create temporary test directory: $error']);
}

late final PackageResult result;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually need the late keyword? I would expect it to work without it (with better safety).

/// Run the dart fix tests for the package in the given temporary directory.
///
/// Resolves with the status code of the command.
Future<int> _runDartFixTests(RepositoryPackage package, Directory testDirectory) async {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package is never used.

final int pubGetStatusCode = await _runProcess('dart', <String>[
'pub',
'get',
], workingDirectory: testDirectory);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have runPubGet to abstract this, in pub_utils.dart. You just need to construct a RepositoryPackage from the test directory.

], workingDirectory: testDirectory);
}

Future<int> _runProcess(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods should be removed in favor of the command taking a ProcessRunner, and using processRunner.runAndStream. See dart_test_command.dart for an example (or almost any other command).

@justinmc

Copy link
Copy Markdown
Contributor Author

How long does it take to run?

About 40 seconds. Most of the time is from running flutter pub get three times in series. I've added it to dart_unit_tests.yaml preemptively, but let me know if that's too long and we should put it somewhere else.

@justinmc

Copy link
Copy Markdown
Contributor Author

CI is failing and some of the failures have to do with my new tests, but the error messages are cryptic. I'm going to push a merge commit and come back to this tomorrow.

final String name = 'test-dart-fixes';

@override
List<String> get aliases => <String>[];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the default value, so no override is needed.

'This command requires "flutter" to be in your path.';

@override
PackageLoopingType get packageLoopingType => PackageLoopingType.topLevelOnly;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

try {
final bool success = await _runDartFixTests(testDirectory);
if (!success) {
throw Exception('Failed to run dart fix tests.');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than turning a bool into an exception, why not just:

result = success ? PackageResult.success() : PackageResult.fail(['Tests failed']);

It seems easier to follow, and also avoids the common failure case having the string "Dart fix tests failed: Failed to run dart fix tests." (which seems confusing).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, good catch.

final bool success = await runPubGet(RepositoryPackage(testDirectory), processRunner, platform);

if (!success) {
return success;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if you make this method return a PackageResult rather than a bool, you could make the error summary distinguish between pub get failing and the tests themselves failing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I ended up making it throw an exception, but same idea.

contains('Running for package1'),
contains('Running for package2'),
contains('Running for package3'),
contains("SKIPPING: No MemoryDirectory: '/packages/package3/test_fixes' directory."),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This weird error message is because you are logging the file system object rather than its path; we should just have the path (preferably the package-relative path rather than the absolute path).

});
}

/// Fails when fix.dart does not equal fix.dart.expect.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of simulating the internal behavior of the fix tests? The command itself doesn't appear to know anything about the way the test works internally, so it seems like you'd get just as much test value out of just doing our standard exit value mocking, without the complexity of this class and of creating fake test-only expectation files just for this test-only code to read them to decide to fail.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, simplified in 190f200.

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@stuartmorgan-g stuartmorgan-g left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@justinmc justinmc added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 31, 2026
@auto-submit
auto-submit Bot merged commit c8faec1 into flutter:main Aug 31, 2026
13 checks passed
@justinmc
justinmc deleted the test-dart-fixes branch August 31, 2026 17:09
pull Bot pushed a commit to g-star1024/flutter that referenced this pull request Sep 1, 2026
…r#192119)

flutter/packages@d642322...7a7912f

2026-09-01 21270878+elliette@users.noreply.github.com [material_ui]
Migrate AppBar M3 template to use new gen_defaults script
(flutter/packages#12707)
2026-09-01 32538273+ValentinVignal@users.noreply.github.com
[vector_graphics] Fix deprecation lints (flutter/packages#12702)
2026-08-31 21270878+elliette@users.noreply.github.com [material_ui]
Standardize M3 and M3E token template base class names
(flutter/packages#12675)
2026-08-31 32538273+ValentinVignal@users.noreply.github.com
[vector_graphics_compiler] Fix deprecation issues in tests
(flutter/packages#12700)
2026-08-31 stuartmorgan@google.com [google_maps_flutter] Convert marker
controllers to Swift (flutter/packages#12662)
2026-08-31 jmccandless@google.com [material_ui, cupertino_ui, go_router]
Command to test dart fixes (flutter/packages#12390)
2026-08-31 engine-flutter-autoroll@skia.org Roll Flutter from
c978386 to c8c5e3b (4 revisions) (flutter/packages#12706)
2026-08-31 269567208+reidbaker-agent@users.noreply.github.com [tool]
Exempt AGENTS.md from version and changelog checks
(flutter/packages#12681)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: go_router triage-framework Should be looked at in framework triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants