Unverified Commit b123846c authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Improve flutter test startup time (#29404)

parent cf12c314
...@@ -10,6 +10,7 @@ import '../base/file_system.dart'; ...@@ -10,6 +10,7 @@ import '../base/file_system.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../cache.dart'; import '../cache.dart';
import '../codegen.dart'; import '../codegen.dart';
import '../dart/pub.dart';
import '../project.dart'; import '../project.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../test/coverage_collector.dart'; import '../test/coverage_collector.dart';
...@@ -17,7 +18,7 @@ import '../test/event_printer.dart'; ...@@ -17,7 +18,7 @@ import '../test/event_printer.dart';
import '../test/runner.dart'; import '../test/runner.dart';
import '../test/watcher.dart'; import '../test/watcher.dart';
class TestCommand extends FlutterCommand { class TestCommand extends FastFlutterCommand {
TestCommand({ bool verboseHelp = false }) { TestCommand({ bool verboseHelp = false }) {
requiresPubspecYaml(); requiresPubspecYaml();
usesPubOption(); usesPubOption();
...@@ -91,8 +92,7 @@ class TestCommand extends FlutterCommand { ...@@ -91,8 +92,7 @@ class TestCommand extends FlutterCommand {
String get description => 'Run Flutter unit tests for the current project.'; String get description => 'Run Flutter unit tests for the current project.';
@override @override
Future<void> validateCommand() async { Future<FlutterCommandResult> runCommand() async {
await super.validateCommand();
if (!fs.isFileSync('pubspec.yaml')) { if (!fs.isFileSync('pubspec.yaml')) {
throwToolExit( throwToolExit(
'Error: No pubspec.yaml file found in the current working directory.\n' 'Error: No pubspec.yaml file found in the current working directory.\n'
...@@ -100,10 +100,9 @@ class TestCommand extends FlutterCommand { ...@@ -100,10 +100,9 @@ class TestCommand extends FlutterCommand {
'called *_test.dart and must reside in the package\'s \'test\' ' 'called *_test.dart and must reside in the package\'s \'test\' '
'directory (or one of its subdirectories).'); 'directory (or one of its subdirectories).');
} }
} if (shouldRunPub) {
await pubGet(context: PubContext.getVerifyContext(name), skipPubspecYamlCheck: true);
@override }
Future<FlutterCommandResult> runCommand() async {
final List<String> names = argResults['name']; final List<String> names = argResults['name'];
final List<String> plainNames = argResults['plain-name']; final List<String> plainNames = argResults['plain-name'];
final FlutterProject flutterProject = await FlutterProject.current(); final FlutterProject flutterProject = await FlutterProject.current();
......
...@@ -76,13 +76,14 @@ Future<void> pubGet({ ...@@ -76,13 +76,14 @@ Future<void> pubGet({
bool upgrade = false, bool upgrade = false,
bool offline = false, bool offline = false,
bool checkLastModified = true, bool checkLastModified = true,
bool skipPubspecYamlCheck = false
}) async { }) async {
directory ??= fs.currentDirectory.path; directory ??= fs.currentDirectory.path;
final File pubSpecYaml = fs.file(fs.path.join(directory, 'pubspec.yaml')); final File pubSpecYaml = fs.file(fs.path.join(directory, 'pubspec.yaml'));
final File dotPackages = fs.file(fs.path.join(directory, '.packages')); final File dotPackages = fs.file(fs.path.join(directory, '.packages'));
if (!pubSpecYaml.existsSync()) { if (!skipPubspecYamlCheck && !pubSpecYaml.existsSync()) {
if (!skipIfAbsent) if (!skipIfAbsent)
throwToolExit('$directory: no pubspec.yaml found'); throwToolExit('$directory: no pubspec.yaml found');
return; return;
......
...@@ -662,3 +662,15 @@ abstract class FlutterCommand extends Command<void> { ...@@ -662,3 +662,15 @@ abstract class FlutterCommand extends Command<void> {
ApplicationPackageStore applicationPackages; ApplicationPackageStore applicationPackages;
} }
/// A command which runs less analytics and checks to speed up startup time.
abstract class FastFlutterCommand extends FlutterCommand {
@override
Future<void> run() {
return context.run<void>(
name: 'command',
overrides: <Type, Generator>{FlutterCommand: () => this},
body: runCommand,
);
}
}
...@@ -275,6 +275,7 @@ class _Compiler { ...@@ -275,6 +275,7 @@ class _Compiler {
flutterProject: flutterProject, flutterProject: flutterProject,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
compilerMessageConsumer: reportCompilerMessage, compilerMessageConsumer: reportCompilerMessage,
initializeFromDill: testFilePath,
// We already ran codegen once at the start, we only need to // We already ran codegen once at the start, we only need to
// configure builders. // configure builders.
runCold: true, runCold: true,
......
...@@ -20,28 +20,17 @@ import 'globals.dart'; ...@@ -20,28 +20,17 @@ import 'globals.dart';
class FlutterVersion { class FlutterVersion {
@visibleForTesting @visibleForTesting
FlutterVersion([this._clock = const SystemClock()]) { FlutterVersion([this._clock = const SystemClock()]) {
_channel = _runGit('git rev-parse --abbrev-ref --symbolic @{u}');
final String branch = _runGit('git rev-parse --abbrev-ref HEAD');
_branch = branch == 'HEAD' ? _channel : branch;
final int slash = _channel.indexOf('/');
if (slash != -1) {
final String remote = _channel.substring(0, slash);
_repositoryUrl = _runGit('git ls-remote --get-url $remote');
_channel = _channel.substring(slash + 1);
} else if (_channel.isEmpty) {
_channel = 'unknown';
}
_frameworkRevision = _runGit('git log -n 1 --pretty=format:%H'); _frameworkRevision = _runGit('git log -n 1 --pretty=format:%H');
_frameworkAge = _runGit('git log -n 1 --pretty=format:%ar');
_frameworkVersion = GitTagVersion.determine().frameworkVersionFor(_frameworkRevision); _frameworkVersion = GitTagVersion.determine().frameworkVersionFor(_frameworkRevision);
} }
final SystemClock _clock; final SystemClock _clock;
String _repositoryUrl; String _repositoryUrl;
String get repositoryUrl => _repositoryUrl; String get repositoryUrl {
final String _ = channel;
return _repositoryUrl;
}
static const Set<String> officialChannels = <String>{ static const Set<String> officialChannels = <String>{
'master', 'master',
...@@ -64,7 +53,22 @@ class FlutterVersion { ...@@ -64,7 +53,22 @@ class FlutterVersion {
String _channel; String _channel;
/// The channel is the upstream branch. /// The channel is the upstream branch.
/// `master`, `dev`, `beta`, `stable`; or old ones, like `alpha`, `hackathon`, ... /// `master`, `dev`, `beta`, `stable`; or old ones, like `alpha`, `hackathon`, ...
String get channel => _channel; String get channel {
if (_channel == null) {
final String channel = _runGit('git rev-parse --abbrev-ref --symbolic @{u}');
final int slash = channel.indexOf('/');
if (slash != -1) {
final String remote = channel.substring(0, slash);
_repositoryUrl = _runGit('git ls-remote --get-url $remote');
_channel = channel.substring(slash + 1);
} else if (channel.isEmpty) {
_channel = 'unknown';
} else {
_channel = channel;
}
}
return _channel;
}
/// The name of the local branch. /// The name of the local branch.
/// Use getBranchName() to read this. /// Use getBranchName() to read this.
...@@ -75,7 +79,9 @@ class FlutterVersion { ...@@ -75,7 +79,9 @@ class FlutterVersion {
String get frameworkRevisionShort => _shortGitRevision(frameworkRevision); String get frameworkRevisionShort => _shortGitRevision(frameworkRevision);
String _frameworkAge; String _frameworkAge;
String get frameworkAge => _frameworkAge; String get frameworkAge {
return _frameworkAge ??= _runGit('git log -n 1 --pretty=format:%ar');
}
String _frameworkVersion; String _frameworkVersion;
String get frameworkVersion => _frameworkVersion; String get frameworkVersion => _frameworkVersion;
...@@ -182,6 +188,10 @@ class FlutterVersion { ...@@ -182,6 +188,10 @@ class FlutterVersion {
/// If [redactUnknownBranches] is true and the branch is unknown, /// If [redactUnknownBranches] is true and the branch is unknown,
/// the branch name will be returned as `'[user-branch]'`. /// the branch name will be returned as `'[user-branch]'`.
String getBranchName({ bool redactUnknownBranches = false }) { String getBranchName({ bool redactUnknownBranches = false }) {
_branch ??= () {
final String branch = _runGit('git rev-parse --abbrev-ref HEAD');
return branch == 'HEAD' ? channel : branch;
}();
if (redactUnknownBranches || _branch.isEmpty) { if (redactUnknownBranches || _branch.isEmpty) {
// Only return the branch names we know about; arbitrary branch names might contain PII. // Only return the branch names we know about; arbitrary branch names might contain PII.
if (!officialChannels.contains(_branch) && !obsoleteBranches.containsKey(_branch)) if (!officialChannels.contains(_branch) && !obsoleteBranches.containsKey(_branch))
...@@ -266,7 +276,7 @@ class FlutterVersion { ...@@ -266,7 +276,7 @@ class FlutterVersion {
/// writes shared cache files. /// writes shared cache files.
Future<void> checkFlutterVersionFreshness() async { Future<void> checkFlutterVersionFreshness() async {
// Don't perform update checks if we're not on an official channel. // Don't perform update checks if we're not on an official channel.
if (!officialChannels.contains(_channel)) { if (!officialChannels.contains(channel)) {
return; return;
} }
...@@ -359,7 +369,7 @@ class FlutterVersion { ...@@ -359,7 +369,7 @@ class FlutterVersion {
// Cache is empty or it's been a while since the last server ping. Ping the server. // Cache is empty or it's been a while since the last server ping. Ping the server.
try { try {
final DateTime remoteFrameworkCommitDate = DateTime.parse(await FlutterVersion.fetchRemoteFrameworkCommitDate(_channel)); final DateTime remoteFrameworkCommitDate = DateTime.parse(await FlutterVersion.fetchRemoteFrameworkCommitDate(channel));
await versionCheckStamp.store( await versionCheckStamp.store(
newTimeVersionWasChecked: _clock.now(), newTimeVersionWasChecked: _clock.now(),
newKnownRemoteVersion: remoteFrameworkCommitDate, newKnownRemoteVersion: remoteFrameworkCommitDate,
......
...@@ -1001,6 +1001,17 @@ Future<void> _runFlutterTest(Directory workingDir, { String target }) async { ...@@ -1001,6 +1001,17 @@ Future<void> _runFlutterTest(Directory workingDir, { String target }) async {
'flutter_tools.dart', 'flutter_tools.dart',
)); ));
// While flutter test does get packages, it doesn't write version
// files anymore.
await Process.run(
'$dartSdkPath/bin/dart',
<String>[]
..addAll(dartVmFlags)
..add(flutterToolsPath)
..addAll(<String>['packages', 'get']),
workingDirectory: workingDir.path,
);
final List<String> args = <String>[] final List<String> args = <String>[]
..addAll(dartVmFlags) ..addAll(dartVmFlags)
..add(flutterToolsPath) ..add(flutterToolsPath)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment