অ্যাপ অ্যাকশন টেস্ট লাইব্রেরি (AATL) ডেভেলপারদের প্রোগ্রাম্যাটিকভাবে অ্যাপ অ্যাকশন ফুলফিলমেন্ট পরীক্ষা করার ক্ষমতা প্রদান করে, যা সাধারণত প্রকৃত ভয়েস কোয়েরি বা অ্যাপ অ্যাকশন টেস্ট টুল ব্যবহার করে করা হয়।
লাইব্রেরিটি নিশ্চিত করতে সাহায্য করে যে shortcut.xml কনফিগারেশন সঠিক এবং
বর্ণিত Android ইনটেন্ট ইনভোকেশন সফল হয়েছে। অ্যাপ অ্যাকশন টেস্ট লাইব্রেরি
আপনার অ্যাপের নির্দিষ্ট Google Assistant ইনটেন্ট ও প্যারামিটার পূরণ করার ক্ষমতা পরীক্ষা করার জন্য একটি মেকানিজম প্রদান করে। এটি করার জন্য, এটি সেগুলিকে একটি Android ডিপ লিঙ্ক বা Android ইনটেন্টে রূপান্তর করে, যা একটি Android অ্যাক্টিভিটি ইনস্ট্যান্টিয়েট করতে ব্যবহার করা যেতে পারে।
Android এনভায়রনমেন্টে Robolectric ইউনিট বা ইনস্ট্রুমেন্টেড টেস্টের মাধ্যমে পরীক্ষা করা হয়। এটি ডেভেলপারদের তাদের অ্যাপ্লিকেশনটি আসল অ্যাপের মতো আচরণ করে ব্যাপকভাবে পরীক্ষা করার অনুমতি দেয়। BII, কাস্টম ইনটেন্ট বা ডিপ লিঙ্ক ফুলফিলমেন্ট পরীক্ষা করার জন্য, যেকোনও ইনস্ট্রুমেন্টেড টেস্টিং ফ্রেমওয়ার্ক ব্যবহার করা যেতে পারে (UI Automator, Espresso, JUnit4, Appium, Detox, Calabash)।
অ্যাপ্লিকেশনটি বহুভাষিক হলে, ডেভেলপাররা যাচাই করতে পারেন যে অ্যাপ্লিকেশনটির কার্যকারিতা বিভিন্ন লোকেলে সঠিকভাবে কাজ করছে কিনা।
এটি কীভাবে কাজ করে
অ্যাপের টেস্টিং এনভায়রনমেন্টের মধ্যে অ্যাপ অ্যাকশন টেস্ট লাইব্রেরি ইন্টিগ্রেট করতে, ডেভেলপারদের
অ্যাপের app মডিউলে নতুন রোবোলেক্ট্রিক বা ইনস্ট্রুমেন্টেড টেস্ট তৈরি করতে বা আগে থেকে থাকা টেস্ট আপডেট করতে হবে।
টেস্ট কোডে নিম্নলিখিত অংশগুলি থাকে:
- সাধারণ সেট-আপ পদ্ধতি বা স্বতন্ত্র টেস্ট কেসে লাইব্রেরি ইনস্ট্যান্সের ইনিশিয়ালাইজেশন।
- ইনটেন্ট তৈরির ফলাফল পেতে প্রতিটি স্বতন্ত্র টেস্ট লাইব্রেরি ইনস্ট্যান্সের
fulfillমেথডকে কল করে। - তারপর ডেভেলপার ডিপ লিঙ্ক অ্যাসার্ট করেন বা অ্যাপ ফুলফিলমেন্ট ট্রিগার করেন, এবং অ্যাপের স্ট্যাটাসে কাস্টম ভ্যালিডেশন চালান।
সেট-আপ করার জন্য প্রয়োজনীয় শর্ত
টেস্ট লাইব্রেরি ব্যবহার করার জন্য, আপনার অ্যাপ্লিকেশনে টেস্ট যোগ করার আগে কিছু প্রাথমিক অ্যাপ কনফিগারেশন প্রয়োজন।
কনফিগারেশন
অ্যাপ অ্যাকশন টেস্ট লাইব্রেরি ব্যবহার করতে, আপনার অ্যাপ নিম্নলিখিত উপায়ে কনফিগার করা আছে কিনা তা নিশ্চিত করুন:
- Android Gradle প্লাগ-ইন (AGP) ইনস্টল করুন
appমডিউলেরres/xmlফোল্ডারেshortcuts.xmlফাইল যোগ করুন।- নিশ্চিত করুন যে
AndroidManifest.xml-এ<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />অন্তর্ভুক্ত আছে এগুলির মধ্যে যেকোনও একটির অধীনে:<application>ট্যাগ- লঞ্চার
<activity>ট্যাগ
shortcuts.xml-এ<shortcuts>এলিমেন্টের মধ্যে<capability>এলিমেন্ট রাখুন
অ্যাপ অ্যাকশন টেস্ট লাইব্রেরি ডিপেন্ডেন্সি যোগ করুন
settings.gradle-এ প্রোজেক্ট রিপোজিটরির তালিকায় Google রিপোজিটরি যোগ করুন:allprojects { repositories { … google() } }অ্যাপ মডিউল
build.gradleফাইলে, AATL ডিপেন্ডেন্সি যোগ করুন:androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'আপনি যে লাইব্রেরি ডাউনলোড করেছেন সেটির ভার্সন নম্বর ব্যবহার করছেন কিনা তা নিশ্চিত করুন।
ইন্টিগ্রেশন টেস্ট তৈরি করুন
app/src/androidTest-এর অধীনে নতুন পরীক্ষা তৈরি করুন। Robolectric পরীক্ষার জন্য,app/src/test-এর অধীনে সেগুলি তৈরি করুন:Kotlin
import android.content.Context import android.content.Intent import android.widget.TextView import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ActivityScenario import com.google.assistant.appactions.testing.aatl.AppActionsTestManager import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType import com.google.common.collect.ImmutableMap import org.junit.Assert.assertEquals import org.junit.Before import org.junit.runner.RunWith import org.junit.Test import org.robolectric.RobolectricTestRunner … @Test fun IntentTestExample() { val intentParams = mapOf("feature" to "settings") val intentName = "actions.intent.OPEN_APP_FEATURE" val result = aatl.fulfill(intentName, intentParams) assertEquals(FulfillmentType.INTENT, result.getFulfillmentType()) val intentResult = result as AppActionsFulfillmentIntentResult val intent = intentResult.intent // Developer can choose to assert different relevant properties of the returned intent, such as the action, activity, package, scheme and so on assertEquals("youtube", intent.scheme) assertEquals("settings", intent.getStringExtra("featureParam")) assertEquals("actions.intent.OPEN_APP_FEATURE", intent.action) assertEquals("com.google.android.youtube/.MainActivity", intent.component.flattenToShortString()) assertEquals("com.google.myapp", intent.package) // Developers can choose to use returned Android Intent to launch and assess the activity. Below are examples for how it will look like for Robolectric and Espresso tests. // Please note that the below part is just a possible example of how Android tests are validating Activity functionality correctness for given Android Intent. // Robolectric example: val activity = Robolectric.buildActivity(MainActivity::class.java, intentResult.intent).create().resume().get() val title: TextView = activity.findViewById(R.id.startActivityTitle) assertEquals(title?.text?.toString(), "Launching…") }
জাভা
import android.content.Context; import android.content.Intent; import android.widget.TextView; import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ActivityScenario; import com.google.assistant.appactions.testing.aatl.AppActionsTestManager; import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult; import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult; import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType; import com.google.common.collect.ImmutableMap; import org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.Test; import org.robolectric.RobolectricTestRunner; ... @Test public void IntentTestExample() throws Exception { Map<String, String> intentParams = ImmutableMap.of("feature", "settings"); String intentName = "actions.intent.OPEN_APP_FEATURE"; AppActionsFulfillmentResult result = aatl.fulfill(intentName, intentParams); assertEquals(FulfillmentType.INTENT, result.getFulfillmentType()); AppActionsFulfillmentIntentResult intentResult = (AppActionsFulfillmentIntentResult) result; Intent intent = intentResult.getIntent(); // Developer can choose to assert different relevant properties of the returned intent, such as the action, activity, package, or scheme assertEquals("settings", intent.getStringExtra("featureParam")); assertEquals("actions.intent.OPEN_APP_FEATURE", intent.getAction()); assertEquals("com.google.android.youtube/.MainActivity", intent.getComponent().flattenToShortString()); assertEquals("com.google.myapp", intent.getPackage()); // Developers can choose to use returned Android Intent to launch and assess the activity. Below are examples for how it will look like for Robolectric and Espresso tests. // Please note that the below part is just a possible example of how Android tests are validating Activity functionality correctness for given Android Intent. // Robolectric example: MainActivity activity = Robolectric.buildActivity(MainActivity.class,intentResult.intent).create().resume().get(); TextView title: TextView = activity.findViewById(R.id.startActivityTitle) assertEquals(title?.getText()?.toString(), "Launching…") }
আপনি Espresso ব্যবহার করলে, AATL ফলাফলের উপর ভিত্তি করে অ্যাক্টিভিটি কীভাবে লঞ্চ করবেন তা আপনাকে পরিবর্তন করতে হবে।
ActivityScenarioপদ্ধতি ব্যবহার করে Espresso-এর একটি উদাহরণ এখানে দেওয়া হল:Kotlin
ActivityScenario.launch<MainActivity>(intentResult.intent); Espresso.onView(ViewMatchers.withId(R.id.startActivityTitle)) .check(ViewAssertions.matches(ViewMatchers.withText("Launching…")))
জাভা
ActivityScenario.launch<MainActivity>(intentResult.intent); Espresso.onView(ViewMatchers.withId(R.id.startActivityTitle)) .check(ViewAssertions.matches(ViewMatchers.withText("Launching…")))
প্যারামিটার ম্যাপিংয়ে নাম ও মূল প্রপার্টি যেন BII-এর প্যারামিটারের সাথে ম্যাচ করে। যেমন,
exercisePlan.forExercise.name,GET_EXERCISE_PLAN-এ প্যারামিটারের জন্য ডকুমেন্টেশনের সাথে মেলে।Android Context প্যারামিটার (
ApplicationProviderবাInstrumentationRegistryথেকে প্রাপ্ত):- সিঙ্গেল মডিউল অ্যাপ আর্কিটেকচার:
Kotlin
private lateinit var aatl: AppActionsTestManager @Before fun init() { val appContext = ApplicationProvider.getApplicationContext() aatl = AppActionsTestManager(appContext) }
জাভা
private AppActionsTestManager aatl; @Before public void init() { Context appContext = ApplicationProvider.getApplicationContext(); aatl = new AppActionsTestManager(appContext); }
- মাল্টি-মডিউল অ্যাপ আর্কিটেকচার:
Kotlin
private lateinit var aatl: AppActionsTestManager @Before fun init() { val appContext = ApplicationProvider.getApplicationContext() val lookupPackages = listOf("com.myapp.mainapp", "com.myapp.resources") aatl = AppActionsTestManager(appContext, lookupPackages) }
জাভা
private AppActionsTestManager aatl; @Before public void init() throws Exception { Context appContext = ApplicationProvider.getApplicationContext(); List<String> lookupPackages = Arrays.asList("com.myapp.mainapp","com.myapp.resources"); aatl = new AppActionsTestManager(appContext, Optional.of(lookupPackages)); }
API-এর
fulfillপদ্ধতিটি এক্সিকিউট করুন এবংAppActionsFulfillmentResultঅবজেক্টটি পান।
অ্যাসার্শন পারফর্ম করুন
App Actions টেস্ট লাইব্রেরি অ্যাসার্ট করার জন্য সাজেস্ট করা পদ্ধতি হল:
AppActionsFulfillmentResult-এর ফুলফিলমেন্টের ধরন অ্যাসার্ট করুন। অপ্রত্যাশিত BII অনুরোধের ক্ষেত্রে অ্যাপটি কীভাবে আচরণ করে তা পরীক্ষা করার জন্য এটিFulfillmentType.INTENT, বাFulfillmentType.UNFULFILLEDহতে হবে।- ফুলফিলমেন্টের ২ ধরনের ফ্লেভার আছে:
INTENTএবংDEEPLINKফুলফিলমেন্ট।- সাধারণত, ডেভেলপার
INTENTএবংDEEPLINK-এর মধ্যে পার্থক্য করতে পারেনshortcuts.xml-এ ইনটেন্ট ট্যাগ দেখে যা তারা লাইব্রেরি ট্রিগার করে পূরণ করছেন। - ইন্টেন্ট ট্যাগের অধীনে url-template ট্যাগ থাকলে, এটি ইঙ্গিত করে যে
DEEPLINKএই ইন্টেন্ট পূরণ করে। - ফলাফল ইনটেন্টের
getData()পদ্ধতি যদি নন-নাল অবজেক্ট রিটার্ন করে, তাহলে এটিওDEEPLINKফুলফিলমেন্ট নির্দেশ করে। একইভাবে,getDataযদিnullরিটার্ন করে, তাহলে বুঝতে হবে যে এটিINTENTফুলফিলমেন্ট।
- সাধারণত, ডেভেলপার
INTENTকেসের জন্য,AppActionsFulfillmentResult-কেAppActionsIntentFulfillmentResult-এ টাইপকাস্ট করুন,getIntentপদ্ধতি কল করে Android ইনটেন্ট ফেচ করুন এবং নিম্নলিখিতগুলির মধ্যে একটি করুন:- Android Intent-এর স্বতন্ত্র ফিল্ড অ্যাসার্ট করুন।
- intent.getData.getHost পদ্ধতির মাধ্যমে অ্যাক্সেস করা হয়েছে এমন ইনটেন্টের uri অ্যাসার্ট করুন।
DEEPLINKকেসের জন্য,AppActionsFulfillmentResult-কেAppActionsIntentFulfillmentResult-এ টাইপকাস্ট করুন (উপরেINTENTপরিস্থিতির মতোই),getIntentপদ্ধতি কল করে Android ইনটেন্ট ফেচ করুন এবং ডিপলিঙ্ক URL (intent.getData.getHost-এর মাধ্যমে অ্যাক্সেস করা) অ্যাসার্ট করুন।INTENTএবংDEEPLINK, দুটির ক্ষেত্রেই আপনি বেছে নেওয়া Android টেস্টিং ফ্রেমওয়ার্কের মাধ্যমে অ্যাক্টিভিটি লঞ্চ করার জন্য ফলাফল হিসেবে পাওয়া ইনটেন্ট ব্যবহার করতে পারবেন।
ইন্টারন্যাশনালাইজেশন
আপনার অ্যাপে একাধিক লোকেল থাকলে, আপনি টেস্টের অধীনে একটি নির্দিষ্ট লোকেল চালানোর জন্য টেস্ট কনফিগার করতে পারেন। অন্যথায়, আপনি সরাসরি লোকেল পরিবর্তন করতে পারেন:
Kotlin
import android.content.res.Configuration import java.util.Locale ... val newLocale = Locale("es") val conf = context.resources.configuration conf = Configuration(conf) conf.setLocale(newLocale)
জাভা
Locale newLocale = new Locale("es"); Configuration conf = context.getResources().getConfiguration(); conf = new Configuration(conf); conf.setLocale(newLocale);
স্প্যানিশ (ES) লোকেলের জন্য কনফিগার করা AATL টেস্টের একটি উদাহরণ এখানে দেওয়া হল:
Kotlin
import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertEquals import android.content.Context import android.content.res.Configuration import androidx.test.platform.app.InstrumentationRegistry import com.google.assistant.appactions.testing.aatl.AppActionsTestManager import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType import com.google.common.collect.ImmutableMap import java.util.Locale import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class ShortcutForDifferentLocaleTest { @Before fun setUp() { val context = InstrumentationRegistry.getInstrumentation().getContext() // change the device locale to 'es' val newLocale = Locale("es") val conf = context.resources.configuration conf = Configuration(conf) conf.setLocale(newLocale) val localizedContext = context.createConfigurationContext(conf) } @Test fun shortcutForDifferentLocale_succeeds() { val aatl = AppActionsTestManager(localizedContext) val intentName = "actions.intent.GET_EXERCISE_PLAN" val intentParams = ImmutableMap.of("exercisePlan.forExercise.name", "Running") val result = aatl.fulfill(intentName, intentParams) assertThat(result.getFulfillmentType()).isEqualTo(FulfillmentType.INTENT) val intentResult = result as AppActionsFulfillmentIntentResult assertThat(intentResult.getIntent().getData().toString()) .isEqualTo("myexercise://browse?plan=running_weekly") } }
জাভা
import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import android.content.Context; import android.content.res.Configuration; import androidx.test.platform.app.InstrumentationRegistry; import com.google.assistant.appactions.testing.aatl.AppActionsTestManager; import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult; import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult; import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType; import com.google.common.collect.ImmutableMap; import java.util.Locale; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @Test public void shortcutForDifferentLocale_succeeds() throws Exception { Context context = InstrumentationRegistry.getInstrumentation().getContext(); // change the device locale to 'es' Locale newLocale = new Locale("es"); Configuration conf = context.getResources().getConfiguration(); conf = new Configuration(conf); conf.setLocale(newLocale); Context localizedContext = context.createConfigurationContext(conf); AppActionsTestManager aatl = new AppActionsTestManager(localizedContext); String intentName = "actions.intent.GET_EXERCISE_PLAN"; ImmutableMap<String, String> intentParams = ImmutableMap.of("exercisePlan.forExercise.name", "Running"); AppActionsFulfillmentResult result = aatl.fulfill(intentName, intentParams); assertThat(result.getFulfillmentType()).isEqualTo(FulfillmentType.INTENT); AppActionsFulfillmentIntentResult intentResult = (AppActionsFulfillmentIntentResult) result; assertThat(intentResult.getIntent().getData().toString()) .isEqualTo("myexercise://browse?plan=running_weekly"); }
সমস্যার সমাধান করুন
আপনার ইন্টিগ্রেশন টেস্ট অপ্রত্যাশিতভাবে ব্যর্থ হলে, আপনি সতর্কতা বা ত্রুটি স্তরের মেসেজ পেতে Android Studio logcat উইন্ডোতে AATL লগ মেসেজ খুঁজতে পারেন। এছাড়াও, লাইব্রেরি থেকে আরও আউটপুট ক্যাপচার করতে আপনি লগিং লেভেল বাড়াতে পারেন।
সীমাবদ্ধতা
App Actions Test Library-র বর্তমান সীমাবদ্ধতাগুলি হল :
- AATL ন্যাচারাল ল্যাঙ্গুয়েজ আন্ডারস্ট্যান্ডিং (NLU) বা স্পিচ-টু-টেক্সট (STT) ফিচার পরীক্ষা করে না।
- ডিফল্ট অ্যাপ মডিউল ছাড়া অন্য মডিউলে পরীক্ষা করা হলে AATL কাজ করে না।
- AATL শুধুমাত্র Android 7.0 "Nougat" (API লেভেল ২৪) এবং তার পরবর্তী ভার্সনের সাথে মানানসই।