Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit a4f0e88

Browse files
[flutter_plugin_tools] Make having no Java unit tests a failure (#4310)
This brings the native Android unit tests in line with the policy of having tests that we expect all plugins to have—unless there's a very specific reason to opt them out—fail when missing instead of skipping when missing, to help guard against errors where we silently fail to run tests we think we are running. Adds an explicit exclusion list covering the plugins that have a reason to be opted out. Android portion of flutter/flutter#85469
1 parent b38c4e4 commit a4f0e88

File tree

5 files changed

+119
-12
lines changed

5 files changed

+119
-12
lines changed

.cirrus.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ task:
182182
- export CIRRUS_COMMIT_MESSAGE=""
183183
# Native integration tests are handled by firebase-test-lab below, so
184184
# only run unit tests.
185-
- ./script/tool_runner.sh native-test --android --no-integration # must come after apk build
185+
# Must come after build-examples.
186+
- ./script/tool_runner.sh native-test --android --no-integration --exclude script/configs/exclude_native_unit_android.yaml
186187
firebase_test_lab_script:
187188
# Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they
188189
# might include non-ASCII characters which makes Gradle crash.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Deprecated; no plan to backfill the missing files
2+
- android_alarm_manager
3+
- battery
4+
- device_info/device_info
5+
- package_info
6+
- sensors
7+
- share
8+
- wifi_info_flutter/wifi_info_flutter
9+
10+
# No need for unit tests:
11+
- espresso

script/tool/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## NEXT
2+
3+
- `native-test --android` now fails plugins that don't have unit tests,
4+
rather than skipping them.
5+
16
## 0.7.1
27

38
- Add support for `.pluginToolsConfig.yaml` in the `build-examples` command.

script/tool/lib/src/native_test_command.dart

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ this command.
242242

243243
final Iterable<RepositoryPackage> examples = plugin.getExamples();
244244

245-
bool ranTests = false;
245+
bool ranUnitTests = false;
246+
bool ranAnyTests = false;
246247
bool failed = false;
247248
bool hasMissingBuild = false;
248249
for (final RepositoryPackage example in examples) {
@@ -289,7 +290,8 @@ this command.
289290
printError('$exampleName unit tests failed.');
290291
failed = true;
291292
}
292-
ranTests = true;
293+
ranUnitTests = true;
294+
ranAnyTests = true;
293295
}
294296

295297
if (runIntegrationTests) {
@@ -311,7 +313,7 @@ this command.
311313
printError('$exampleName integration tests failed.');
312314
failed = true;
313315
}
314-
ranTests = true;
316+
ranAnyTests = true;
315317
}
316318
}
317319

@@ -321,7 +323,12 @@ this command.
321323
? 'Examples must be built before testing.'
322324
: null);
323325
}
324-
if (!ranTests) {
326+
if (!mode.integrationOnly && !ranUnitTests) {
327+
printError('No unit tests ran. Plugins are required to have unit tests.');
328+
return _PlatformResult(RunState.failed,
329+
error: 'No unit tests ran (use --exclude if this is intentional).');
330+
}
331+
if (!ranAnyTests) {
325332
return _PlatformResult(RunState.skipped);
326333
}
327334
return _PlatformResult(RunState.succeeded);

script/tool/test/native_test_command_test.dart

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ void main() {
430430
],
431431
);
432432

433-
await runCapturingPrint(runner, <String>['native-test', '--android']);
433+
await runCapturingPrint(
434+
runner, <String>['native-test', '--android', '--no-unit']);
434435

435436
final Directory androidFolder =
436437
plugin.childDirectory('example').childDirectory('android');
@@ -467,7 +468,8 @@ void main() {
467468
],
468469
);
469470

470-
await runCapturingPrint(runner, <String>['native-test', '--android']);
471+
await runCapturingPrint(
472+
runner, <String>['native-test', '--android', '--no-unit']);
471473

472474
// Nothing should run since those files are all
473475
// integration_test-specific.
@@ -641,7 +643,11 @@ void main() {
641643
);
642644

