blob: 878b9f210427ce1ed81146d047c29a74ec1c40eb [file] [log] [blame]
// 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 '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../device.dart';
import '../globals.dart' as globals;
import '../project.dart';
import '../web/chrome.dart';
import '../web/memory_fs.dart';
import 'flutter_platform.dart' as loader;
import 'flutter_web_platform.dart';
import 'test_time_recorder.dart';
import 'test_wrapper.dart';
import 'watcher.dart';
import 'web_test_compiler.dart';
/// A class that abstracts launching the test process from the test runner.
abstract class FlutterTestRunner {
const factory FlutterTestRunner() = _FlutterTestRunnerImpl;
/// Runs tests using package:test and the Flutter engine.
Future<int> runTests(
TestWrapper testWrapper,
List<String> testFiles, {
required DebuggingOptions debuggingOptions,
List<String> names = const <String>[],
List<String> plainNames = const <String>[],
String? tags,
String? excludeTags,
bool enableObservatory = false,
bool ipv6 = false,
bool machine = false,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
bool updateGoldens = false,
TestWatcher? watcher,
required int? concurrency,
String? testAssetDirectory,
FlutterProject? flutterProject,
String? icudtlPath,
Directory? coverageDirectory,
bool web = false,
String? randomSeed,
String? reporter,
String? timeout,
bool runSkipped = false,
int? shardIndex,
int? totalShards,
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
TestTimeRecorder? testTimeRecorder,
});
}
class _FlutterTestRunnerImpl implements FlutterTestRunner {
const _FlutterTestRunnerImpl();
@override
Future<int> runTests(
TestWrapper testWrapper,
List<String> testFiles, {
required DebuggingOptions debuggingOptions,
List<String> names = const <String>[],
List<String> plainNames = const <String>[],
String? tags,
String? excludeTags,
bool enableObservatory = false,
bool ipv6 = false,
bool machine = false,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
bool updateGoldens = false,
TestWatcher? watcher,
required int? concurrency,
String? testAssetDirectory,
FlutterProject? flutterProject,
String? icudtlPath,
Directory? coverageDirectory,
bool web = false,
String? randomSeed,
String? reporter,
String? timeout,
bool runSkipped = false,
int? shardIndex,
int? totalShards,
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
TestTimeRecorder? testTimeRecorder,
}) async {
// Configure package:test to use the Flutter engine for child processes.
final String shellPath = globals.artifacts!.getArtifactPath(Artifact.flutterTester);
// Compute the command-line arguments for package:test.
final List<String> testArgs = <String>[
if (!globals.terminal.supportsColor)
'--no-color',
if (debuggingOptions.startPaused)
'--pause-after-load',
if (machine)
...<String>['-r', 'json']
else if (reporter != null)
...<String>['-r', reporter],
if (timeout != null)
...<String>['--timeout', timeout],
'--concurrency=$concurrency',
for (final String name in names)
...<String>['--name', name],
for (final String plainName in plainNames)
...<String>['--plain-name', plainName],
if (randomSeed != null)
'--test-randomize-ordering-seed=$randomSeed',
if (tags != null)
...<String>['--tags', tags],
if (excludeTags != null)
...<String>['--exclude-tags', excludeTags],
if (runSkipped)
'--run-skipped',
if (totalShards != null)
'--total-shards=$totalShards',
if (shardIndex != null)
'--shard-index=$shardIndex',
'--chain-stack-traces',
];
if (web) {
final String tempBuildDir = globals.fs.systemTempDirectory
.createTempSync('flutter_test.')
.absolute
.uri
.toFilePath();
final WebMemoryFS result = await WebTestCompiler(
logger: globals.logger,
fileSystem: globals.fs,
platform: globals.platform,
artifacts: globals.artifacts!,
processManager: globals.processManager,
config: globals.config,
).initialize(
projectDirectory: flutterProject!.directory,
testOutputDir: tempBuildDir,
testFiles: testFiles,
buildInfo: debuggingOptions.buildInfo,
);
if (result == null) {
throwToolExit('Failed to compile tests');
}
testArgs
..add('--platform=chrome')
..add('--')
..addAll(testFiles);
testWrapper.registerPlatformPlugin(
<Runtime>[Runtime.chrome],
() {
return FlutterWebPlatform.start(
flutterProject.directory.path,
updateGoldens: updateGoldens,
shellPath: shellPath,
flutterProject: flutterProject,
pauseAfterLoad: debuggingOptions.startPaused,
nullAssertions: debuggingOptions.nullAssertions,
buildInfo: debuggingOptions.buildInfo,
webMemoryFS: result,
logger: globals.logger,
fileSystem: globals.fs,
artifacts: globals.artifacts,
processManager: globals.processManager,
chromiumLauncher: ChromiumLauncher(
fileSystem: globals.fs,
platform: globals.platform,
processManager: globals.processManager,
operatingSystemUtils: globals.os,
browserFinder: findChromeExecutable,
logger: globals.logger,
),
cache: globals.cache,
testTimeRecorder: testTimeRecorder,
);
},
);
await testWrapper.main(testArgs);
return exitCode;
}
testArgs
..add('--')
..addAll(testFiles);
final InternetAddressType serverType =
ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4;
final loader.FlutterPlatform platform = loader.installHook(
testWrapper: testWrapper,
shellPath: shellPath,
debuggingOptions: debuggingOptions,
watcher: watcher,
enableObservatory: enableObservatory,
machine: machine,
serverType: serverType,
precompiledDillPath: precompiledDillPath,
precompiledDillFiles: precompiledDillFiles,
updateGoldens: updateGoldens,
testAssetDirectory: testAssetDirectory,
projectRootDirectory: globals.fs.currentDirectory.uri,
flutterProject: flutterProject,
icudtlPath: icudtlPath,
integrationTestDevice: integrationTestDevice,
integrationTestUserIdentifier: integrationTestUserIdentifier,
testTimeRecorder: testTimeRecorder,
);
try {
globals.printTrace('running test package with arguments: $testArgs');
await testWrapper.main(testArgs);
// test.main() sets dart:io's exitCode global.
globals.printTrace('test package returned with exit code $exitCode');
return exitCode;
} finally {
await platform.close();
}
}
}