-
Notifications
You must be signed in to change notification settings - Fork 6k
[web] separate tests into build + test steps; add run command #27495
Conversation
3f00f4e to
cea6ce9
Compare
3f427fc to
0c5f37b
Compare
9a4a434 to
d15e57f
Compare
mdebbar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a few suggestions but nothing that blocks the PR.
| if (unrecognizedStepNames.isNotEmpty) { | ||
| io.stderr.writeln(); | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we explain what happened here and print the step names that were unrecognized? The user could make a typo in a step name and not understand why the command is failing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're too kind. I totally messed this one up :)
Fixing.
| if (htmlTargets.isNotEmpty) { | ||
| await _compileTestsInParallel(targets: htmlTargets, forCanvasKit: false); | ||
| } | ||
|
|
||
| if (canvasKitTargets.isNotEmpty) { | ||
| await _compileTestsInParallel(targets: canvasKitTargets, forCanvasKit: true); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: in case both of these are true at the same time, should we compile them in parallel? Or do they have to be sequential?
| if (htmlTargets.isNotEmpty) { | |
| await _compileTestsInParallel(targets: htmlTargets, forCanvasKit: false); | |
| } | |
| if (canvasKitTargets.isNotEmpty) { | |
| await _compileTestsInParallel(targets: canvasKitTargets, forCanvasKit: true); | |
| } | |
| await Future.wait([ | |
| if (htmlTargets.isNotEmpty) | |
| _compileTestsInParallel(targets: htmlTargets, forCanvasKit: false), | |
| if (canvasKitTargets.isNotEmpty) | |
| _compileTestsInParallel(targets: canvasKitTargets, forCanvasKit: true), | |
| ]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| await for (final bool isSuccess in results) { | ||
| if (!isSuccess) { | ||
| throw ToolExit('Failed to compile tests.'); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why you picked this over Future.wait()?
I just looked it up now. You can pass eagerError: true which might be even better than the await for loop since it awaits all tests in parallel instead of awaiting in sequence. e.g. what if the first test takes a long time to run, and the second test fails quickly? The await for loop waits until the first test is complete, while Future.wait(eagerError: true) stops as soon as the second test fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait. results is a stream, not a list of futures. Ok, my suggestion is probably invalid.
godofredoc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this PR but maybe for a future improvement, it would be great to have the ability to skip and/or run individual tests from a test suite using felt command parameters.
LGTM with some questions and suggestions.
| /// Usage: | ||
| /// | ||
| /// felt run name_of_build_step | ||
| class RunCommand extends Command<bool> with ArgUtils<bool> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this class be called BuildCommand instead? seems like this class encapsulates the functionality for build steps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
felt build is already taken. It means "build host_debug_unopt". In this case "run" makes sense because it does is run some steps. Those steps may be building, but the may also execute tests, and in the future check licenses, run analysis, and so on.
| required bool forCanvasKit, | ||
| }) async { | ||
| /// Maximum number of concurrent dart2js processes to use. | ||
| final Pool pool = Pool(8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to use a constant for this or calculate it based on the number of available CPUs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: made this configurable via FELT_DART2JS_CONCURRENCY environment variable.
| await _runTestBatch( | ||
| testFiles: unitTestFiles, | ||
| browserEnvironment: browserEnvironment, | ||
| concurrency: 10, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a constant for this value or calculate it based on available CPUs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| required BrowserEnvironment browserEnvironment, | ||
| required bool doUpdateScreenshotGoldens, | ||
| required int concurrency, | ||
| required bool expectFailure, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the use case for this flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We run smoke tests that are expected to fail. This is for detecting when there's something wrong and the test suite isn't running at all.
81f5d00 to
33e680f
Compare
33e680f to
ea8babb
Compare
That's already supported, although not via the new |
Introduce
felt runthat runs one or more build steps, identified by name. Build steps can run one after another to complete a larger task. For example, to run tests, one can run acompile_testsstep followed by arun_testsstep. A build graph can execute steps on different bots and pass build artifacts from bot to bot for higher parallelism and better machine utilisation.Use
felt runto separate web tests into build and test steps:compile_tests- compiles tests but does not run them. This step is intended to be executed by a dedicated build bot, and its artifacts shared with bots that run the tests.run_tests_BROWSER- whereBROWSERcan bechrome,edge,firefox,safari,ios-safari, are steps that run tests (but do not compile them). These steps are intended to be executed by build bots with a particular OS/browser combination.Build steps are implemented on top of the existing
PipelineandPipelineStepclasses. This way steps can be used byfelt runas well as by existing commands. For example, this PR implements bothfelt runandfelt testin terms of the same build step classes.Additional clean-ups/refactorings to facilitate this design:
ScreenshotManageralready indicates that the current browser doesn't support screenshots, and we already have a way to skip tests from within the test itself; there's no need for yet another way of skipping tests. This removes some complexity from the felt code.--chrome-version,--safari-version,--edge-version,--firefox-version,--type,--verbose.BrowserLocka more structured class, so we don't have to parse YAML everywhere.browser_lock.yaml(use underscores).Fixes flutter/flutter#85274