@@ -57,7 +57,7 @@ def self.run(params)
57
57
58
58
binary_type = binary_type_from_path ( binary_path )
59
59
UI . message ( "📡 Uploading the #{ binary_type } ." )
60
- operation = upload_binary ( app_name , binary_path , binary_type , client , timeout )
60
+ operation = upload_binary ( client , app_name , binary_path , binary_type , timeout )
61
61
UI . message ( "🕵️ Validating upload…" )
62
62
release = poll_upload_release_operation ( client , operation , binary_type )
63
63
@@ -88,11 +88,12 @@ def self.run(params)
88
88
test_devices =
89
89
get_value_from_value_or_file ( params [ :test_devices ] , params [ :test_devices_file ] )
90
90
if present? ( test_devices )
91
- UI . message ( "🤖 Starting automated tests. Note: This feature is in beta." )
91
+ test_cases =
92
+ string_to_array ( get_value_from_value_or_file ( params [ :test_case_ids ] , params [ :test_case_ids_file ] ) ) &.map { |id | "#{ app_name } /testCases/#{ id } " }
92
93
test_password = test_password_from_params ( params )
93
- release_test = test_release ( alpha_client , release , test_devices , params [ :test_username ] , test_password , params [ :test_username_resource ] , params [ :test_password_resource ] )
94
+ release_tests = test_release ( alpha_client , release , test_devices , test_cases , params [ :test_username ] , test_password , params [ :test_username_resource ] , params [ :test_password_resource ] )
94
95
unless params [ :test_non_blocking ]
95
- poll_test_finished ( alpha_client , release_test . name )
96
+ poll_test_finished ( alpha_client , release_tests )
96
97
end
97
98
end
98
99
@@ -279,7 +280,7 @@ def self.poll_upload_release_operation(client, operation, binary_type)
279
280
extract_release ( operation )
280
281
end
281
282
282
- def self . upload_binary ( app_name , binary_path , binary_type , client , timeout )
283
+ def self . upload_binary ( client , app_name , binary_path , binary_type , timeout )
283
284
options = Google ::Apis ::RequestOptions . new
284
285
options . max_elapsed_time = timeout # includes retries (default = no retries)
285
286
options . header = {
@@ -359,7 +360,10 @@ def self.distribute_release(client, release, request)
359
360
end
360
361
end
361
362
362
- def self . test_release ( alpha_client , release , test_devices , username = nil , password = nil , username_resource = nil , password_resource = nil )
363
+ def self . test_release ( alpha_client , release , test_devices , test_cases , username = nil , password = nil , username_resource = nil , password_resource = nil )
364
+ if present? ( test_cases ) && ( !username_resource . nil? || !password_resource . nil? )
365
+ UI . user_error! ( "Password and username resource names are not supported for the AI testing agent." )
366
+ end
363
367
if username_resource . nil? ^ password_resource . nil?
364
368
UI . user_error! ( "Username and password resource names for automated tests need to be specified together." )
365
369
end
@@ -401,37 +405,64 @@ def self.test_release(alpha_client, release, test_devices, username = nil, passw
401
405
)
402
406
end
403
407
408
+ UI . message ( "🤖 Starting automated tests. Note: This feature is in beta." )
409
+ release_tests = [ ]
410
+ if present? ( test_cases )
411
+ test_cases . each do |tc |
412
+ release_tests . push ( create_release_test ( alpha_client , release . name , device_executions , login_credential , tc ) )
413
+ end
414
+ else
415
+ release_tests . push ( create_release_test ( alpha_client , release . name , device_executions , login_credential ) )
416
+ end
417
+ release_tests
418
+ end
419
+
420
+ def self . create_release_test ( alpha_client , release_name , device_executions , login_credential , test_case_name = nil )
404
421
release_test =
405
422
Google ::Apis ::FirebaseappdistributionV1alpha ::GoogleFirebaseAppdistroV1alphaReleaseTest . new (
423
+ device_executions : device_executions ,
406
424
login_credential : login_credential ,
407
- device_executions : device_executions
425
+ test_case : test_case_name
408
426
)
409
- alpha_client . create_project_app_release_test ( release . name , release_test )
427
+ alpha_client . create_project_app_release_test ( release_name , release_test )
410
428
rescue Google ::Apis ::Error => err
411
- UI . crash! ( err )
429
+ case err . status_code . to_i
430
+ when 404
431
+ UI . user_error! ( "Test Case #{ test_case_name } not found" )
432
+ else
433
+ UI . crash! ( err )
434
+ end
412
435
end
413
436
414
- def self . poll_test_finished ( alpha_client , release_test_name )
437
+ def self . poll_test_finished ( alpha_client , release_tests )
438
+ release_test_names = release_tests . map ( &:name )
415
439
TEST_MAX_POLLING_RETRIES . times do
416
- UI . message ( "⏳ The automated test results are pending." )
440
+ UI . message ( "⏳ #{ release_test_names . size } automated test results are pending." )
417
441
sleep ( TEST_POLLING_INTERVAL_SECONDS )
418
- release_test = alpha_client . get_project_app_release_test ( release_test_name )
419
- if release_test . device_executions . all? { |e | e . state == 'PASSED' }
420
- UI . success ( "✅ Passed automated test(s)." )
421
- return
422
- end
423
- release_test . device_executions . each do |de |
424
- case de . state
425
- when 'PASSED' , 'IN_PROGRESS'
426
- next
427
- when 'FAILED'
428
- UI . test_failure! ( "Automated test failed for #{ device_to_s ( de . device ) } : #{ de . failed_reason } ." )
429
- when 'INCONCLUSIVE'
430
- UI . test_failure! ( "Automated test inconclusive for #{ device_to_s ( de . device ) } : #{ de . inconclusive_reason } ." )
442
+ release_test_names . delete_if do |release_test_name |
443
+ release_test = alpha_client . get_project_app_release_test ( release_test_name )
444
+ if release_test . device_executions . all? { |e | e . state == 'PASSED' }
445
+ true
431
446
else
432
- UI . test_failure! ( "Unsupported automated test state for #{ device_to_s ( de . device ) } : #{ de . state } ." )
447
+ release_test . device_executions . each do |de |
448
+ case de . state
449
+ when 'PASSED' , 'IN_PROGRESS'
450
+ next
451
+ when 'FAILED'
452
+ UI . test_failure! ( "Automated test failed for #{ device_to_s ( de . device ) } : #{ de . failed_reason } ." )
453
+ when 'INCONCLUSIVE'
454
+ UI . test_failure! ( "Automated test inconclusive for #{ device_to_s ( de . device ) } : #{ de . inconclusive_reason } ." )
455
+ else
456
+ UI . test_failure! ( "Unsupported automated test state for #{ device_to_s ( de . device ) } : #{ de . state } ." )
457
+ end
458
+ end
459
+ false
433
460
end
434
461
end
462
+ if release_test_names . empty?
463
+ UI . success ( "✅ Passed automated test(s)." )
464
+ return
465
+ end
435
466
end
436
467
UI . test_failure! ( "It took longer than expected to process your test, please try again." )
437
468
end
@@ -580,6 +611,16 @@ def self.available_options
580
611
optional : false ,
581
612
default_value : false ,
582
613
type : Boolean ) ,
614
+ FastlaneCore ::ConfigItem . new ( key : :test_case_ids ,
615
+ env_name : "FIREBASEAPPDISTRO_TEST_CASE_IDS" ,
616
+ description : "Test Case IDs, separated by commas. Note: This feature is in beta" ,
617
+ optional : true ,
618
+ type : String ) ,
619
+ FastlaneCore ::ConfigItem . new ( key : :test_case_ids_file ,
620
+ env_name : "FIREBASEAPPDISTRO_TEST_CASE_IDS_FILE" ,
621
+ description : "Path to file with containing Test Case IDs, separated by commas or newlines. Note: This feature is in beta" ,
622
+ optional : true ,
623
+ type : String ) ,
583
624
584
625
# Auth
585
626
FastlaneCore ::ConfigItem . new ( key : :firebase_cli_token ,
0 commit comments