[flutter_tools] allow using flutter test for testing the tool too (#69911)
This commit is contained in:
parent
a0ec4d67e9
commit
5fedad9173
@ -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:
|
||||
|
@ -15,14 +15,14 @@ which we follow.
|
||||
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 @@ followed by command-line arguments, as usual.
|
||||
|
||||
To run the analyzer on Flutter Tools, in this directory run:
|
||||
```shell
|
||||
$ ../../bin/flutter analyze
|
||||
$ flutter analyze
|
||||
```
|
||||
|
||||
### Writing tests
|
||||
@ -50,12 +50,6 @@ In general, the tests for the code in a file called `file.dart` should go in a
|
||||
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 @@ environment variable. This second variable is not necessary if the `flutter` and
|
||||
|
||||
```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 @@ The tests in `test/integration.shard` are slower to run than the tests in
|
||||
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
|
||||
|
@ -131,6 +131,17 @@ class TestCommand extends FlutterCommand {
|
||||
'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 @@ class TestCommand extends FlutterCommand {
|
||||
web: stringArg('platform') == 'chrome',
|
||||
randomSeed: stringArg('test-randomize-ordering-seed'),
|
||||
nullAssertions: boolArg(FlutterOptions.kNullAssertions),
|
||||
reporter: stringArg('reporter'),
|
||||
timeout: stringArg('timeout'),
|
||||
);
|
||||
|
||||
if (collector != null) {
|
||||
|
@ -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 @@ String generateTestBootstrap({
|
||||
bool updateGoldens = false,
|
||||
String languageVersionHeader = '',
|
||||
bool nullSafety = false,
|
||||
bool flutterTestDep = true,
|
||||
}) {
|
||||
assert(testUrl != null);
|
||||
assert(host != null);
|
||||
@ -142,8 +144,13 @@ import 'dart:async';
|
||||
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 @@ void main() {
|
||||
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 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
// 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 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
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 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
testConfigFile: findTestConfigFile(globals.fs.file(testUrl)),
|
||||
host: host,
|
||||
updateGoldens: updateGoldens,
|
||||
flutterTestDep: _packageConfig['flutter_test'] != null,
|
||||
languageVersionHeader: '// @dart=${languageVersion.major}.${languageVersion.minor}'
|
||||
);
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ abstract class FlutterTestRunner {
|
||||
String randomSeed,
|
||||
bool nullAssertions = false,
|
||||
@required BuildInfo buildInfo,
|
||||
String reporter,
|
||||
String timeout,
|
||||
});
|
||||
}
|
||||
|
||||
@ -83,6 +85,8 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
||||
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 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
||||
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],
|
||||
|
@ -134,10 +134,10 @@ class TestCompiler {
|
||||
);
|
||||
// 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'
|
||||
|
@ -188,6 +188,8 @@ class FakeFlutterTestRunner implements FlutterTestRunner {
|
||||
@override List<String> extraFrontEndOptions,
|
||||
bool nullAssertions = false,
|
||||
BuildInfo buildInfo,
|
||||
String reporter,
|
||||
String timeout,
|
||||
}) async {
|
||||
lastEnableObservatoryValue = enableObservatory;
|
||||
return exitCode;
|
||||
|
@ -33,7 +33,7 @@ void main() {
|
||||
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 @@ void main() {
|
||||
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 @@ void main() {
|
||||
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')],
|
||||
|
Loading…
x
Reference in New Issue
Block a user