Skip to content

Commit dcc2fe2

Browse files
committedDec 12, 2024
Support test_case_ids and test_case_ids_file
Bump version to 0.10.0
1 parent 7113e92 commit dcc2fe2

File tree

4 files changed

+131
-31
lines changed

4 files changed

+131
-31
lines changed
 

‎lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def self.run(params)
5757

5858
binary_type = binary_type_from_path(binary_path)
5959
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)
6161
UI.message("🕵️ Validating upload…")
6262
release = poll_upload_release_operation(client, operation, binary_type)
6363

@@ -88,11 +88,12 @@ def self.run(params)
8888
test_devices =
8989
get_value_from_value_or_file(params[:test_devices], params[:test_devices_file])
9090
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}" }
9293
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])
9495
unless params[:test_non_blocking]
95-
poll_test_finished(alpha_client, release_test.name)
96+
poll_test_finished(alpha_client, release_tests)
9697
end
9798
end
9899

@@ -279,7 +280,7 @@ def self.poll_upload_release_operation(client, operation, binary_type)
279280
extract_release(operation)
280281
end
281282

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)
283284
options = Google::Apis::RequestOptions.new
284285
options.max_elapsed_time = timeout # includes retries (default = no retries)
285286
options.header = {
@@ -359,7 +360,10 @@ def self.distribute_release(client, release, request)
359360
end
360361
end
361362

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
363367
if username_resource.nil? ^ password_resource.nil?
364368
UI.user_error!("Username and password resource names for automated tests need to be specified together.")
365369
end
@@ -401,37 +405,64 @@ def self.test_release(alpha_client, release, test_devices, username = nil, passw
401405
)
402406
end
403407

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)
404421
release_test =
405422
Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaReleaseTest.new(
423+
device_executions: device_executions,
406424
login_credential: login_credential,
407-
device_executions: device_executions
425+
test_case: test_case_name
408426
)
409-
alpha_client.create_project_app_release_test(release.name, release_test)
427+
alpha_client.create_project_app_release_test(release_name, release_test)
410428
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
412435
end
413436

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)
415439
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.")
417441
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
431446
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
433460
end
434461
end
462+
if release_test_names.empty?
463+
UI.success("✅ Passed automated test(s).")
464+
return
465+
end
435466
end
436467
UI.test_failure!("It took longer than expected to process your test, please try again.")
437468
end
@@ -580,6 +611,16 @@ def self.available_options
580611
optional: false,
581612
default_value: false,
582613
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),
583624

584625
# Auth
585626
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,48 @@
11
require 'google/apis/firebaseappdistribution_v1'
22
require 'google/apis/firebaseappdistribution_v1alpha'
3+
4+
# This is partially copied from google/apis/firebaseappdistribution_v1alpha v0.9.0 (2024-12-08) based discovery document revision 20241204.
5+
# We can't depend on that version directly as long as fastlane locks google-cloud-env < 2.0.0 (to support Ruby 2.6).
6+
# Newer versions of the API clients depend on google-apis-core >= 0.15.0 which depends on googleauth ~> 1.9 which depends on google-cloud-env ~> 2.1.
7+
# See also https://github.com/fastlane/fastlane/pull/21685#pullrequestreview-2490037163
8+
module Google
9+
module Apis
10+
module FirebaseappdistributionV1alpha
11+
class GoogleFirebaseAppdistroV1alphaReleaseTest
12+
include Google::Apis::Core::Hashable
13+
14+
attr_accessor :create_time
15+
attr_accessor :device_executions
16+
attr_accessor :display_name
17+
attr_accessor :login_credential
18+
attr_accessor :name
19+
attr_accessor :test_case
20+
attr_accessor :test_state
21+
22+
def initialize(**args)
23+
update!(**args)
24+
end
25+
26+
def update!(**args)
27+
@create_time = args[:create_time] if args.key?(:create_time)
28+
@device_executions = args[:device_executions] if args.key?(:device_executions)
29+
@display_name = args[:display_name] if args.key?(:display_name)
30+
@login_credential = args[:login_credential] if args.key?(:login_credential)
31+
@name = args[:name] if args.key?(:name)
32+
@test_case = args[:test_case] if args.key?(:test_case)
33+
@test_state = args[:test_state] if args.key?(:test_state)
34+
end
35+
36+
class Representation < Google::Apis::Core::JsonRepresentation
37+
property :create_time, as: 'createTime'
38+
collection :device_executions, as: 'deviceExecutions', class: Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaDeviceExecution, decorator: Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaDeviceExecution::Representation
39+
property :display_name, as: 'displayName'
40+
property :login_credential, as: 'loginCredential', class: Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaLoginCredential, decorator: Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaLoginCredential::Representation
41+
property :name, as: 'name'
42+
property :test_case, as: 'testCase'
43+
property :test_state, as: 'testState'
44+
end
45+
end
46+
end
47+
end
48+
end
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Fastlane
22
module FirebaseAppDistribution
3-
VERSION = "0.9.1"
3+
VERSION = "0.10.0"
44
end
55
end

‎spec/firebase_app_distribution_action_spec.rb

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,24 @@ def stub_get_aab_info(integration_state = 'INTEGRATED')
625625
end
626626
devices = 'model=model1,version=version1,locale=locale1,orientation=orientation1;version=version2,model=model2,orientation=orientation2,locale=locale2'
627627
action.run({
628-
app: android_app_id,
629-
android_artifact_path: 'path/to.apk',
630-
test_devices: devices,
631-
test_non_blocking: true
632-
})
628+
app: android_app_id,
629+
android_artifact_path: 'path/to.apk',
630+
test_devices: devices,
631+
test_non_blocking: true
632+
})
633+
end
634+
635+
it 'passes test case IDs' do
636+
allow_any_instance_of(Google::Apis::FirebaseappdistributionV1alpha::FirebaseAppDistributionService).to receive(:create_project_app_release_test) do |_, release_name, request|
637+
expect(["#{android_app_name}/testCases/foo", "#{android_app_name}/testCases/bar", "#{android_app_name}/testCases/baz"]).to include(request.test_case)
638+
end
639+
action.run({
640+
app: android_app_id,
641+
android_artifact_path: 'path/to.apk',
642+
test_devices: 'model=model1,version=version1,locale=locale1,orientation=orientation1',
643+
test_case_ids: "foo, bar, baz",
644+
test_non_blocking: true
645+
})
633646
end
634647
end
635648
end

0 commit comments

Comments
 (0)