mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] use package:test for coverage and remove build_runner test precompilation (#51966)
This commit is contained in:
parent
7593228665
commit
124aa6f8b1
@ -39,8 +39,6 @@ final List<String> flutterTestArgs = <String>[];
|
||||
|
||||
final bool useFlutterTestFormatter = Platform.environment['FLUTTER_TEST_FORMATTER'] == 'true';
|
||||
|
||||
final bool canUseBuildRunner = Platform.environment['FLUTTER_TEST_NO_BUILD_RUNNER'] != 'true';
|
||||
|
||||
/// The number of Cirrus jobs that run host-only devicelab tests in parallel.
|
||||
///
|
||||
/// WARNING: if you change this number, also change .cirrus.yml
|
||||
@ -236,18 +234,18 @@ Future<bq.BigqueryApi> _getBigqueryApi() async {
|
||||
}
|
||||
|
||||
Future<void> _runToolCoverage() async {
|
||||
await runCommand( // Precompile tests to speed up subsequent runs.
|
||||
pub,
|
||||
<String>['run', 'build_runner', 'build'],
|
||||
workingDirectory: toolRoot,
|
||||
await _pubRunTest(
|
||||
toolRoot,
|
||||
testPaths: <String>[
|
||||
path.join('test', 'general.shard'),
|
||||
path.join('test', 'commands.shard', 'hermetic'),
|
||||
],
|
||||
coverage: 'coverage',
|
||||
);
|
||||
await runCommand(
|
||||
dart,
|
||||
<String>[path.join('tool', 'tool_coverage.dart')],
|
||||
await runCommand(pub,
|
||||
<String>['run', 'coverage:format_coverage', '--lcov', '--in=coverage', '--out=coverage/lcov.info'],
|
||||
workingDirectory: toolRoot,
|
||||
environment: <String, String>{
|
||||
'FLUTTER_ROOT': flutterRoot,
|
||||
}
|
||||
outputMode: OutputMode.discard,
|
||||
);
|
||||
}
|
||||
|
||||
@ -273,8 +271,7 @@ Future<void> _runToolTests() async {
|
||||
: '';
|
||||
await _pubRunTest(
|
||||
toolsPath,
|
||||
testPath: path.join(kTest, '$subshard$kDotShard', suffix),
|
||||
useBuildRunner: canUseBuildRunner,
|
||||
testPaths: <String>[path.join(kTest, '$subshard$kDotShard', suffix)],
|
||||
tableData: bigqueryApi?.tabledata,
|
||||
enableFlutterToolAsserts: true,
|
||||
);
|
||||
@ -706,25 +703,12 @@ Future<void> _runFlutterWebTest(String workingDirectory, List<String> tests) asy
|
||||
}
|
||||
|
||||
Future<void> _pubRunTest(String workingDirectory, {
|
||||
String testPath,
|
||||
List<String> testPaths,
|
||||
bool enableFlutterToolAsserts = true,
|
||||
bool useBuildRunner = false,
|
||||
String coverage,
|
||||
bq.TabledataResourceApi tableData,
|
||||
}) async {
|
||||
final List<String> args = <String>['run'];
|
||||
if (useBuildRunner) {
|
||||
final String posixTestPath = path.posix.joinAll(path.split(testPath));
|
||||
args.addAll(<String>[
|
||||
'build_runner',
|
||||
'test',
|
||||
'--build-filter=$posixTestPath/*.dill',
|
||||
'--build-filter=$posixTestPath/**/*.dill',
|
||||
'--',
|
||||
]);
|
||||
} else {
|
||||
args.add('test');
|
||||
}
|
||||
args.add(useFlutterTestFormatter ? '-rjson' : '-rcompact');
|
||||
int cpus;
|
||||
final String cpuVariable = Platform.environment['CPU']; // CPU is set in cirrus.yml
|
||||
if (cpuVariable != null) {
|
||||
@ -737,11 +721,23 @@ Future<void> _pubRunTest(String workingDirectory, {
|
||||
} else {
|
||||
cpus = 2; // Don't default to 1, otherwise we won't catch race conditions.
|
||||
}
|
||||
args.add('-j$cpus');
|
||||
if (!hasColor)
|
||||
args.add('--no-color');
|
||||
if (testPath != null)
|
||||
args.add(testPath);
|
||||
|
||||
final List<String> args = <String>[
|
||||
'run',
|
||||
'test',
|
||||
if (useFlutterTestFormatter)
|
||||
'-rjson'
|
||||
else
|
||||
'-rcompact',
|
||||
'-j$cpus',
|
||||
if (!hasColor)
|
||||
'--no-color',
|
||||
if (coverage != null)
|
||||
'--coverage=$coverage',
|
||||
if (testPaths != null)
|
||||
for (final String testPath in testPaths)
|
||||
testPath,
|
||||
];
|
||||
final Map<String, String> pubEnvironment = <String, String>{
|
||||
'FLUTTER_ROOT': flutterRoot,
|
||||
};
|
||||
|
@ -98,30 +98,15 @@ dev_dependencies:
|
||||
mockito: 4.1.1
|
||||
file_testing: 2.1.0
|
||||
test: 1.14.1
|
||||
build_runner: 1.7.4
|
||||
build_vm_compilers: 1.0.4
|
||||
build_test: 0.10.12+1
|
||||
pubspec_parse: 0.1.5
|
||||
|
||||
bazel_worker: 0.1.23+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
build: 1.2.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
build_config: 0.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
build_modules: 2.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
build_resolvers: 1.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
build_runner_core: 4.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
checked_yaml: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
code_builder: 3.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
dart_style: 1.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
graphs: 0.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_annotation: 3.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
protobuf: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pubspec_parse: 0.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
scratch_space: 0.0.4+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
timing: 0.1.1+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
|
||||
dartdoc:
|
||||
# Exclude this package from the hosted API docs.
|
||||
nodoc: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 193b
|
||||
# PUBSPEC CHECKSUM: 86fe
|
||||
|
@ -1,158 +0,0 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:coverage/coverage.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/context_runner.dart';
|
||||
import 'package:flutter_tools/src/test/test_wrapper.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:stream_channel/isolate_channel.dart';
|
||||
import 'package:stream_channel/stream_channel.dart';
|
||||
import 'package:test_api/src/backend/suite_platform.dart'; // ignore: implementation_imports
|
||||
import 'package:test_core/src/runner/runner_suite.dart'; // ignore: implementation_imports
|
||||
import 'package:test_core/src/runner/suite.dart'; // ignore: implementation_imports
|
||||
import 'package:test_core/src/runner/plugin/platform_helpers.dart'; // ignore: implementation_imports
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/test/coverage_collector.dart';
|
||||
|
||||
/// Generates an lcov report for the flutter tool unit tests.
|
||||
///
|
||||
/// Example invocation:
|
||||
///
|
||||
/// dart tool/tool_coverage.dart
|
||||
Future<void> main(List<String> arguments) async {
|
||||
return runInContext(() async {
|
||||
final VMPlatform vmPlatform = VMPlatform();
|
||||
const TestWrapper test = TestWrapper();
|
||||
test.registerPlatformPlugin(
|
||||
<Runtime>[Runtime.vm],
|
||||
() => vmPlatform,
|
||||
);
|
||||
if (arguments.isEmpty) {
|
||||
arguments = <String>[
|
||||
path.join('test', 'general.shard'),
|
||||
path.join('test', 'commands.shard', 'hermetic'),
|
||||
];
|
||||
}
|
||||
await test.main(<String>[
|
||||
'--no-color',
|
||||
'-r', 'compact',
|
||||
'-j', '1',
|
||||
...arguments
|
||||
]);
|
||||
exit(exitCode);
|
||||
});
|
||||
}
|
||||
|
||||
/// A platform that loads tests in isolates spawned within this Dart process.
|
||||
class VMPlatform extends PlatformPlugin {
|
||||
final CoverageCollector coverageCollector = CoverageCollector(
|
||||
libraryPredicate: (String libraryName) => libraryName.contains(FlutterProject.current().manifest.appName),
|
||||
);
|
||||
final Map<String, Future<void>> _pending = <String, Future<void>>{};
|
||||
final String precompiledPath = path.join('.dart_tool', 'build', 'generated', 'flutter_tools');
|
||||
|
||||
@override
|
||||
StreamChannel<void> loadChannel(String codePath, SuitePlatform platform) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future<RunnerSuite> load(
|
||||
String codePath,
|
||||
SuitePlatform platform,
|
||||
SuiteConfiguration suiteConfig,
|
||||
Object message,
|
||||
) async {
|
||||
final ReceivePort receivePort = ReceivePort();
|
||||
Isolate isolate;
|
||||
try {
|
||||
isolate = await _spawnIsolate(codePath, receivePort.sendPort);
|
||||
} catch (error) {
|
||||
receivePort.close();
|
||||
rethrow;
|
||||
}
|
||||
final Completer<void> completer = Completer<void>();
|
||||
// When this is completed we remove it from the map of pending so we can
|
||||
// log the futures that get "stuck".
|
||||
unawaited(completer.future.whenComplete(() {
|
||||
_pending.remove(codePath);
|
||||
}));
|
||||
final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
|
||||
final StreamChannel<Object> channel = IsolateChannel<Object>.connectReceive(receivePort)
|
||||
.transformStream(StreamTransformer<Object, Object>.fromHandlers(
|
||||
handleDone: (EventSink<Object> sink) async {
|
||||
try {
|
||||
// this will throw if collection fails.
|
||||
await coverageCollector.collectCoverageIsolate(info.serverUri);
|
||||
} finally {
|
||||
isolate.kill(priority: Isolate.immediate);
|
||||
isolate = null;
|
||||
sink.close();
|
||||
completer.complete();
|
||||
}
|
||||
},
|
||||
handleError: (dynamic error, StackTrace stackTrace, EventSink<Object> sink) {
|
||||
isolate.kill(priority: Isolate.immediate);
|
||||
isolate = null;
|
||||
sink.close();
|
||||
completer.complete();
|
||||
},
|
||||
));
|
||||
|
||||
final RunnerSuiteController controller = deserializeSuite(
|
||||
codePath,
|
||||
platform,
|
||||
suiteConfig,
|
||||
null,
|
||||
channel,
|
||||
message,
|
||||
);
|
||||
_pending[codePath] = completer.future;
|
||||
return await controller.suite;
|
||||
}
|
||||
|
||||
/// Spawns an isolate and passes it [message].
|
||||
///
|
||||
/// This isolate connects an [IsolateChannel] to [message] and sends the
|
||||
/// serialized tests over that channel.
|
||||
Future<Isolate> _spawnIsolate(String codePath, SendPort message) async {
|
||||
String testPath = path.absolute(path.join(precompiledPath, codePath) + '.vm_test.dart');
|
||||
testPath = testPath.substring(0, testPath.length - '.dart'.length) + '.vm.app.dill';
|
||||
return await Isolate.spawnUri(path.toUri(testPath), <String>[], message,
|
||||
packageConfig: path.toUri('.packages'),
|
||||
checked: true,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
try {
|
||||
await Future.wait(_pending.values).timeout(const Duration(minutes: 1));
|
||||
} on TimeoutException {
|
||||
// TODO(jonahwilliams): resolve whether there are any specific tests that
|
||||
// get stuck or if it is a general infra issue with how we are collecting
|
||||
// coverage.
|
||||
// Log tests that are "Stuck" waiting for coverage.
|
||||
print('The following tests timed out waiting for coverage:');
|
||||
print(_pending.keys.join(', '));
|
||||
}
|
||||
final String packagePath = Directory.current.path;
|
||||
final Resolver resolver = Resolver(packagesPath: '.packages');
|
||||
final Formatter formatter = LcovFormatter(resolver, reportOn: <String>[
|
||||
'lib',
|
||||
], basePath: packagePath);
|
||||
final String result = await coverageCollector.finalizeCoverage(
|
||||
formatter: formatter,
|
||||
);
|
||||
final String outputLcovPath = path.join('coverage', 'lcov.info');
|
||||
File(outputLcovPath)
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(result);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user