[flutter_plugin_tools] Migrate firebase-test-lab to new base command (#4116)

Migrates firebase-test-lab to use the new package-looping base command.

Other changes:
- Extracts several helpers to make the main flow easier to follow
- Removes support for finding and running `*_e2e.dart` files, since we no longer use that file structure for integration tests.

Part of https://github.com/flutter/flutter/issues/83413
This commit is contained in:
stuartmorgan
2021-06-30 11:43:41 -07:00
committed by GitHub
parent ea72f74d0b
commit ec9233eb41
3 changed files with 249 additions and 229 deletions

View File

@ -1,3 +1,9 @@
## NEXT
- Modified the output format of many commands
- **Breaking change**: `firebase-test-lab` no longer supports `*_e2e.dart`
files, only `integration_test/*_test.dart`.
## 0.3.0 ## 0.3.0
- Add a --build-id flag to `firebase-test-lab` instead of hard-coding the use of - Add a --build-id flag to `firebase-test-lab` instead of hard-coding the use of

View File

@ -10,18 +10,16 @@ import 'package:path/path.dart' as p;
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'common/core.dart'; import 'common/core.dart';
import 'common/plugin_command.dart'; import 'common/package_looping_command.dart';
import 'common/process_runner.dart'; import 'common/process_runner.dart';
/// A command to run tests via Firebase test lab. /// A command to run tests via Firebase test lab.
class FirebaseTestLabCommand extends PluginCommand { class FirebaseTestLabCommand extends PackageLoopingCommand {
/// Creates an instance of the test runner command. /// Creates an instance of the test runner command.
FirebaseTestLabCommand( FirebaseTestLabCommand(
Directory packagesDir, { Directory packagesDir, {
ProcessRunner processRunner = const ProcessRunner(), ProcessRunner processRunner = const ProcessRunner(),
Print print = print, }) : super(packagesDir, processRunner: processRunner) {
}) : _print = print,
super(packagesDir, processRunner: processRunner) {
argParser.addOption( argParser.addOption(
'project', 'project',
defaultsTo: 'flutter-infra', defaultsTo: 'flutter-infra',
@ -74,8 +72,6 @@ class FirebaseTestLabCommand extends PluginCommand {
static const String _gradleWrapper = 'gradlew'; static const String _gradleWrapper = 'gradlew';
final Print _print;
Completer<void>? _firebaseProjectConfigured; Completer<void>? _firebaseProjectConfigured;
Future<void> _configureFirebaseProject() async { Future<void> _configureFirebaseProject() async {
@ -86,7 +82,7 @@ class FirebaseTestLabCommand extends PluginCommand {
final String serviceKey = getStringArg('service-key'); final String serviceKey = getStringArg('service-key');
if (serviceKey.isEmpty) { if (serviceKey.isEmpty) {
_print('No --service-key provided; skipping gcloud authorization'); print('No --service-key provided; skipping gcloud authorization');
} else { } else {
await processRunner.run( await processRunner.run(
'gcloud', 'gcloud',
@ -105,10 +101,10 @@ class FirebaseTestLabCommand extends PluginCommand {
getStringArg('project'), getStringArg('project'),
]); ]);
if (exitCode == 0) { if (exitCode == 0) {
_print('\nFirebase project configured.'); print('\nFirebase project configured.');
return; return;
} else { } else {
_print( print(
'\nWarning: gcloud config set returned a non-zero exit code. Continuing anyway.'); '\nWarning: gcloud config set returned a non-zero exit code. Continuing anyway.');
} }
} }
@ -116,172 +112,155 @@ class FirebaseTestLabCommand extends PluginCommand {
} }
@override @override
Future<void> run() async { Future<List<String>> runForPackage(Directory package) async {
final Stream<Directory> packagesWithTests = getPackages().where( if (!package
(Directory d) => .childDirectory('example')
isFlutterPackage(d) && .childDirectory('android')
d .childDirectory('app')
.childDirectory('example') .childDirectory('src')
.childDirectory('android') .childDirectory('androidTest')
.childDirectory('app') .existsSync()) {
.childDirectory('src') printSkip('No example with androidTest directory');
.childDirectory('androidTest') return PackageLoopingCommand.success;
.existsSync()); }
final List<String> failingPackages = <String>[]; final List<String> errors = <String>[];
final List<String> missingFlutterBuild = <String>[];
int resultsCounter =
0; // We use a unique GCS bucket for each Firebase Test Lab run
await for (final Directory package in packagesWithTests) {
// See https://github.com/flutter/flutter/issues/38983
final Directory exampleDirectory = package.childDirectory('example'); final Directory exampleDirectory = package.childDirectory('example');
final String packageName = final Directory androidDirectory =
p.relative(package.path, from: packagesDir.path); exampleDirectory.childDirectory('android');
_print('\nRUNNING FIREBASE TEST LAB TESTS for $packageName');
final Directory androidDirectory = // Ensures that gradle wrapper exists
exampleDirectory.childDirectory('android'); if (!await _ensureGradleWrapperExists(androidDirectory)) {
errors.add('Unable to build example apk');
return errors;
}
final String enableExperiment = getStringArg(kEnableExperiment); await _configureFirebaseProject();
final String encodedEnableExperiment =
Uri.encodeComponent('--enable-experiment=$enableExperiment');
// Ensures that gradle wrapper exists if (!await _runGradle(androidDirectory, 'app:assembleAndroidTest')) {
if (!androidDirectory.childFile(_gradleWrapper).existsSync()) { errors.add('Unable to assemble androidTest');
final int exitCode = await processRunner.runAndStream( return errors;
'flutter', }
<String>[
'build',
'apk',
if (enableExperiment.isNotEmpty)
'--enable-experiment=$enableExperiment',
],
workingDir: androidDirectory);
if (exitCode != 0) { // Used within the loop to ensure a unique GCS output location for each
failingPackages.add(packageName); // test file's run.
continue; int resultsCounter = 0;
} for (final File test in _findIntegrationTestFiles(package)) {
final String testName = p.relative(test.path, from: package.path);
print('Testing $testName...');
if (!await _runGradle(androidDirectory, 'app:assembleDebug',
testFile: test)) {
printError('Could not build $testName');
errors.add('$testName failed to build');
continue; continue;
} }
final String buildId = getStringArg('build-id');
final String testRunId = getStringArg('test-run-id');
final String resultsDir =
'plugins_android_test/${getPackageDescription(package)}/$buildId/$testRunId/${resultsCounter++}/';
final List<String> args = <String>[
'firebase',
'test',
'android',
'run',
'--type',
'instrumentation',
'--app',
'build/app/outputs/apk/debug/app-debug.apk',
'--test',
'build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk',
'--timeout',
'5m',
'--results-bucket=${getStringArg('results-bucket')}',
'--results-dir=$resultsDir',
];
for (final String device in getStringListArg('device')) {
args.addAll(<String>['--device', device]);
}
final int exitCode = await processRunner.runAndStream('gcloud', args,
workingDir: exampleDirectory);
await _configureFirebaseProject(); if (exitCode != 0) {
printError('Test failure for $testName');
errors.add('$testName failed tests');
}
}
return errors;
}
int exitCode = await processRunner.runAndStream( /// Checks that 'gradlew' exists in [androidDirectory], and if not runs a
p.join(androidDirectory.path, _gradleWrapper), /// Flutter build to generate it.
///
/// Returns true if either gradlew was already present, or the build succeeds.
Future<bool> _ensureGradleWrapperExists(Directory androidDirectory) async {
if (!androidDirectory.childFile(_gradleWrapper).existsSync()) {
print('Running flutter build apk...');
final String experiment = getStringArg(kEnableExperiment);
final int exitCode = await processRunner.runAndStream(
'flutter',
<String>[ <String>[
'app:assembleAndroidTest', 'build',
'-Pverbose=true', 'apk',
if (enableExperiment.isNotEmpty) if (experiment.isNotEmpty) '--enable-experiment=$experiment',
'-Pextra-front-end-options=$encodedEnableExperiment',
if (enableExperiment.isNotEmpty)
'-Pextra-gen-snapshot-options=$encodedEnableExperiment',
], ],
workingDir: androidDirectory); workingDir: androidDirectory);
if (exitCode != 0) { if (exitCode != 0) {
failingPackages.add(packageName); return false;
continue;
}
// Look for tests recursively in folders that start with 'test' and that
// live in the root or example folders.
bool isTestDir(FileSystemEntity dir) {
return dir is Directory &&
(p.basename(dir.path).startsWith('test') ||
p.basename(dir.path) == 'integration_test');
}
final List<Directory> testDirs =
package.listSync().where(isTestDir).cast<Directory>().toList();
final Directory example = package.childDirectory('example');
testDirs.addAll(
example.listSync().where(isTestDir).cast<Directory>().toList());
for (final Directory testDir in testDirs) {
bool isE2ETest(FileSystemEntity file) {
return file.path.endsWith('_e2e.dart') ||
(file.parent.basename == 'integration_test' &&
file.path.endsWith('_test.dart'));
}
final List<FileSystemEntity> testFiles = testDir
.listSync(recursive: true, followLinks: true)
.where(isE2ETest)
.toList();
for (final FileSystemEntity test in testFiles) {
exitCode = await processRunner.runAndStream(
p.join(androidDirectory.path, _gradleWrapper),
<String>[
'app:assembleDebug',
'-Pverbose=true',
'-Ptarget=${test.path}',
if (enableExperiment.isNotEmpty)
'-Pextra-front-end-options=$encodedEnableExperiment',
if (enableExperiment.isNotEmpty)
'-Pextra-gen-snapshot-options=$encodedEnableExperiment',
],
workingDir: androidDirectory);
if (exitCode != 0) {
failingPackages.add(packageName);
continue;
}
final String buildId = getStringArg('build-id');
final String testRunId = getStringArg('test-run-id');
final String resultsDir =
'plugins_android_test/$packageName/$buildId/$testRunId/${resultsCounter++}/';
final List<String> args = <String>[
'firebase',
'test',
'android',
'run',
'--type',
'instrumentation',
'--app',
'build/app/outputs/apk/debug/app-debug.apk',
'--test',
'build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk',
'--timeout',
'5m',
'--results-bucket=${getStringArg('results-bucket')}',
'--results-dir=$resultsDir',
];
for (final String device in getStringListArg('device')) {
args.addAll(<String>['--device', device]);
}
exitCode = await processRunner.runAndStream('gcloud', args,
workingDir: exampleDirectory);
if (exitCode != 0) {
failingPackages.add(packageName);
continue;
}
}
} }
} }
return true;
}
_print('\n\n'); /// Builds [target] using 'gradlew' in the given [directory]. Assumes
if (failingPackages.isNotEmpty) { /// 'gradlew' already exists.
_print( ///
'The instrumentation tests for the following packages are failing (see above for' /// [testFile] optionally does the Flutter build with the given test file as
'details):'); /// the build target.
for (final String package in failingPackages) { ///
_print(' * $package'); /// Returns true if the command succeeds.
} Future<bool> _runGradle(
Directory directory,
String target, {
File? testFile,
}) async {
final String experiment = getStringArg(kEnableExperiment);
final String? extraOptions = experiment.isNotEmpty
? Uri.encodeComponent('--enable-experiment=$experiment')
: null;
final int exitCode = await processRunner.runAndStream(
p.join(directory.path, _gradleWrapper),
<String>[
target,
'-Pverbose=true',
if (testFile != null) '-Ptarget=${testFile.path}',
if (extraOptions != null) '-Pextra-front-end-options=$extraOptions',
if (extraOptions != null)
'-Pextra-gen-snapshot-options=$extraOptions',
],
workingDir: directory);
if (exitCode != 0) {
return false;
} }
if (missingFlutterBuild.isNotEmpty) { return true;
_print('Run "pub global run flutter_plugin_tools build-examples --apk" on' }
'the following packages before executing tests again:');
for (final String package in missingFlutterBuild) { /// Finds and returns all integration test files for [package].
_print(' * $package'); Iterable<File> _findIntegrationTestFiles(Directory package) sync* {
} final Directory integrationTestDir =
package.childDirectory('example').childDirectory('integration_test');
if (!integrationTestDir.existsSync()) {
return;
} }
if (failingPackages.isNotEmpty || missingFlutterBuild.isNotEmpty) { yield* integrationTestDir
throw ToolExit(1); .listSync(recursive: true, followLinks: true)
} .where((FileSystemEntity file) =>
file is File && file.basename.endsWith('_test.dart'))
_print('All Firebase Test Lab tests successful!'); .cast<File>();
} }
} }

View File

@ -18,18 +18,15 @@ void main() {
group('$FirebaseTestLabCommand', () { group('$FirebaseTestLabCommand', () {
FileSystem fileSystem; FileSystem fileSystem;
late Directory packagesDir; late Directory packagesDir;
late List<String> printedMessages;
late CommandRunner<void> runner; late CommandRunner<void> runner;
late RecordingProcessRunner processRunner; late RecordingProcessRunner processRunner;
setUp(() { setUp(() {
fileSystem = MemoryFileSystem(); fileSystem = MemoryFileSystem();
packagesDir = createPackagesDirectory(fileSystem: fileSystem); packagesDir = createPackagesDirectory(fileSystem: fileSystem);
printedMessages = <String>[];
processRunner = RecordingProcessRunner(); processRunner = RecordingProcessRunner();
final FirebaseTestLabCommand command = FirebaseTestLabCommand(packagesDir, final FirebaseTestLabCommand command =
processRunner: processRunner, FirebaseTestLabCommand(packagesDir, processRunner: processRunner);
print: (Object? message) => printedMessages.add(message.toString()));
runner = CommandRunner<void>( runner = CommandRunner<void>(
'firebase_test_lab_command', 'Test for $FirebaseTestLabCommand'); 'firebase_test_lab_command', 'Test for $FirebaseTestLabCommand');
@ -48,32 +45,31 @@ void main() {
'example/should_not_run_e2e.dart', 'example/should_not_run_e2e.dart',
'example/android/app/src/androidTest/MainActivityTest.java', 'example/android/app/src/androidTest/MainActivityTest.java',
]); ]);
await expectLater(
() => runCapturingPrint(runner, <String>['firebase-test-lab']), Error? commandError;
throwsA(const TypeMatcher<ToolExit>())); final List<String> output = await runCapturingPrint(
runner, <String>['firebase-test-lab'], errorHandler: (Error e) {
commandError = e;
});
expect(commandError, isA<ToolExit>());
expect( expect(
printedMessages, output,
contains( contains(
'\nWarning: gcloud config set returned a non-zero exit code. Continuing anyway.')); '\nWarning: gcloud config set returned a non-zero exit code. Continuing anyway.'));
}); });
test('runs e2e tests', () async { test('runs integration tests', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[ createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'test/plugin_test.dart', 'test/plugin_test.dart',
'test/plugin_e2e.dart', 'example/integration_test/bar_test.dart',
'should_not_run_e2e.dart',
'lib/test/should_not_run_e2e.dart',
'example/test/plugin_e2e.dart',
'example/test_driver/plugin_e2e.dart',
'example/test_driver/plugin_e2e_test.dart',
'example/integration_test/foo_test.dart', 'example/integration_test/foo_test.dart',
'example/integration_test/should_not_run.dart', 'example/integration_test/should_not_run.dart',
'example/android/gradlew', 'example/android/gradlew',
'example/should_not_run_e2e.dart',
'example/android/app/src/androidTest/MainActivityTest.java', 'example/android/app/src/androidTest/MainActivityTest.java',
]); ]);
await runCapturingPrint(runner, <String>[ final List<String> output = await runCapturingPrint(runner, <String>[
'firebase-test-lab', 'firebase-test-lab',
'--device', '--device',
'model=flame,version=29', 'model=flame,version=29',
@ -86,14 +82,17 @@ void main() {
]); ]);
expect( expect(
printedMessages, output,
orderedEquals(<String>[ containsAllInOrder(<Matcher>[
'\nRUNNING FIREBASE TEST LAB TESTS for plugin', contains('Running for plugin'),
'\nFirebase project configured.', contains('Firebase project configured.'),
'\n\n', contains('Testing example/integration_test/bar_test.dart...'),
'All Firebase Test Lab tests successful!', contains('Testing example/integration_test/foo_test.dart...'),
]), ]),
); );
expect(output, isNot(contains('test/plugin_test.dart')));
expect(output,
isNot(contains('example/integration_test/should_not_run.dart')));
expect( expect(
processRunner.recordedCalls, processRunner.recordedCalls,
@ -111,7 +110,7 @@ void main() {
'/packages/plugin/example/android'), '/packages/plugin/example/android'),
ProcessCall( ProcessCall(
'/packages/plugin/example/android/gradlew', '/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/test/plugin_e2e.dart' 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/bar_test.dart'
.split(' '), .split(' '),
'/packages/plugin/example/android'), '/packages/plugin/example/android'),
ProcessCall( ProcessCall(
@ -121,7 +120,7 @@ void main() {
'/packages/plugin/example'), '/packages/plugin/example'),
ProcessCall( ProcessCall(
'/packages/plugin/example/android/gradlew', '/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/test/plugin_e2e.dart' 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart'
.split(' '), .split(' '),
'/packages/plugin/example/android'), '/packages/plugin/example/android'),
ProcessCall( ProcessCall(
@ -129,16 +128,91 @@ void main() {
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/1/ --device model=flame,version=29 --device model=seoul,version=26' 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/1/ --device model=flame,version=29 --device model=seoul,version=26'
.split(' '), .split(' '),
'/packages/plugin/example'), '/packages/plugin/example'),
]),
);
});
test('skips packages with no androidTest directory', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/integration_test/foo_test.dart',
'example/android/gradlew',
]);
final List<String> output = await runCapturingPrint(runner, <String>[
'firebase-test-lab',
'--device',
'model=flame,version=29',
'--device',
'model=seoul,version=26',
'--test-run-id',
'testRunId',
'--build-id',
'buildId',
]);
expect(
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin'),
contains('No example with androidTest directory'),
]),
);
expect(output,
isNot(contains('Testing example/integration_test/foo_test.dart...')));
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[]),
);
});
test('builds if gradlew is missing', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/integration_test/foo_test.dart',
'example/android/app/src/androidTest/MainActivityTest.java',
]);
final List<String> output = await runCapturingPrint(runner, <String>[
'firebase-test-lab',
'--device',
'model=flame,version=29',
'--device',
'model=seoul,version=26',
'--test-run-id',
'testRunId',
'--build-id',
'buildId',
]);
expect(
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin'),
contains('Running flutter build apk...'),
contains('Firebase project configured.'),
contains('Testing example/integration_test/foo_test.dart...'),
]),
);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall( ProcessCall(
'/packages/plugin/example/android/gradlew', 'flutter',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/test_driver/plugin_e2e.dart' 'build apk'.split(' '),
.split(' '), '/packages/plugin/example/android',
'/packages/plugin/example/android'), ),
ProcessCall( ProcessCall(
'gcloud', 'gcloud',
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/2/ --device model=flame,version=29 --device model=seoul,version=26' 'auth activate-service-account --key-file=${Platform.environment['HOME']}/gcloud-service-key.json'
.split(' '), .split(' '),
'/packages/plugin/example'), null),
ProcessCall(
'gcloud', 'config set project flutter-infra'.split(' '), null),
ProcessCall(
'/packages/plugin/example/android/gradlew',
'app:assembleAndroidTest -Pverbose=true'.split(' '),
'/packages/plugin/example/android'),
ProcessCall( ProcessCall(
'/packages/plugin/example/android/gradlew', '/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart' 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart'
@ -146,7 +220,7 @@ void main() {
'/packages/plugin/example/android'), '/packages/plugin/example/android'),
ProcessCall( ProcessCall(
'gcloud', 'gcloud',
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/3/ --device model=flame,version=29 --device model=seoul,version=26' 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=flame,version=29 --device model=seoul,version=26'
.split(' '), .split(' '),
'/packages/plugin/example'), '/packages/plugin/example'),
]), ]),
@ -155,17 +229,8 @@ void main() {
test('experimental flag', () async { test('experimental flag', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[ createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'test/plugin_test.dart',
'test/plugin_e2e.dart',
'should_not_run_e2e.dart',
'lib/test/should_not_run_e2e.dart',
'example/test/plugin_e2e.dart',
'example/test_driver/plugin_e2e.dart',
'example/test_driver/plugin_e2e_test.dart',
'example/integration_test/foo_test.dart', 'example/integration_test/foo_test.dart',
'example/integration_test/should_not_run.dart',
'example/android/gradlew', 'example/android/gradlew',
'example/should_not_run_e2e.dart',
'example/android/app/src/androidTest/MainActivityTest.java', 'example/android/app/src/androidTest/MainActivityTest.java',
]); ]);
@ -197,7 +262,7 @@ void main() {
'/packages/plugin/example/android'), '/packages/plugin/example/android'),
ProcessCall( ProcessCall(
'/packages/plugin/example/android/gradlew', '/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/test/plugin_e2e.dart -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1' 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1'
.split(' '), .split(' '),
'/packages/plugin/example/android'), '/packages/plugin/example/android'),
ProcessCall( ProcessCall(
@ -205,36 +270,6 @@ void main() {
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=flame,version=29' 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=flame,version=29'
.split(' '), .split(' '),
'/packages/plugin/example'), '/packages/plugin/example'),
ProcessCall(
'/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/test/plugin_e2e.dart -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1'
.split(' '),
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/1/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
'/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/test_driver/plugin_e2e.dart -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1'
.split(' '),
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/2/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
'/packages/plugin/example/android/gradlew',
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1'
.split(' '),
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/3/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
]), ]),
); );
}); });