mirror of
https://github.com/flutter/packages.git
synced 2025-05-23 03:36:45 +08:00

Adds an initial Android platform tests LUCI script, and initial targets in bringup mode (using 6 shards instead of the 8 we have in Cirrus since the added shards were to try to address what in retrospect was likely a device availability issue, and since for now this will be running fewer tests; once everything is migrated we can evaluate whether we need more shards). Rather than wait for emulator and/or FTL support in LUCI to do the migration of this target, this will partially migrate; the script currently does only the parts that don't require any kind of device. That will let us set up a baseline of LUCI Android platform tests bots to easily expand from as we figure out those pieces, and we can turn down these parts of the tests in Cirrus once these come out of bringup mode to minimize duplication. To avoid having to run a full `flutter build` for both versions, this also updates the repo tooling to use the new `flutter build apk --config-only` option to create `gradlew` without doing a full build. Part of https://github.com/flutter/flutter/issues/114373
827 lines
31 KiB
Dart
827 lines
31 KiB
Dart
// Copyright 2013 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 'dart:io';
|
|
|
|
import 'package:args/command_runner.dart';
|
|
import 'package:file/file.dart';
|
|
import 'package:file/memory.dart';
|
|
import 'package:flutter_plugin_tools/src/common/core.dart';
|
|
import 'package:flutter_plugin_tools/src/common/file_utils.dart';
|
|
import 'package:flutter_plugin_tools/src/firebase_test_lab_command.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:test/test.dart';
|
|
|
|
import 'mocks.dart';
|
|
import 'util.dart';
|
|
|
|
void main() {
|
|
group('FirebaseTestLabCommand', () {
|
|
FileSystem fileSystem;
|
|
late MockPlatform mockPlatform;
|
|
late Directory packagesDir;
|
|
late CommandRunner<void> runner;
|
|
late RecordingProcessRunner processRunner;
|
|
|
|
setUp(() {
|
|
fileSystem = MemoryFileSystem();
|
|
mockPlatform = MockPlatform();
|
|
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
|
|
processRunner = RecordingProcessRunner();
|
|
final FirebaseTestLabCommand command = FirebaseTestLabCommand(
|
|
packagesDir,
|
|
processRunner: processRunner,
|
|
platform: mockPlatform,
|
|
);
|
|
|
|
runner = CommandRunner<void>(
|
|
'firebase_test_lab_command', 'Test for $FirebaseTestLabCommand');
|
|
runner.addCommand(command);
|
|
});
|
|
|
|
void writeJavaTestFile(RepositoryPackage plugin, String relativeFilePath,
|
|
{String runnerClass = 'FlutterTestRunner'}) {
|
|
childFileWithSubcomponents(
|
|
plugin.directory, p.posix.split(relativeFilePath))
|
|
.writeAsStringSync('''
|
|
@DartIntegrationTest
|
|
@RunWith($runnerClass.class)
|
|
public class MainActivityTest {
|
|
@Rule
|
|
public ActivityTestRule<FlutterActivity> rule = new ActivityTestRule<>(FlutterActivity.class);
|
|
}
|
|
''');
|
|
}
|
|
|
|
test('fails if gcloud auth fails', () async {
|
|
processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
|
|
FakeProcessInfo(MockProcess(exitCode: 1), <String>['auth'])
|
|
];
|
|
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['firebase-test-lab'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Unable to activate gcloud account.'),
|
|
]));
|
|
});
|
|
|
|
test('retries gcloud set', () async {
|
|
processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
|
|
FakeProcessInfo(MockProcess(), <String>['auth']),
|
|
FakeProcessInfo(MockProcess(exitCode: 1), <String>['config']),
|
|
];
|
|
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['firebase-test-lab']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Warning: gcloud config set returned a non-zero exit code. Continuing anyway.'),
|
|
]));
|
|
});
|
|
|
|
test('only runs gcloud configuration once', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin1 =
|
|
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
|
|
'test/plugin_test.dart',
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin1, javaTestFileRelativePath);
|
|
final RepositoryPackage plugin2 =
|
|
createFakePlugin('plugin2', packagesDir, extraFiles: <String>[
|
|
'test/plugin_test.dart',
|
|
'example/integration_test/bar_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin2, javaTestFileRelativePath);
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
'--device',
|
|
'model=seoul,version=26',
|
|
'--test-run-id',
|
|
'testRunId',
|
|
'--build-id',
|
|
'buildId',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin1'),
|
|
contains('Firebase project configured.'),
|
|
contains('Testing example/integration_test/foo_test.dart...'),
|
|
contains('Running for plugin2'),
|
|
contains('Testing example/integration_test/bar_test.dart...'),
|
|
]),
|
|
);
|
|
|
|
expect(
|
|
processRunner.recordedCalls,
|
|
orderedEquals(<ProcessCall>[
|
|
ProcessCall(
|
|
'gcloud',
|
|
'auth activate-service-account --key-file=${Platform.environment['HOME']}/gcloud-service-key.json'
|
|
.split(' '),
|
|
null),
|
|
ProcessCall(
|
|
'gcloud', 'config set project flutter-cirrus'.split(' '), null),
|
|
ProcessCall(
|
|
'/packages/plugin1/example/android/gradlew',
|
|
'app:assembleAndroidTest -Pverbose=true'.split(' '),
|
|
'/packages/plugin1/example/android'),
|
|
ProcessCall(
|
|
'/packages/plugin1/example/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin1/example/integration_test/foo_test.dart'
|
|
.split(' '),
|
|
'/packages/plugin1/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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin1/buildId/testRunId/example/0/ --device model=redfin,version=30 --device model=seoul,version=26'
|
|
.split(' '),
|
|
'/packages/plugin1/example'),
|
|
ProcessCall(
|
|
'/packages/plugin2/example/android/gradlew',
|
|
'app:assembleAndroidTest -Pverbose=true'.split(' '),
|
|
'/packages/plugin2/example/android'),
|
|
ProcessCall(
|
|
'/packages/plugin2/example/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin2/example/integration_test/bar_test.dart'
|
|
.split(' '),
|
|
'/packages/plugin2/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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin2/buildId/testRunId/example/0/ --device model=redfin,version=30 --device model=seoul,version=26'
|
|
.split(' '),
|
|
'/packages/plugin2/example'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('runs integration tests', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'test/plugin_test.dart',
|
|
'example/integration_test/bar_test.dart',
|
|
'example/integration_test/foo_test.dart',
|
|
'example/integration_test/should_not_run.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
'--device',
|
|
'model=seoul,version=26',
|
|
'--test-run-id',
|
|
'testRunId',
|
|
'--build-id',
|
|
'buildId',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin'),
|
|
contains('Firebase project configured.'),
|
|
contains('Testing example/integration_test/bar_test.dart...'),
|
|
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(
|
|
processRunner.recordedCalls,
|
|
orderedEquals(<ProcessCall>[
|
|
ProcessCall(
|
|
'gcloud',
|
|
'auth activate-service-account --key-file=${Platform.environment['HOME']}/gcloud-service-key.json'
|
|
.split(' '),
|
|
null),
|
|
ProcessCall(
|
|
'gcloud', 'config set project flutter-cirrus'.split(' '), null),
|
|
ProcessCall(
|
|
'/packages/plugin/example/android/gradlew',
|
|
'app:assembleAndroidTest -Pverbose=true'.split(' '),
|
|
'/packages/plugin/example/android'),
|
|
ProcessCall(
|
|
'/packages/plugin/example/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/bar_test.dart'
|
|
.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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30 --device model=seoul,version=26'
|
|
.split(' '),
|
|
'/packages/plugin/example'),
|
|
ProcessCall(
|
|
'/packages/plugin/example/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart'
|
|
.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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example/1/ --device model=redfin,version=30 --device model=seoul,version=26'
|
|
.split(' '),
|
|
'/packages/plugin/example'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('runs for all examples', () async {
|
|
const List<String> examples = <String>['example1', 'example2'];
|
|
const String javaTestFileExampleRelativePath =
|
|
'android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir,
|
|
examples: examples,
|
|
extraFiles: <String>[
|
|
for (final String example in examples) ...<String>[
|
|
'example/$example/integration_test/a_test.dart',
|
|
'example/$example/android/gradlew',
|
|
'example/$example/$javaTestFileExampleRelativePath',
|
|
],
|
|
]);
|
|
for (final String example in examples) {
|
|
writeJavaTestFile(
|
|
plugin, 'example/$example/$javaTestFileExampleRelativePath');
|
|
}
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
'--device',
|
|
'model=seoul,version=26',
|
|
'--test-run-id',
|
|
'testRunId',
|
|
'--build-id',
|
|
'buildId',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Testing example/example1/integration_test/a_test.dart...'),
|
|
contains('Testing example/example2/integration_test/a_test.dart...'),
|
|
]),
|
|
);
|
|
|
|
expect(
|
|
processRunner.recordedCalls,
|
|
containsAll(<ProcessCall>[
|
|
ProcessCall(
|
|
'/packages/plugin/example/example1/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/example1/integration_test/a_test.dart'
|
|
.split(' '),
|
|
'/packages/plugin/example/example1/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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example1/0/ --device model=redfin,version=30 --device model=seoul,version=26'
|
|
.split(' '),
|
|
'/packages/plugin/example/example1'),
|
|
ProcessCall(
|
|
'/packages/plugin/example/example2/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/example2/integration_test/a_test.dart'
|
|
.split(' '),
|
|
'/packages/plugin/example/example2/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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example2/0/ --device model=redfin,version=30 --device model=seoul,version=26'
|
|
.split(' '),
|
|
'/packages/plugin/example/example2'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails if a test fails twice', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/bar_test.dart',
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
|
|
FakeProcessInfo(MockProcess(), <String>['auth']),
|
|
FakeProcessInfo(MockProcess(), <String>['config']),
|
|
FakeProcessInfo(MockProcess(exitCode: 1),
|
|
<String>['firebase', 'test']), // integration test #1
|
|
FakeProcessInfo(MockProcess(exitCode: 1),
|
|
<String>['firebase', 'test']), // integration test #1 retry
|
|
FakeProcessInfo(
|
|
MockProcess(), <String>['firebase', 'test']), // integration test #2
|
|
];
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Testing example/integration_test/bar_test.dart...'),
|
|
contains('Testing example/integration_test/foo_test.dart...'),
|
|
contains('plugin:\n'
|
|
' example/integration_test/bar_test.dart failed tests'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('passes with warning if a test fails once, then passes on retry',
|
|
() async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/bar_test.dart',
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
|
|
FakeProcessInfo(MockProcess(), <String>['auth']),
|
|
FakeProcessInfo(MockProcess(), <String>['config']),
|
|
FakeProcessInfo(MockProcess(exitCode: 1),
|
|
<String>['firebase', 'test']), // integration test #1
|
|
FakeProcessInfo(MockProcess(),
|
|
<String>['firebase', 'test']), // integration test #1 retry
|
|
FakeProcessInfo(
|
|
MockProcess(), <String>['firebase', 'test']), // integration test #2
|
|
];
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Testing example/integration_test/bar_test.dart...'),
|
|
contains('bar_test.dart failed on attempt 1. Retrying...'),
|
|
contains('Testing example/integration_test/foo_test.dart...'),
|
|
contains('Ran for 1 package(s) (1 with warnings)'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails for plugins with no androidTest directory', () async {
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
]);
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin'),
|
|
contains('No androidTest directory found.'),
|
|
contains('The following packages had errors:'),
|
|
contains('plugin:\n'
|
|
' No tests ran (use --exclude if this is intentional).'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('skips for non-plugin packages with no androidTest directory',
|
|
() async {
|
|
createFakePackage('a_package', 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=redfin,version=30',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for a_package'),
|
|
contains('No androidTest directory found.'),
|
|
contains('No examples support Android.'),
|
|
contains('Skipped 1 package'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails for packages with no integration test files', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin'),
|
|
contains('No integration tests were run'),
|
|
contains('The following packages had errors:'),
|
|
contains('plugin:\n'
|
|
' No tests ran (use --exclude if this is intentional).'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails for packages with no integration_test runner', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'test/plugin_test.dart',
|
|
'example/integration_test/bar_test.dart',
|
|
'example/integration_test/foo_test.dart',
|
|
'example/integration_test/should_not_run.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
// Use the wrong @RunWith annotation.
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath,
|
|
runnerClass: 'AndroidJUnit4.class');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin'),
|
|
contains('No integration_test runner found. '
|
|
'See the integration_test package README for setup instructions.'),
|
|
contains('plugin:\n'
|
|
' No integration_test runner.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('skips packages with no android directory', () async {
|
|
createFakePackage('package', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
]);
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for package'),
|
|
contains('No examples support Android'),
|
|
]),
|
|
);
|
|
expect(output,
|
|
isNot(contains('Testing example/integration_test/foo_test.dart...')));
|
|
|
|
expect(
|
|
processRunner.recordedCalls,
|
|
orderedEquals(<ProcessCall>[]),
|
|
);
|
|
});
|
|
|
|
test('builds if gradlew is missing', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
'--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(
|
|
'flutter',
|
|
'build apk --config-only'.split(' '),
|
|
'/packages/plugin/example/android',
|
|
),
|
|
ProcessCall(
|
|
'gcloud',
|
|
'auth activate-service-account --key-file=${Platform.environment['HOME']}/gcloud-service-key.json'
|
|
.split(' '),
|
|
null),
|
|
ProcessCall(
|
|
'gcloud', 'config set project flutter-cirrus'.split(' '), null),
|
|
ProcessCall(
|
|
'/packages/plugin/example/android/gradlew',
|
|
'app:assembleAndroidTest -Pverbose=true'.split(' '),
|
|
'/packages/plugin/example/android'),
|
|
ProcessCall(
|
|
'/packages/plugin/example/android/gradlew',
|
|
'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart'
|
|
.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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30'
|
|
.split(' '),
|
|
'/packages/plugin/example'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails if building to generate gradlew fails', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
|
|
FakeProcessInfo(MockProcess(exitCode: 1), <String>['build'])
|
|
];
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Unable to build example apk'),
|
|
]));
|
|
});
|
|
|
|
test('fails if assembleAndroidTest fails', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
final String gradlewPath = plugin
|
|
.getExamples()
|
|
.first
|
|
.platformDirectory(FlutterPlatform.android)
|
|
.childFile('gradlew')
|
|
.path;
|
|
processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[
|
|
FakeProcessInfo(
|
|
MockProcess(exitCode: 1), <String>['app:assembleAndroidTest']),
|
|
];
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Unable to assemble androidTest'),
|
|
]));
|
|
});
|
|
|
|
test('fails if assembleDebug fails', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
final String gradlewPath = plugin
|
|
.getExamples()
|
|
.first
|
|
.platformDirectory(FlutterPlatform.android)
|
|
.childFile('gradlew')
|
|
.path;
|
|
processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[
|
|
FakeProcessInfo(MockProcess(), <String>['app:assembleAndroidTest']),
|
|
FakeProcessInfo(MockProcess(exitCode: 1), <String>['app:assembleDebug'])
|
|
];
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
},
|
|
);
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Could not build example/integration_test/foo_test.dart'),
|
|
contains('The following packages had errors:'),
|
|
contains(' plugin:\n'
|
|
' example/integration_test/foo_test.dart failed to build'),
|
|
]));
|
|
});
|
|
|
|
test('experimental flag', () async {
|
|
const String javaTestFileRelativePath =
|
|
'example/android/app/src/androidTest/MainActivityTest.java';
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
|
|
'example/integration_test/foo_test.dart',
|
|
'example/android/gradlew',
|
|
javaTestFileRelativePath,
|
|
]);
|
|
writeJavaTestFile(plugin, javaTestFileRelativePath);
|
|
|
|
await runCapturingPrint(runner, <String>[
|
|
'firebase-test-lab',
|
|
'--device',
|
|
'model=redfin,version=30',
|
|
'--test-run-id',
|
|
'testRunId',
|
|
'--build-id',
|
|
'buildId',
|
|
'--enable-experiment=exp1',
|
|
]);
|
|
|
|
expect(
|
|
processRunner.recordedCalls,
|
|
orderedEquals(<ProcessCall>[
|
|
ProcessCall(
|
|
'gcloud',
|
|
'auth activate-service-account --key-file=${Platform.environment['HOME']}/gcloud-service-key.json'
|
|
.split(' '),
|
|
null),
|
|
ProcessCall(
|
|
'gcloud', 'config set project flutter-cirrus'.split(' '), null),
|
|
ProcessCall(
|
|
'/packages/plugin/example/android/gradlew',
|
|
'app:assembleAndroidTest -Pverbose=true -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1'
|
|
.split(' '),
|
|
'/packages/plugin/example/android'),
|
|
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 7m --results-bucket=gs://flutter_cirrus_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30'
|
|
.split(' '),
|
|
'/packages/plugin/example'),
|
|
]),
|
|
);
|
|
});
|
|
});
|
|
}
|