@@ -176,30 +176,22 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
176
176
final String testRunId = getStringArg ('test-run-id' );
177
177
final String resultsDir =
178
178
'plugins_android_test/${package .displayName }/$buildId /$testRunId /${resultsCounter ++}/' ;
179
- final List <String > args = < String > [
180
- 'firebase' ,
181
- 'test' ,
182
- 'android' ,
183
- 'run' ,
184
- '--type' ,
185
- 'instrumentation' ,
186
- '--app' ,
187
- 'build/app/outputs/apk/debug/app-debug.apk' ,
188
- '--test' ,
189
- 'build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk' ,
190
- '--timeout' ,
191
- '7m' ,
192
- '--results-bucket=${getStringArg ('results-bucket' )}' ,
193
- '--results-dir=$resultsDir ' ,
194
- ];
195
- for (final String device in getStringListArg ('device' )) {
196
- args.addAll (< String > ['--device' , device]);
197
- }
198
- final int exitCode = await processRunner.runAndStream ('gcloud' , args,
199
- workingDir: example.directory);
200
179
201
- if (exitCode != 0 ) {
202
- printError ('Test failure for $testName ' );
180
+ // Automatically retry failures; there is significant flake with these
181
+ // tests whose cause isn't yet understood, and having to re-run the
182
+ // entire shard for a flake in any one test is extremely slow. This should
183
+ // be removed once the root cause of the flake is understood.
184
+ // See https://github.com/flutter/flutter/issues/95063
185
+ const int maxRetries = 2 ;
186
+ bool passing = false ;
187
+ for (int i = 1 ; i <= maxRetries && ! passing; ++ i) {
188
+ if (i > 1 ) {
189
+ logWarning ('$testName failed on attempt ${i - 1 }. Retrying...' );
190
+ }
191
+ passing = await _runFirebaseTest (example, test, resultsDir: resultsDir);
192
+ }
193
+ if (! passing) {
194
+ printError ('Test failure for $testName after $maxRetries attempts' );
203
195
errors.add ('$testName failed tests' );
204
196
}
205
197
}
@@ -238,6 +230,42 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
238
230
return true ;
239
231
}
240
232
233
+ /// Runs [test] from [example] as a Firebase Test Lab test, returning true if
234
+ /// the test passed.
235
+ ///
236
+ /// [resultsDir] should be a unique-to-the-test-run directory to store the
237
+ /// results on the server.
238
+ Future <bool > _runFirebaseTest (
239
+ RepositoryPackage example,
240
+ File test, {
241
+ required String resultsDir,
242
+ }) async {
243
+ final List <String > args = < String > [
244
+ 'firebase' ,
245
+ 'test' ,
246
+ 'android' ,
247
+ 'run' ,
248
+ '--type' ,
249
+ 'instrumentation' ,
250
+ '--app' ,
251
+ 'build/app/outputs/apk/debug/app-debug.apk' ,
252
+ '--test' ,
253
+ 'build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk' ,
254
+ '--timeout' ,
255
+ '7m' ,
256
+ '--results-bucket=${getStringArg ('results-bucket' )}' ,
257
+ '--results-dir=$resultsDir ' ,
258
+ for (final String device in getStringListArg ('device' )) ...< String > [
259
+ '--device' ,
260
+ device
261
+ ],
262
+ ];
263
+ final int exitCode = await processRunner.runAndStream ('gcloud' , args,
264
+ workingDir: example.directory);
265
+
266
+ return exitCode == 0 ;
267
+ }
268
+
241
269
/// Builds [target] using Gradle in the given [project] . Assumes Gradle is
242
270
/// already configured.
243
271
///
0 commit comments