643645
final List<String> output = await runCapturingPrint(
644-
runner, <String>['native-test', '--android']);
646+
runner, <String>['native-test', '--android'],
647+
errorHandler: (Error e) {
648+
// Having no unit tests is fatal, but that's not the point of this
649+
// test so just ignore the failure.
650+
});
645651

646652
expect(
647653
output,
@@ -654,7 +660,7 @@ void main() {
654660
]));
655661
});
656662

657-
test('fails when a test fails', () async {
663+
test('fails when a unit test fails', () async {
658664
final Directory pluginDir = createFakePlugin(
659665
'plugin',
660666
packagesDir,
@@ -695,6 +701,84 @@ void main() {
695701
);
696702
});
697703

704+
test('fails when an integration test fails', () async {
705+
final Directory pluginDir = createFakePlugin(
706+
'plugin',
707+
packagesDir,
708+
platformSupport: <String, PlatformDetails>{
709+
kPlatformAndroid: const PlatformDetails(PlatformSupport.inline)
710+
},
711+
extraFiles: <String>[
712+
'example/android/gradlew',
713+
'example/android/app/src/test/example_test.java',
714+
'example/android/app/src/androidTest/IntegrationTest.java',
715+
],
716+
);
717+
718+
final String gradlewPath = pluginDir
719+
.childDirectory('example')
720+
.childDirectory('android')
721+
.childFile('gradlew')
722+
.path;
723+
processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
724+
MockProcess(), // unit passes
725+
MockProcess(exitCode: 1), // integration fails
726+
];
727+
728+
Error? commandError;
729+
final List<String> output = await runCapturingPrint(
730+
runner, <String>['native-test', '--android'],
731+
errorHandler: (Error e) {
732+
commandError = e;
733+
});
734+
735+
expect(commandError, isA<ToolExit>());
736+
737+
expect(
738+
output,
739+
containsAllInOrder(<Matcher>[
740+
contains('plugin/example integration tests failed.'),
741+
contains('The following packages had errors:'),
742+
contains('plugin')
743+
]),
744+
);
745+
});
746+
747+
test('fails if there are no unit tests', () async {
748+
createFakePlugin(
749+
'plugin',
750+
packagesDir,
751+
platformSupport: <String, PlatformDetails>{
752+
kPlatformAndroid: const PlatformDetails(PlatformSupport.inline)
753+
},
754+
extraFiles: <String>[
755+
'example/android/gradlew',
756+
'example/android/app/src/androidTest/IntegrationTest.java',
757+
],
758+
);
759+
760+
Error? commandError;
761+
final List<String> output = await runCapturingPrint(
762+
runner, <String>['native-test', '--android'],
763+
errorHandler: (Error e) {
764+
commandError = e;
765+
});
766+
767+
expect(commandError, isA<ToolExit>());
768+
769+
expect(
770+
output,
771+
containsAllInOrder(<Matcher>[
772+
contains('No Android unit tests found for plugin/example'),
773+
contains(
774+
'No unit tests ran. Plugins are required to have unit tests.'),
775+
contains('The following packages had errors:'),
776+
contains('plugin:\n'
777+
' No unit tests ran (use --exclude if this is intentional).')
778+
]),
779+
);
780+
});
781+
698782
test('skips if Android is not supported', () async {
699783
createFakePlugin(
700784
'plugin',
@@ -713,7 +797,7 @@ void main() {
713797
);
714798
});
715799

716-
test('skips when running no tests', () async {
800+
test('skips when running no tests in integration-only mode', () async {
717801
createFakePlugin(
718802
'plugin',
719803
packagesDir,
@@ -723,12 +807,11 @@ void main() {
723807
);
724808

725809
final List<String> output = await runCapturingPrint(
726-
runner, <String>['native-test', '--android']);
810+
runner, <String>['native-test', '--android', '--no-unit']);
727811

728812
expect(
729813
output,
730814
containsAllInOrder(<Matcher>[
731-
contains('No Android unit tests found for plugin/example'),
732815
contains('No Android integration tests found for plugin/example'),
733816
contains('SKIPPING: No tests found.'),
734817
]),

0 commit comments

Comments
 (0)