mirror of
https://github.com/flutter/packages.git
synced 2025-06-30 14:47:22 +08:00
[ci] Add partial LUCI Android platform tests (#4381)
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
This commit is contained in:
@ -251,6 +251,7 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
|
||||
<String>[
|
||||
'build',
|
||||
'apk',
|
||||
'--config-only',
|
||||
if (experiment.isNotEmpty) '--enable-experiment=$experiment',
|
||||
],
|
||||
workingDir: project.androidDirectory);
|
||||
|
@ -43,9 +43,15 @@ class LintAndroidCommand extends PackageLoopingCommand {
|
||||
processRunner: processRunner, platform: platform);
|
||||
|
||||
if (!project.isConfigured()) {
|
||||
// TODO(stuartmorgan): Replace this with a --config-only build once
|
||||
// that's available on stable.
|
||||
return PackageResult.fail(<String>['Build examples before linting']);
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
flutterCommand,
|
||||
<String>['build', 'apk', '--config-only'],
|
||||
workingDir: example.directory,
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
printError('Unable to configure Gradle project.');
|
||||
return PackageResult.fail(<String>['Unable to configure Gradle.']);
|
||||
}
|
||||
}
|
||||
|
||||
final String packageName = package.directory.basename;
|
||||
|
@ -276,7 +276,6 @@ this command.
|
||||
bool ranUnitTests = false;
|
||||
bool ranAnyTests = false;
|
||||
bool failed = false;
|
||||
bool hasMissingBuild = false;
|
||||
bool hasMisconfiguredIntegrationTest = false;
|
||||
// Iterate through all examples (in the rare case that there is more than
|
||||
// one example); running any tests found for each one. Requirements on what
|
||||
@ -311,12 +310,16 @@ this command.
|
||||
platform: platform,
|
||||
);
|
||||
if (!project.isConfigured()) {
|
||||
printError('ERROR: Run "flutter build apk" on $exampleName, or run '
|
||||
'this tool\'s "build-examples --apk" command, '
|
||||
'before executing tests.');
|
||||
failed = true;
|
||||
hasMissingBuild = true;
|
||||
continue;
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
flutterCommand,
|
||||
<String>['build', 'apk', '--config-only'],
|
||||
workingDir: example.directory,
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
printError('Unable to configure Gradle project.');
|
||||
failed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (runUnitTests) {
|
||||
@ -379,10 +382,7 @@ this command.
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
return _PlatformResult(RunState.failed,
|
||||
error: hasMissingBuild
|
||||
? 'Examples must be built before testing.'
|
||||
: null);
|
||||
return _PlatformResult(RunState.failed);
|
||||
}
|
||||
if (hasMisconfiguredIntegrationTest) {
|
||||
return _PlatformResult(RunState.failed,
|
||||
|
@ -622,7 +622,7 @@ public class MainActivityTest {
|
||||
orderedEquals(<ProcessCall>[
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
'build apk'.split(' '),
|
||||
'build apk --config-only'.split(' '),
|
||||
'/packages/plugin/example/android',
|
||||
),
|
||||
ProcessCall(
|
||||
|
@ -109,12 +109,54 @@ void main() {
|
||||
]));
|
||||
});
|
||||
|
||||
test('fails if gradlew is missing', () async {
|
||||
test('runs --config-only build if gradlew is missing', () async {
|
||||
final RepositoryPackage plugin = createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final Directory androidDir =
|
||||
plugin.getExamples().first.platformDirectory(FlutterPlatform.android);
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['lint-android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
ProcessCall(
|
||||
getFlutterCommand(mockPlatform),
|
||||
const <String>['build', 'apk', '--config-only'],
|
||||
plugin.getExamples().first.directory.path,
|
||||
),
|
||||
ProcessCall(
|
||||
androidDir.childFile('gradlew').path,
|
||||
const <String>['plugin1:lintDebug'],
|
||||
androidDir.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('fails if gradlew generation fails', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner
|
||||
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
|
||||
<FakeProcessInfo>[
|
||||
FakeProcessInfo(MockProcess(exitCode: 1)),
|
||||
];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['lint-android'], errorHandler: (Error e) {
|
||||
@ -126,7 +168,7 @@ void main() {
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Build examples before linting'),
|
||||
contains('Unable to configure Gradle project'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
@ -773,7 +773,44 @@ public class FlutterActivityTest {
|
||||
);
|
||||
});
|
||||
|
||||
test('fails when the app needs to be built', () async {
|
||||
test('runs a config-only build when the app needs to be built', () async {
|
||||
final RepositoryPackage package = createFakePlugin(
|
||||
'plugin',
|
||||
packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.inline)
|
||||
},
|
||||
extraFiles: <String>[
|
||||
'example/android/app/src/test/example_test.java',
|
||||
],
|
||||
);
|
||||
final RepositoryPackage example = package.getExamples().first;
|
||||
final Directory androidFolder =
|
||||
example.platformDirectory(FlutterPlatform.android);
|
||||
|
||||
await runCapturingPrint(runner, <String>['native-test', '--android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
ProcessCall(
|
||||
getFlutterCommand(mockPlatform),
|
||||
const <String>['build', 'apk', '--config-only'],
|
||||
example.path,
|
||||
),
|
||||
ProcessCall(
|
||||
androidFolder.childFile('gradlew').path,
|
||||
const <String>[
|
||||
'app:testDebugUnitTest',
|
||||
'plugin:testDebugUnitTest',
|
||||
],
|
||||
androidFolder.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('fails when the gradlew generation fails', () async {
|
||||
createFakePlugin(
|
||||
'plugin',
|
||||
packagesDir,
|
||||
@ -785,6 +822,10 @@ public class FlutterActivityTest {
|
||||
],
|
||||
);
|
||||
|
||||
processRunner
|
||||
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
|
||||
<FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['native-test', '--android'],
|
||||
@ -797,9 +838,7 @@ public class FlutterActivityTest {
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('ERROR: Run "flutter build apk" on plugin/example'),
|
||||
contains('plugin:\n'
|
||||
' Examples must be built before testing.')
|
||||
contains('Unable to configure Gradle project'),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
Reference in New Issue
Block a user