mirror of
https://github.com/flutter/packages.git
synced 2025-06-06 03:19:27 +08:00
[tools] Remove single-example RepositoryPackage method (#5600)
This commit is contained in:
@ -112,13 +112,4 @@ class RepositoryPackage {
|
||||
.map((FileSystemEntity entity) =>
|
||||
RepositoryPackage(entity as Directory));
|
||||
}
|
||||
|
||||
/// Returns the example directory, assuming there is only one.
|
||||
///
|
||||
/// DO NOT USE THIS METHOD. It exists only to easily find code that was
|
||||
/// written to use a single example and needs to be restructured to handle
|
||||
/// multiple examples. New code should always use [getExamples].
|
||||
// TODO(stuartmorgan): Eliminate all uses of this.
|
||||
RepositoryPackage getSingleExampleDeprecated() =>
|
||||
RepositoryPackage(directory.childDirectory('example'));
|
||||
}
|
||||
|
@ -125,8 +125,7 @@ class DriveExamplesCommand extends PackageLoopingCommand {
|
||||
Future<PackageResult> runForPackage(RepositoryPackage package) async {
|
||||
final bool isPlugin = isFlutterPlugin(package);
|
||||
|
||||
if (package.isPlatformInterface &&
|
||||
!package.getSingleExampleDeprecated().directory.existsSync()) {
|
||||
if (package.isPlatformInterface && package.getExamples().isEmpty) {
|
||||
// Platform interface packages generally aren't intended to have
|
||||
// examples, and don't need integration tests, so skip rather than fail.
|
||||
return PackageResult.skip(
|
||||
|
@ -119,7 +119,32 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
|
||||
|
||||
@override
|
||||
Future<PackageResult> runForPackage(RepositoryPackage package) async {
|
||||
final RepositoryPackage example = package.getSingleExampleDeprecated();
|
||||
final List<PackageResult> results = <PackageResult>[];
|
||||
for (final RepositoryPackage example in package.getExamples()) {
|
||||
results.add(await _runForExample(example, package: package));
|
||||
}
|
||||
|
||||
// If all results skipped, report skip overall.
|
||||
if (results
|
||||
.every((PackageResult result) => result.state == RunState.skipped)) {
|
||||
return PackageResult.skip('No examples support Android.');
|
||||
}
|
||||
// Otherwise, report failure if there were any failures.
|
||||
final List<String> allErrors = results
|
||||
.map((PackageResult result) =>
|
||||
result.state == RunState.failed ? result.details : <String>[])
|
||||
.expand((List<String> list) => list)
|
||||
.toList();
|
||||
return allErrors.isEmpty
|
||||
? PackageResult.success()
|
||||
: PackageResult.fail(allErrors);
|
||||
}
|
||||
|
||||
/// Runs the test for the given example of [package].
|
||||
Future<PackageResult> _runForExample(
|
||||
RepositoryPackage example, {
|
||||
required RepositoryPackage package,
|
||||
}) async {
|
||||
final Directory androidDirectory =
|
||||
example.directory.childDirectory('android');
|
||||
if (!androidDirectory.existsSync()) {
|
||||
@ -163,7 +188,7 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
|
||||
// Used within the loop to ensure a unique GCS output location for each
|
||||
// test file's run.
|
||||
int resultsCounter = 0;
|
||||
for (final File test in _findIntegrationTestFiles(package)) {
|
||||
for (final File test in _findIntegrationTestFiles(example)) {
|
||||
final String testName =
|
||||
getRelativePosixPath(test, from: package.directory);
|
||||
print('Testing $testName...');
|
||||
@ -175,7 +200,8 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
|
||||
final String buildId = getStringArg('build-id');
|
||||
final String testRunId = getStringArg('test-run-id');
|
||||
final String resultsDir =
|
||||
'plugins_android_test/${package.displayName}/$buildId/$testRunId/${resultsCounter++}/';
|
||||
'plugins_android_test/${package.displayName}/$buildId/$testRunId/'
|
||||
'${example.directory.basename}/${resultsCounter++}/';
|
||||
|
||||
// Automatically retry failures; there is significant flake with these
|
||||
// tests whose cause isn't yet understood, and having to re-run the
|
||||
@ -299,12 +325,10 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Finds and returns all integration test files for [package].
|
||||
Iterable<File> _findIntegrationTestFiles(RepositoryPackage package) sync* {
|
||||
final Directory integrationTestDir = package
|
||||
.getSingleExampleDeprecated()
|
||||
.directory
|
||||
.childDirectory('integration_test');
|
||||
/// Finds and returns all integration test files for [example].
|
||||
Iterable<File> _findIntegrationTestFiles(RepositoryPackage example) sync* {
|
||||
final Directory integrationTestDir =
|
||||
example.directory.childDirectory('integration_test');
|
||||
|
||||
if (!integrationTestDir.existsSync()) {
|
||||
return;
|
||||
|
@ -28,7 +28,7 @@ class LintAndroidCommand extends PackageLoopingCommand {
|
||||
|
||||
@override
|
||||
final String description = 'Runs "gradlew lint" on Android plugins.\n\n'
|
||||
'Requires the example to have been build at least once before running.';
|
||||
'Requires the examples to have been build at least once before running.';
|
||||
|
||||
@override
|
||||
Future<PackageResult> runForPackage(RepositoryPackage package) async {
|
||||
@ -38,12 +38,13 @@ class LintAndroidCommand extends PackageLoopingCommand {
|
||||
'Plugin does not have an Android implemenatation.');
|
||||
}
|
||||
|
||||
final RepositoryPackage example = package.getSingleExampleDeprecated();
|
||||
bool failed = false;
|
||||
for (final RepositoryPackage example in package.getExamples()) {
|
||||
final GradleProject project = GradleProject(example.directory,
|
||||
processRunner: processRunner, platform: platform);
|
||||
|
||||
if (!project.isConfigured()) {
|
||||
return PackageResult.fail(<String>['Build example before linting']);
|
||||
return PackageResult.fail(<String>['Build examples before linting']);
|
||||
}
|
||||
|
||||
final String packageName = package.directory.basename;
|
||||
@ -53,10 +54,14 @@ class LintAndroidCommand extends PackageLoopingCommand {
|
||||
// dependencies.
|
||||
//
|
||||
// TODO(stuartmorgan): Consider adding an XML parser to read and summarize
|
||||
// all results. Currently, only the first three errors will be shown inline,
|
||||
// and the rest have to be checked via the CI-uploaded artifact.
|
||||
// all results. Currently, only the first three errors will be shown
|
||||
// inline, and the rest have to be checked via the CI-uploaded artifact.
|
||||
final int exitCode = await project.runCommand('$packageName:lintDebug');
|
||||
if (exitCode != 0) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return exitCode == 0 ? PackageResult.success() : PackageResult.fail();
|
||||
return failed ? PackageResult.fail() : PackageResult.success();
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import 'mocks.dart';
|
||||
import 'util.dart';
|
||||
|
||||
void main() {
|
||||
group('$FirebaseTestLabCommand', () {
|
||||
group('FirebaseTestLabCommand', () {
|
||||
FileSystem fileSystem;
|
||||
late MockPlatform mockPlatform;
|
||||
late Directory packagesDir;
|
||||
@ -173,7 +173,7 @@ public class MainActivityTest {
|
||||
'/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_firebase_testlab --results-dir=plugins_android_test/plugin1/buildId/testRunId/0/ --device model=redfin,version=30 --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 7m --results-bucket=gs://flutter_firebase_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(
|
||||
@ -187,7 +187,7 @@ public class MainActivityTest {
|
||||
'/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_firebase_testlab --results-dir=plugins_android_test/plugin2/buildId/testRunId/0/ --device model=redfin,version=30 --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 7m --results-bucket=gs://flutter_firebase_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'),
|
||||
]),
|
||||
@ -254,7 +254,7 @@ public class MainActivityTest {
|
||||
'/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_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=redfin,version=30 --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 7m --results-bucket=gs://flutter_firebase_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(
|
||||
@ -264,13 +264,78 @@ public class MainActivityTest {
|
||||
'/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_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/1/ --device model=redfin,version=30 --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 7m --results-bucket=gs://flutter_firebase_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 Directory pluginDir = 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(
|
||||
pluginDir, '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_firebase_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_firebase_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';
|
||||
@ -479,7 +544,7 @@ public class MainActivityTest {
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for package'),
|
||||
contains('package/example does not support Android'),
|
||||
contains('No examples support Android'),
|
||||
]),
|
||||
);
|
||||
expect(output,
|
||||
@ -547,7 +612,7 @@ public class MainActivityTest {
|
||||
'/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_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=redfin,version=30'
|
||||
'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_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30'
|
||||
.split(' '),
|
||||
'/packages/plugin/example'),
|
||||
]),
|
||||
@ -717,7 +782,7 @@ public class MainActivityTest {
|
||||
'/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_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=redfin,version=30'
|
||||
'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_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30'
|
||||
.split(' '),
|
||||
'/packages/plugin/example'),
|
||||
]),
|
||||
|
@ -16,7 +16,7 @@ import 'mocks.dart';
|
||||
import 'util.dart';
|
||||
|
||||
void main() {
|
||||
group('$LintAndroidCommand', () {
|
||||
group('LintAndroidCommand', () {
|
||||
FileSystem fileSystem;
|
||||
late Directory packagesDir;
|
||||
late CommandRunner<void> runner;
|
||||
@ -72,6 +72,47 @@ void main() {
|
||||
]));
|
||||
});
|
||||
|
||||
test('runs on all examples', () async {
|
||||
final List<String> examples = <String>['example1', 'example2'];
|
||||
final Directory pluginDir = createFakePlugin('plugin1', packagesDir,
|
||||
examples: examples,
|
||||
extraFiles: <String>[
|
||||
'example/example1/android/gradlew',
|
||||
'example/example2/android/gradlew',
|
||||
],
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final Iterable<Directory> exampleAndroidDirs = examples.map(
|
||||
(String example) => pluginDir
|
||||
.childDirectory('example')
|
||||
.childDirectory(example)
|
||||
.childDirectory('android'));
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['lint-android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
for (final Directory directory in exampleAndroidDirs)
|
||||
ProcessCall(
|
||||
directory.childFile('gradlew').path,
|
||||
const <String>['plugin1:lintDebug'],
|
||||
directory.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('fails if gradlew is missing', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
@ -89,18 +130,25 @@ void main() {
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Build example before linting'),
|
||||
contains('Build examples before linting'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('fails if linting finds issues', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
final Directory pluginDir =
|
||||
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
|
||||
'example/android/gradlew',
|
||||
], platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner.mockProcessesForExecutable['gradlew'] = <io.Process>[
|
||||
final String gradlewPath = pluginDir
|
||||
.childDirectory('example')
|
||||
.childDirectory('android')
|
||||
.childFile('gradlew')
|
||||
.path;
|
||||
processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
|
||||
MockProcess(exitCode: 1),
|
||||
];
|
||||
|
||||
@ -115,7 +163,7 @@ void main() {
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Build example before linting'),
|
||||
contains('The following packages had errors:'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
Reference in New Issue
Block a user