Unverified Commit 4315cdcf authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Some test cleanup for flutter_tools. (#90227)

parent 5ab6c7bc
...@@ -278,6 +278,8 @@ Future<void> _runGeneralToolTests() async { ...@@ -278,6 +278,8 @@ Future<void> _runGeneralToolTests() async {
testPaths: <String>[path.join('test', 'general.shard')], testPaths: <String>[path.join('test', 'general.shard')],
enableFlutterToolAsserts: false, enableFlutterToolAsserts: false,
// Detect unit test time regressions (poor time delay handling, etc). // Detect unit test time regressions (poor time delay handling, etc).
// This overrides the 15 minute default for tools tests.
// See the README.md and dart_test.yaml files in the flutter_tools package.
perTestTimeout: const Duration(seconds: 2), perTestTimeout: const Duration(seconds: 2),
); );
} }
...@@ -295,8 +297,6 @@ Future<void> _runWebToolTests() async { ...@@ -295,8 +297,6 @@ Future<void> _runWebToolTests() async {
path.join(flutterRoot, 'packages', 'flutter_tools'), path.join(flutterRoot, 'packages', 'flutter_tools'),
forceSingleCore: true, forceSingleCore: true,
testPaths: <String>[path.join('test', 'web.shard')], testPaths: <String>[path.join('test', 'web.shard')],
enableFlutterToolAsserts: true,
perTestTimeout: const Duration(minutes: 3),
includeLocalEngineEnv: true, includeLocalEngineEnv: true,
); );
} }
......
...@@ -39,17 +39,30 @@ $ flutter analyze ...@@ -39,17 +39,30 @@ $ flutter analyze
As with other parts of the Flutter repository, all changes in behavior [must be As with other parts of the Flutter repository, all changes in behavior [must be
tested](https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#write-test-find-bug). tested](https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#write-test-find-bug).
Tests live under the `test/` subdirectory. Tests live under the `test/` subdirectory.
- Hermetic unit tests of tool internals go under `test/general.shard`.
- Tests of tool commands go under `test/commands.shard`. Hermetic tests go under - Hermetic unit tests of tool internals go under `test/general.shard`
its `hermetic/` subdirectory. Non-hermetic tests go under its `permeable` and must run in significantly less than two seconds.
sub-directory. Avoid adding tests here and prefer writing either a unit test or a full
integration test. - Tests of tool commands go under `test/commands.shard`. Hermetic
- Integration tests (e.g. tests that run the tool in a subprocess) go under tests go under its `hermetic/` subdirectory. Non-hermetic tests go
`test/integration.shard`. under its `permeable` sub-directory. Avoid adding tests here and
prefer writing either a unit test or a full integration test.
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 - Integration tests (e.g. tests that run the tool in a subprocess) go
the test. under `test/integration.shard`.
- Slow web-related tests go in the `test/web.shard` directory.
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.
The `dart_test.yaml` file configures the timeout for these tests to be
15 minutes. The `test.dart` script that is used in CI overrides this
to two seconds for the `test/general.shard` directory, to catch
behaviour that is unexpectedly slow.
Please avoid setting any other timeouts.
#### Using local engine builds in integration tests #### Using local engine builds in integration tests
...@@ -73,29 +86,26 @@ To run all of the unit tests: ...@@ -73,29 +86,26 @@ To run all of the unit tests:
$ flutter test test/general.shard $ flutter test test/general.shard
``` ```
The tests in `test/integration.shard` are slower to run than the tests in The tests in `test/integration.shard` are slower to run than the tests
`test/general.shard`. Depending on your development computer, you might in `test/general.shard`. Depending on your development computer, you
want to increase timeouts and limit concurrency. Generally it is easier to run might want to limit concurrency. Generally it is easier to run these
these on CI, or to manually verify the behavior you are changing instead of running on CI, or to manually verify the behavior you are changing instead of
the test. running the test.
The integration tests also require the `FLUTTER_ROOT` environment variable The integration tests also require the `FLUTTER_ROOT` environment
to be set. The full invocation to run everything might therefore look something like: variable to be set. The full invocation to run everything might
therefore look something like:
```shell ```shell
$ FLUTTER_ROOT=~/path/to/flutter-sdk $ FLUTTER_ROOT=~/path/to/flutter-sdk
$ flutter test --timeout 2x --concurrency 1 $ flutter test --concurrency 1
``` ```
This will take about an hour to complete. This may take some time (on the order of an hour). The unit tests
alone take much less time (on the order of a minute).
To run only the tests in `test/general.shard` (which takes about a minute), You can run the tests in a specific file, e.g.:
in this directory run:
```shell
$ flutter test test/general.shard
```
To run the tests in a specific file, run:
```shell ```shell
$ flutter test test/general.shard/utils_test.dart $ flutter test test/general.shard/utils_test.dart
``` ```
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
# overloaded. For this reason, we set the test timeout to # overloaded. For this reason, we set the test timeout to
# significantly more than it would be by default, and we never set the # significantly more than it would be by default, and we never set the
# timeouts in the tests themselves. # timeouts in the tests themselves.
#
# For the `test/general.shard` specifically, the `dev/bots/test.dart` script
# overrides this, reducing it to only 2000ms. Unit tests must run fast!
timeout: 15m timeout: 15m
tags: tags:
......
...@@ -62,7 +62,7 @@ void main() { ...@@ -62,7 +62,7 @@ void main() {
expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true); expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true);
expect(result.exitCode, 0); expect(result.exitCode, 0);
}, timeout: const Timeout(Duration(minutes: 5))); });
testWithoutContext('simple build appbundle all targets succeeds', () async { testWithoutContext('simple build appbundle all targets succeeds', () async {
final DeferredComponentsProject project = DeferredComponentsProject(BasicDeferredComponentsConfig()); final DeferredComponentsProject project = DeferredComponentsProject(BasicDeferredComponentsConfig());
...@@ -105,7 +105,7 @@ void main() { ...@@ -105,7 +105,7 @@ void main() {
expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true); expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true);
expect(result.exitCode, 0); expect(result.exitCode, 0);
}, timeout: const Timeout(Duration(minutes: 5))); });
testWithoutContext('simple build appbundle no-deferred-components succeeds', () async { testWithoutContext('simple build appbundle no-deferred-components succeeds', () async {
final DeferredComponentsProject project = DeferredComponentsProject(BasicDeferredComponentsConfig()); final DeferredComponentsProject project = DeferredComponentsProject(BasicDeferredComponentsConfig());
...@@ -151,7 +151,7 @@ void main() { ...@@ -151,7 +151,7 @@ void main() {
expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true); expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true);
expect(result.exitCode, 0); expect(result.exitCode, 0);
}, timeout: const Timeout(Duration(minutes: 5))); });
testWithoutContext('simple build appbundle mismatched golden no-validate-deferred-components succeeds', () async { testWithoutContext('simple build appbundle mismatched golden no-validate-deferred-components succeeds', () async {
final DeferredComponentsProject project = DeferredComponentsProject(MismatchedGoldenDeferredComponentsConfig()); final DeferredComponentsProject project = DeferredComponentsProject(MismatchedGoldenDeferredComponentsConfig());
...@@ -198,7 +198,7 @@ void main() { ...@@ -198,7 +198,7 @@ void main() {
expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true); expect(archive.findFile('base/assets/flutter_assets/test_assets/asset1.txt') != null, true);
expect(result.exitCode, 0); expect(result.exitCode, 0);
}, timeout: const Timeout(Duration(minutes: 5))); });
testWithoutContext('simple build appbundle missing android dynamic feature module fails', () async { testWithoutContext('simple build appbundle missing android dynamic feature module fails', () async {
final DeferredComponentsProject project = DeferredComponentsProject(NoAndroidDynamicFeatureModuleDeferredComponentsConfig()); final DeferredComponentsProject project = DeferredComponentsProject(NoAndroidDynamicFeatureModuleDeferredComponentsConfig());
......
...@@ -104,5 +104,5 @@ void main() { ...@@ -104,5 +104,5 @@ void main() {
continuePollingValue: '', continuePollingValue: '',
matches: equals(vmServiceUri), matches: equals(vmServiceUri),
); );
}, timeout: const Timeout.factor(4)); });
} }
...@@ -78,6 +78,6 @@ String unsafeString = null; ...@@ -78,6 +78,6 @@ String unsafeString = null;
if (targetPlatform == 'ios') '--no-codesign', if (targetPlatform == 'ios') '--no-codesign',
], workingDirectory: projectRoot.path); ], workingDirectory: projectRoot.path);
expect(result.exitCode, 0); expect(result.exitCode, 0);
}, timeout: const Timeout(Duration(minutes: 3))); });
} }
} }
...@@ -71,6 +71,6 @@ int x = 'String'; ...@@ -71,6 +71,6 @@ int x = 'String';
contains("A value of type 'String' can't be assigned to a variable of type 'int'."), contains("A value of type 'String' can't be assigned to a variable of type 'int'."),
); );
expect(result.exitCode, 1); expect(result.exitCode, 1);
}, timeout: const Timeout(Duration(minutes: 3))); });
} }
} }
...@@ -69,5 +69,5 @@ void main() { ...@@ -69,5 +69,5 @@ void main() {
continuePollingValue: '', continuePollingValue: '',
matches: isNotEmpty, matches: isNotEmpty,
); );
}, timeout: const Timeout.factor(4)); });
} }
...@@ -90,5 +90,5 @@ void main() { ...@@ -90,5 +90,5 @@ void main() {
'app-release.apk', 'app-release.apk',
); );
expect(fileSystem.file(exampleAppApk), exists); expect(fileSystem.file(exampleAppApk), exists);
}, timeout: const Timeout(Duration(minutes: 5))); });
} }
...@@ -145,8 +145,6 @@ void main() { ...@@ -145,8 +145,6 @@ void main() {
...getLocalEngineArguments(), ...getLocalEngineArguments(),
'clean', 'clean',
], workingDirectory: workingDirectory); ], workingDirectory: workingDirectory);
}, skip: !platform.isMacOS, // [intended] only makes sense for macos platform. }, skip: !platform.isMacOS); // [intended] only makes sense for macos platform.
timeout: const Timeout(Duration(minutes: 5)),
);
} }
} }
...@@ -25,10 +25,7 @@ ...@@ -25,10 +25,7 @@
// @dart = 2.8 // @dart = 2.8
// This file is ready to transition, just uncomment /*?*/, /*!*/, and /*late*/. // This file is ready to transition, just uncomment /*?*/, /*!*/, and /*late*/.
// TODO(gspencergoog): Remove this tag once this test's state leaks/test // This file intentionally assumes the tests run in order.
// dependencies have been fixed.
// https://github.com/flutter/flutter/issues/85160
// Fails with "flutter test --test-randomize-ordering-seed=1000"
@Tags(<String>['no-shuffle']) @Tags(<String>['no-shuffle'])
import 'dart:async'; import 'dart:async';
...@@ -40,7 +37,7 @@ import 'package:pedantic/pedantic.dart'; ...@@ -40,7 +37,7 @@ import 'package:pedantic/pedantic.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../src/common.dart'; import '../src/common.dart';
import 'test_utils.dart' show fileSystem, platform; import 'test_utils.dart' show fileSystem;
const ProcessManager processManager = LocalProcessManager(); const ProcessManager processManager = LocalProcessManager();
final String flutterRoot = getFlutterRoot(); final String flutterRoot = getFlutterRoot();
...@@ -189,7 +186,7 @@ Future<ProcessTestResult> runFlutter( ...@@ -189,7 +186,7 @@ Future<ProcessTestResult> runFlutter(
List<Transition> transitions, { List<Transition> transitions, {
bool debug = false, bool debug = false,
bool logging = true, bool logging = true,
Duration expectedMaxDuration = const Duration(minutes: 10), // must be less than test timeout of 15 minutes! Duration expectedMaxDuration = const Duration(minutes: 10), // must be less than test timeout of 15 minutes! See ../../dart_test.yaml.
}) async { }) async {
final Stopwatch clock = Stopwatch()..start(); final Stopwatch clock = Stopwatch()..start();
final Process process = await processManager.start( final Process process = await processManager.start(
...@@ -358,7 +355,7 @@ void main() { ...@@ -358,7 +355,7 @@ void main() {
} finally { } finally {
tryToDelete(fileSystem.directory(tempDirectory)); tryToDelete(fileSystem.directory(tempDirectory));
} }
}, skip: platform.isWindows); // https://github.com/flutter/flutter/issues/87924 }, skip: Platform.isWindows); // [intended] Windows doesn't support sending signals so we don't care if it can store the PID.
testWithoutContext('flutter run handle SIGUSR1/2', () async { testWithoutContext('flutter run handle SIGUSR1/2', () async {
final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync(); final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync();
...@@ -622,5 +619,5 @@ void main() { ...@@ -622,5 +619,5 @@ void main() {
'', '',
'Application finished.', 'Application finished.',
]); ]);
}, skip: Platform.isWindows); // TODO(zanderso): Re-enable when this test is reliable on device lab, https://github.com/flutter/flutter/issues/81556 });
} }
...@@ -148,7 +148,6 @@ Matcher containsIgnoringWhitespace(String toSearch) { ...@@ -148,7 +148,6 @@ Matcher containsIgnoringWhitespace(String toSearch) {
@isTest @isTest
void test(String description, FutureOr<void> Function() body, { void test(String description, FutureOr<void> Function() body, {
String? testOn, String? testOn,
Timeout? timeout,
dynamic skip, dynamic skip,
List<String>? tags, List<String>? tags,
Map<String, dynamic>? onPlatform, Map<String, dynamic>? onPlatform,
...@@ -162,12 +161,14 @@ void test(String description, FutureOr<void> Function() body, { ...@@ -162,12 +161,14 @@ void test(String description, FutureOr<void> Function() body, {
}); });
return body(); return body();
}, },
timeout: timeout,
skip: skip, skip: skip,
tags: tags, tags: tags,
onPlatform: onPlatform, onPlatform: onPlatform,
retry: retry, retry: retry,
testOn: testOn, testOn: testOn,
// We don't support "timeout"; see ../../dart_test.yaml which
// configures all tests to have a 15 minute timeout which should
// definitely be enough.
); );
} }
...@@ -182,7 +183,6 @@ void test(String description, FutureOr<void> Function() body, { ...@@ -182,7 +183,6 @@ void test(String description, FutureOr<void> Function() body, {
@isTest @isTest
void testWithoutContext(String description, FutureOr<void> Function() body, { void testWithoutContext(String description, FutureOr<void> Function() body, {
String? testOn, String? testOn,
Timeout? timeout,
dynamic skip, dynamic skip,
List<String>? tags, List<String>? tags,
Map<String, dynamic>? onPlatform, Map<String, dynamic>? onPlatform,
...@@ -194,12 +194,14 @@ void testWithoutContext(String description, FutureOr<void> Function() body, { ...@@ -194,12 +194,14 @@ void testWithoutContext(String description, FutureOr<void> Function() body, {
contextKey: const _NoContext(), contextKey: const _NoContext(),
}); });
}, },
timeout: timeout,
skip: skip, skip: skip,
tags: tags, tags: tags,
onPlatform: onPlatform, onPlatform: onPlatform,
retry: retry, retry: retry,
testOn: testOn, testOn: testOn,
// We don't support "timeout"; see ../../dart_test.yaml which
// configures all tests to have a 15 minute timeout which should
// definitely be enough.
); );
} }
......
...@@ -62,7 +62,6 @@ void testUsingContext( ...@@ -62,7 +62,6 @@ void testUsingContext(
Map<Type, Generator> overrides = const <Type, Generator>{}, Map<Type, Generator> overrides = const <Type, Generator>{},
bool initializeFlutterRoot = true, bool initializeFlutterRoot = true,
String testOn, String testOn,
Timeout timeout,
bool skip, // should default to `false`, but https://github.com/dart-lang/test/issues/545 doesn't allow this bool skip, // should default to `false`, but https://github.com/dart-lang/test/issues/545 doesn't allow this
}) { }) {
if (overrides[FileSystem] != null && overrides[ProcessManager] == null) { if (overrides[FileSystem] != null && overrides[ProcessManager] == null) {
...@@ -167,7 +166,10 @@ void testUsingContext( ...@@ -167,7 +166,10 @@ void testUsingContext(
// BotDetector implementation in the overrides. // BotDetector implementation in the overrides.
BotDetector: overrides[BotDetector] ?? () => const FakeBotDetector(true), BotDetector: overrides[BotDetector] ?? () => const FakeBotDetector(true),
}); });
}, testOn: testOn, skip: skip, timeout: timeout); }, testOn: testOn, skip: skip);
// We don't support "timeout"; see ../../dart_test.yaml which
// configures all tests to have a 15 minute timeout which should
// definitely be enough.
} }
void _printBufferedErrors(AppContext testContext) { void _printBufferedErrors(AppContext testContext) {
......
...@@ -12,9 +12,9 @@ import 'package:flutter_tools/src/base/os.dart'; ...@@ -12,9 +12,9 @@ import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/web/chrome.dart'; import 'package:flutter_tools/src/web/chrome.dart';
import '../../src/common.dart'; import '../src/common.dart';
import '../../src/fake_process_manager.dart'; import '../src/fake_process_manager.dart';
import '../../src/fakes.dart'; import '../src/fakes.dart';
const List<String> kChromeArgs = <String>[ const List<String> kChromeArgs = <String>[
'--disable-background-timer-throttling', '--disable-background-timer-throttling',
...@@ -547,7 +547,7 @@ void main() { ...@@ -547,7 +547,7 @@ void main() {
contains('Unable to connect to Chrome debug port:'), contains('Unable to connect to Chrome debug port:'),
); );
expect(logger.errorText, contains('SocketException')); expect(logger.errorText, contains('SocketException'));
}, timeout: const Timeout.factor(2)); });
} }
Future<Chromium> _testLaunchChrome(String userDataDir, FakeProcessManager processManager, ChromiumLauncher chromeLauncher) { Future<Chromium> _testLaunchChrome(String userDataDir, FakeProcessManager processManager, ChromiumLauncher chromeLauncher) {
......
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