[flutter_tools] allow using flutter test for testing the tool too (#69911)
diff --git a/dev/missing_dependency_tests/trivial_expectation.txt b/dev/missing_dependency_tests/trivial_expectation.txt
index 79bf7d3..cfd88b3 100644
--- a/dev/missing_dependency_tests/trivial_expectation.txt
+++ b/dev/missing_dependency_tests/trivial_expectation.txt
@@ -1,7 +1,7 @@
<<skip until matching line>>
<<stderr>>
<<skip until matching line>>
-Error: cannot run without a dependency on "package:flutter_test". Ensure the following lines are present in your pubspec.yaml:
+Error: cannot run without a dependency on either "package:flutter_test" or "package:test". Ensure the following lines are present in your pubspec.yaml:
dev_dependencies:
flutter_test:
diff --git a/packages/flutter_tools/README.md b/packages/flutter_tools/README.md
index 7bd4dea..2f6b29b 100644
--- a/packages/flutter_tools/README.md
+++ b/packages/flutter_tools/README.md
@@ -15,14 +15,14 @@
First, ensure that the Dart SDK and other necessary artifacts are available by
invoking the Flutter Tools wrapper script. In this directory run:
```shell
-$ ../../bin/flutter --version
+$ flutter --version
```
### Running the Tool
To run Flutter Tools from source, in this directory run:
```shell
-$ ../../bin/dart bin/flutter_tools.dart
+$ dart bin/flutter_tools.dart
```
followed by command-line arguments, as usual.
@@ -31,7 +31,7 @@
To run the analyzer on Flutter Tools, in this directory run:
```shell
-$ ../../bin/flutter analyze
+$ flutter analyze
```
### Writing tests
@@ -50,12 +50,6 @@
file called `file_test.dart` in the subdirectory that matches the behavior of
the test.
-We measure [test coverage](https://codecov.io/gh/flutter/flutter) post-submit.
-A change that deletes code might decrease test coverage, however, most changes
-that add new code should aim to increase coverage. In particular, the coverage
-of the diff should be close to the average coverage, and should ideally be
-better.
-
#### Using local engine builds in integration tests
The integration tests can be configured to use a specific local engine
@@ -67,15 +61,15 @@
```shell
export FLUTTER_LOCAL_ENGINE=android_debug_unopt
-../../bin/dart test test/integration.shard/some_test_case
+flutter test test/integration.shard/some_test_case
```
### Running the tests
-To run the tests in the `test/` directory, first ensure that there are no
-connected devices. Then, in this directory run:
+To run the tests in the `test/` directory:
+
```shell
-$ ../../bin/dart pub run test
+$ flutter test
```
The tests in `test/integration.shard` are slower to run than the tests in
@@ -83,12 +77,12 @@
to be set and pointing to the root of the Flutter SDK. To run only the tests in `test/general.shard`, in this
directory run:
```shell
-$ ../../bin/dart pub run test test/general.shard
+$ flutter test test/general.shard
```
To run the tests in a specific file, run:
```shell
-$ ../../bin/dart pub run test test/general.shard/utils_test.dart
+$ flutter test test/general.shard/utils_test.dart
```
### Forcing snapshot regeneration
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 246f287..f6ae079 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -131,6 +131,17 @@
'interact with the vmservice at runtime.\n'
'This flag is ignored if --start-paused or coverage are requested. '
'The vmservice will be enabled no matter what in those cases.'
+ )
+ ..addOption('reporter',
+ abbr: 'r',
+ defaultsTo: 'compact',
+ help: 'Set how to print test results.\n'
+ '[compact] (default) A single line, updated continuously.\n'
+ '[expanded] A separate line for each update.\n'
+ '[json] A machine-readable format (see https://dart.dev/go/test-docs/json_reporter.md).\n')
+ ..addOption('timeout',
+ help: 'The default test timeout. For example: 15s, 2x, none. Defaults to "30s"',
+ defaultsTo: '30s',
);
addDdsOptions(verboseHelp: verboseHelp);
}
@@ -263,6 +274,8 @@
web: stringArg('platform') == 'chrome',
randomSeed: stringArg('test-randomize-ordering-seed'),
nullAssertions: boolArg(FlutterOptions.kNullAssertions),
+ reporter: stringArg('reporter'),
+ timeout: stringArg('timeout'),
);
if (collector != null) {
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart
index 4d35eb9..408ba64 100644
--- a/packages/flutter_tools/lib/src/test/flutter_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
+import 'dart:io' as io; // ignore: dart_io_import;
import 'package:dds/dds.dart';
import 'package:meta/meta.dart';
@@ -125,6 +126,7 @@
bool updateGoldens = false,
String languageVersionHeader = '',
bool nullSafety = false,
+ bool flutterTestDep = true,
}) {
assert(testUrl != null);
assert(host != null);
@@ -142,8 +144,13 @@
import 'dart:convert'; // ignore: dart_convert_import
import 'dart:io'; // ignore: dart_io_import
import 'dart:isolate';
-
+''');
+ if (flutterTestDep) {
+ buffer.write('''
import 'package:flutter_test/flutter_test.dart';
+''');
+ }
+ buffer.write('''
import 'package:test_api/src/remote_listener.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:stack_trace/stack_trace.dart';
@@ -186,9 +193,13 @@
String server = Uri.decodeComponent('$encodedWebsocketUrl:\$serverPort');
StreamChannel<dynamic> channel = serializeSuite(() {
catchIsolateErrors();
- goldenFileComparator = new LocalFileComparator(Uri.parse('$testUrl'));
- autoUpdateGoldenFiles = $updateGoldens;
''');
+ if (flutterTestDep) {
+ buffer.write('''
+goldenFileComparator = LocalFileComparator(Uri.parse('$testUrl'));
+autoUpdateGoldenFiles = $updateGoldens;
+''');
+ }
if (testConfigFile != null) {
buffer.write('''
return () => test_config.testExecutable(test.main);
@@ -289,23 +300,10 @@
// LoadSuite to emit an error, which will be presented to the user.
// Except for the Declarer error, which is a specific test incompatibility
// error we need to catch.
- try {
- final StreamChannel<dynamic> channel = loadChannel(path, platform);
- final RunnerSuiteController controller = deserializeSuite(path, platform,
- suiteConfig, const PluginEnvironment(), channel, message);
- return await controller.suite;
- } on Exception catch (err) {
- /// Rethrow a less confusing error if it is a test incompatibility.
- if (err.toString().contains("type 'Declarer' is not a subtype of type 'Declarer'")) {
- throw UnsupportedError('Package incompatibility between flutter and test packages:\n'
- ' * flutter is incompatible with test <1.4.0.\n'
- ' * flutter is incompatible with mockito <4.0.0\n'
- "To fix this error, update test to at least '^1.4.0' and mockito to at least '^4.0.0'\n"
- );
- }
- // Guess it was a different error.
- rethrow;
- }
+ final StreamChannel<dynamic> channel = loadChannel(path, platform);
+ final RunnerSuiteController controller = deserializeSuite(path, platform,
+ suiteConfig, const PluginEnvironment(), channel, message);
+ return controller.suite;
}
@override
@@ -457,7 +455,7 @@
finalizers.add(() async {
if (subprocessActive) {
globals.printTrace('test $ourTestCount: ensuring end-of-process for shell');
- process.kill();
+ process.kill(io.ProcessSignal.sigkill);
final int exitCode = await process.exitCode;
subprocessActive = false;
if (!controllerSinkClosed && exitCode != -15) {
@@ -722,6 +720,7 @@
testConfigFile: findTestConfigFile(globals.fs.file(testUrl)),
host: host,
updateGoldens: updateGoldens,
+ flutterTestDep: _packageConfig['flutter_test'] != null,
languageVersionHeader: '// @dart=${languageVersion.major}.${languageVersion.minor}'
);
}
diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart
index fb71684..dfc2325 100644
--- a/packages/flutter_tools/lib/src/test/runner.dart
+++ b/packages/flutter_tools/lib/src/test/runner.dart
@@ -49,6 +49,8 @@
String randomSeed,
bool nullAssertions = false,
@required BuildInfo buildInfo,
+ String reporter,
+ String timeout,
});
}
@@ -83,6 +85,8 @@
String randomSeed,
bool nullAssertions = false,
@required BuildInfo buildInfo,
+ String reporter,
+ String timeout,
}) async {
// Configure package:test to use the Flutter engine for child processes.
final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester);
@@ -99,7 +103,9 @@
if (machine)
...<String>['-r', 'json']
else
- ...<String>['-r', 'compact'],
+ ...<String>['-r', reporter ?? 'compact'],
+ if (timeout != null)
+ ...<String>['--timeout', timeout],
'--concurrency=$concurrency',
for (final String name in names)
...<String>['--name', name],
diff --git a/packages/flutter_tools/lib/src/test/test_compiler.dart b/packages/flutter_tools/lib/src/test/test_compiler.dart
index e8ac393..fbb79ad 100644
--- a/packages/flutter_tools/lib/src/test/test_compiler.dart
+++ b/packages/flutter_tools/lib/src/test/test_compiler.dart
@@ -134,10 +134,10 @@
);
// Compilation will fail if there is no flutter_test dependency, since
// this library is imported by the generated entrypoint script.
- if (_packageConfig['flutter_test'] == null) {
+ if (_packageConfig['test_api'] == null) {
globals.printError(
'\n'
- 'Error: cannot run without a dependency on "package:flutter_test". '
+ 'Error: cannot run without a dependency on either "package:flutter_test" or "package:test". '
'Ensure the following lines are present in your pubspec.yaml:'
'\n\n'
'dev_dependencies:\n'
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
index 31a9953..ea89124 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
@@ -188,6 +188,8 @@
@override List<String> extraFrontEndOptions,
bool nullAssertions = false,
BuildInfo buildInfo,
+ String reporter,
+ String timeout,
}) async {
lastEnableObservatoryValue = enableObservatory;
return exitCode;
diff --git a/packages/flutter_tools/test/general.shard/test_compiler_test.dart b/packages/flutter_tools/test/general.shard/test_compiler_test.dart
index 1597ea3..1c6bc87 100644
--- a/packages/flutter_tools/test/general.shard/test_compiler_test.dart
+++ b/packages/flutter_tools/test/general.shard/test_compiler_test.dart
@@ -33,7 +33,7 @@
fileSystem.file('test/foo.dart').createSync(recursive: true);
fileSystem.file('.packages')
..createSync()
- ..writeAsStringSync('flutter_test:flutter_test/');
+ ..writeAsStringSync('test_api:test_api/\n');
residentCompiler = MockResidentCompiler();
});
@@ -109,7 +109,7 @@
Logger: () => BufferLogger.test(),
});
- testUsingContext('TestCompiler reports an error when there is no dependency on flutter_test', () async {
+ testUsingContext('TestCompiler reports an error when there is no dependency on flutter_test or test', () async {
final FakeTestCompiler testCompiler = FakeTestCompiler(
BuildInfo.debug,
FlutterProject.current(),
@@ -118,7 +118,8 @@
fileSystem.file('.packages').writeAsStringSync('\n');
expect(await testCompiler.compile(Uri.parse('test/foo.dart')), null);
- expect(testLogger.errorText, contains('Error: cannot run without a dependency on "package:flutter_test"'));
+ expect(testLogger.errorText, contains('Error: cannot run without a dependency on '
+ 'either "package:flutter_test" or "package:test'));
verifyNever(residentCompiler.recompile(
any,
<Uri>[Uri.parse('test/foo.dart')],