کتابخانه آزمایشی App Actions (AATL) قابلیتهایی را فراهم میکند تا توسعهدهندگان را قادر میسازد تا اجرای App Action را به صورت برنامهریزی آزمایش کنند، آزمایشهایی را خودکار میکند که معمولاً با استفاده از جستارهای صوتی واقعی یا ابزار تست App Actions انجام میشود.
این کتابخانه کمک میکند تا اطمینان حاصل شود که پیکربندی shortcut.xml
درست است و فراخوانی هدف Android توصیفشده با موفقیت انجام میشود. App Actions Test Library مکانیزمی را برای آزمایش توانایی برنامه شما در انجام اهداف و پارامترهای دستیار Google با تبدیل آنها به پیوند عمیق Android یا قصد Android ارائه میکند، که میتواند برای نمونهبرداری از یک فعالیت Android استفاده شود.
تست به صورت واحد Robolectric یا تست های ابزاردار در محیط اندروید انجام می شود. این به توسعه دهندگان اجازه می دهد تا برنامه خود را با شبیه سازی رفتار واقعی برنامه به طور جامع آزمایش کنند. برای آزمایش BII ها، مقاصد سفارشی یا انجام پیوند عمیق، می توان از هر چارچوب تست ابزاردار (UI Automator، Espresso، JUnit4، Appium، Detox، Calabash) استفاده کرد.
اگر برنامه چند زبانه باشد، توسعه دهندگان می توانند تأیید کنند که عملکرد برنامه در مناطق مختلف به درستی عمل می کند.
چگونه کار می کند
برای ادغام App Actions Test Library در محیط آزمایش برنامه، توسعهدهندگان باید آزمایشهای Robolectric یا ابزاردار موجود را در ماژول app
برنامه ایجاد یا بهروزرسانی کنند.
کد تست شامل بخش های زیر است:
- راهاندازی نمونه کتابخانه، در روش راهاندازی رایج یا در موارد آزمایشی فردی.
- هر آزمون فردی روش
fulfill
نمونه کتابخانه را برای تولید نتیجه ایجاد قصد فراخوانی می کند. - سپس توسعهدهنده پیوند عمیق را تأیید میکند یا اجرای برنامه را فعال میکند و اعتبارسنجی سفارشی را در وضعیت برنامه اجرا میکند.
الزامات راه اندازی
برای استفاده از کتابخانه آزمایشی، قبل از افزودن آزمایشات به برنامه شما، پیکربندی اولیه برنامه مورد نیاز است.
پیکربندی
برای استفاده از App Actions Test Library، مطمئن شوید که برنامه شما به صورت زیر پیکربندی شده است:
- پلاگین Android Gradle (AGP) را نصب کنید
- یک فایل
shortcuts.xml
را در پوشهres/xml
در ماژولapp
قرار دهید. - مطمئن شوید که
AndroidManifest.xml
شامل<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />
در زیر است:- تگ
<application>
- تگ لانچر
<activity>
- تگ
- عنصر
<capability>
را در داخل عنصر<shortcuts>
درshortcuts.xml
قرار دهید
افزودن وابستگیهای کتابخانه آزمایشی اقدامات برنامه
مخزن Google را به لیست مخازن پروژه در
settings.gradle
اضافه کنید:allprojects { repositories { … google() } }
در فایل
build.gradle
ماژول برنامه، وابستگی های AATL را اضافه کنید:androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.
ایجاد تست های یکپارچه سازی
تست های جدید را در
app/src/androidTest
ایجاد کنید. برای تست های روبولکتریک، آنها را در زیرapp/src/test
ایجاد کنید:کاتلین
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…") }
اگر از اسپرسو استفاده می کنید، باید نحوه راه اندازی فعالیت را بر اساس نتایج AATL تغییر دهید. در اینجا یک مثال برای اسپرسو با استفاده از روش
ActivityScenario
آورده شده است:کاتلین
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
مطابقت دارد.نمونه API را با پارامتر Context Android (به دست آمده از
ApplicationProvider
یاInstrumentationRegistry
):- معماری اپلیکیشن تک ماژول:
کاتلین
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); }
- معماری اپلیکیشن چند ماژول:
کاتلین
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)); }
متد
fulfill
API را اجرا کنید و شیAppActionsFulfillmentResult
را بدست آورید.
اظهارات را انجام دهید
روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:
- نوع تحقق
AppActionsFulfillmentResult
را مشخص کنید. بایدFulfillmentType.INTENT
یاFulfillmentType.UNFULFILLED
باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند. - 2 طعم برای تحقق وجود دارد: تحقق
INTENT
وDEEPLINK
.- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
shortcuts.xml
بین اجراهایINTENT
وDEEPLINK
که با راهاندازی کتابخانه انجام میشوند، تفاوت قائل شود. - اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که
DEEPLINK
این هدف را برآورده می کند. - اگر متد
getData()
intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحققDEEPLINK
است. به همین ترتیب، اگرgetData
null
را برگرداند، به این معنی است که یک تحققINTENT
است.
- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
- برای مورد
INTENT
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید، با فراخوانی متدgetIntent
، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:- فیلدهای فردی Android Intent را وارد کنید.
- uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
- برای مورد
DEEPLINK
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید (همانطور که در سناریویINTENT
بالا)، Intent Android را با فراخوانی متدgetIntent
واکشی کنید و URL deeplink را وارد کنید (از طریقintent.getData.getHost
قابل دسترسی است). - هم برای
INTENT
و همDEEPLINK
، میتوانید از قصد بهدستآمده برای راهاندازی فعالیت با چارچوب تست انتخابی Android استفاده کنید.
بین المللی شدن
اگر برنامه شما دارای چندین منطقه است، میتوانید آزمایشها را برای اجرای زیرآزمایش یک منطقه خاص پیکربندی کنید. از طرف دیگر، می توانید مستقیماً منطقه را تغییر دهید:
کاتلین
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);
در اینجا نمونه ای از تست AATL است که برای زبان اسپانیایی (ES) پیکربندی شده است:
کاتلین
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"); }
عیب یابی
اگر تست یکپارچه سازی شما به طور غیرمنتظره ای با شکست مواجه شد، می توانید به دنبال پیام های گزارش AATL در پنجره ورود به سیستم Android Studio بگردید تا پیام اخطار یا سطح خطا را دریافت کنید. همچنین می توانید سطح ثبت را افزایش دهید تا خروجی بیشتری از کتابخانه بگیرید.
محدودیت ها
اینها محدودیتهای فعلی کتابخانه آزمایشی اقدامات برنامه هستند:
- AATL ویژگی های درک زبان طبیعی (NLU) یا گفتار به متن (STT) را آزمایش نمی کند.
- وقتی آزمایشها در ماژولهایی غیر از ماژول برنامه پیشفرض هستند، AATL کار نمیکند.
- AATL فقط با Android 7.0 "Nougat" (سطح API 24) و جدیدتر سازگار است.
کتابخانه آزمایشی App Actions (AATL) قابلیتهایی را فراهم میکند تا توسعهدهندگان را قادر میسازد تا اجرای App Action را به صورت برنامهریزی آزمایش کنند، آزمایشهایی را خودکار میکند که معمولاً با استفاده از جستارهای صوتی واقعی یا ابزار تست App Actions انجام میشود.
این کتابخانه کمک میکند تا اطمینان حاصل شود که پیکربندی shortcut.xml
درست است و فراخوانی هدف Android توصیفشده با موفقیت انجام میشود. App Actions Test Library مکانیزمی را برای آزمایش توانایی برنامه شما در انجام اهداف و پارامترهای دستیار Google با تبدیل آنها به پیوند عمیق Android یا قصد Android ارائه میکند، که میتواند برای نمونهبرداری از یک فعالیت Android استفاده شود.
تست به صورت واحد روبولکتریک یا تست های ابزاردار در محیط اندروید انجام می شود. این به توسعه دهندگان اجازه می دهد تا برنامه خود را با شبیه سازی رفتار واقعی برنامه به طور جامع آزمایش کنند. برای آزمایش BII ها، مقاصد سفارشی یا انجام پیوند عمیق، می توان از هر چارچوب تست ابزاردار (UI Automator، Espresso، JUnit4، Appium، Detox، Calabash) استفاده کرد.
اگر برنامه چند زبانه باشد، توسعه دهندگان می توانند تأیید کنند که عملکرد برنامه در مناطق مختلف به درستی عمل می کند.
چگونه کار می کند
برای ادغام App Actions Test Library در محیط آزمایش برنامه، توسعهدهندگان باید آزمایشهای Robolectric یا ابزاردار موجود را در ماژول app
برنامه ایجاد یا بهروزرسانی کنند.
کد تست شامل بخش های زیر است:
- راهاندازی نمونه کتابخانه، در روش راهاندازی رایج یا در موارد آزمایشی فردی.
- هر آزمون فردی روش
fulfill
نمونه کتابخانه را برای تولید نتیجه ایجاد قصد فراخوانی می کند. - سپس توسعهدهنده پیوند عمیق را تأیید میکند یا اجرای برنامه را فعال میکند و اعتبارسنجی سفارشی را در وضعیت برنامه اجرا میکند.
الزامات راه اندازی
برای استفاده از کتابخانه آزمایشی، قبل از افزودن آزمایشات به برنامه شما، پیکربندی اولیه برنامه مورد نیاز است.
پیکربندی
برای استفاده از App Actions Test Library، مطمئن شوید که برنامه شما به صورت زیر پیکربندی شده است:
- پلاگین Android Gradle (AGP) را نصب کنید
- یک فایل
shortcuts.xml
را در پوشهres/xml
در ماژولapp
قرار دهید. - مطمئن شوید که
AndroidManifest.xml
شامل<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />
در زیر است:- تگ
<application>
- تگ لانچر
<activity>
- تگ
- عنصر
<capability>
را در داخل عنصر<shortcuts>
درshortcuts.xml
قرار دهید
افزودن وابستگیهای کتابخانه آزمایشی اقدامات برنامه
مخزن Google را به لیست مخازن پروژه در
settings.gradle
اضافه کنید:allprojects { repositories { … google() } }
در فایل
build.gradle
ماژول برنامه، وابستگی های AATL را اضافه کنید:androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.
ایجاد تست های یکپارچه سازی
تست های جدید را در
app/src/androidTest
ایجاد کنید. برای تست های روبولکتریک، آنها را در زیرapp/src/test
ایجاد کنید:کاتلین
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…") }
اگر از اسپرسو استفاده می کنید، باید نحوه راه اندازی فعالیت را بر اساس نتایج AATL تغییر دهید. در اینجا یک مثال برای اسپرسو با استفاده از روش
ActivityScenario
آورده شده است:کاتلین
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
مطابقت دارد.نمونه API را با پارامتر Context Android (به دست آمده از
ApplicationProvider
یاInstrumentationRegistry
):- معماری اپلیکیشن تک ماژول:
کاتلین
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); }
- معماری اپلیکیشن چند ماژول:
کاتلین
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)); }
متد
fulfill
API را اجرا کنید و شیAppActionsFulfillmentResult
را بدست آورید.
اظهارات را انجام دهید
روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:
- نوع تحقق
AppActionsFulfillmentResult
را مشخص کنید. بایدFulfillmentType.INTENT
یاFulfillmentType.UNFULFILLED
باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند. - 2 طعم برای تحقق وجود دارد: تحقق
INTENT
وDEEPLINK
.- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
shortcuts.xml
بین اجراهایINTENT
وDEEPLINK
که با راهاندازی کتابخانه انجام میشوند، تفاوت قائل شود. - اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که
DEEPLINK
این هدف را برآورده می کند. - اگر متد
getData()
intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحققDEEPLINK
است. به همین ترتیب، اگرgetData
null
را برگرداند، به این معنی است که یک تحققINTENT
است.
- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
- برای مورد
INTENT
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید، با فراخوانی متدgetIntent
، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:- فیلدهای فردی Android Intent را وارد کنید.
- uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
- برای مورد
DEEPLINK
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید (همانطور که در سناریویINTENT
بالا)، Intent Android را با فراخوانی متدgetIntent
واکشی کنید و URL deeplink را وارد کنید (از طریقintent.getData.getHost
قابل دسترسی است). - هم برای
INTENT
و همDEEPLINK
، میتوانید از قصد بهدستآمده برای راهاندازی فعالیت با چارچوب تست انتخابی Android استفاده کنید.
بین المللی شدن
اگر برنامه شما دارای چندین منطقه است، میتوانید آزمایشها را برای اجرای زیرآزمایش یک منطقه خاص پیکربندی کنید. از طرف دیگر، می توانید مستقیماً منطقه را تغییر دهید:
کاتلین
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);
در اینجا نمونه ای از تست AATL است که برای زبان اسپانیایی (ES) پیکربندی شده است:
کاتلین
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"); }
عیب یابی
اگر تست یکپارچه سازی شما به طور غیرمنتظره ای با شکست مواجه شد، می توانید به دنبال پیام های گزارش AATL در پنجره ورود به سیستم Android Studio بگردید تا پیام اخطار یا سطح خطا را دریافت کنید. همچنین می توانید سطح ثبت را افزایش دهید تا خروجی بیشتری از کتابخانه بگیرید.
محدودیت ها
اینها محدودیتهای فعلی کتابخانه آزمایشی اقدامات برنامه هستند:
- AATL ویژگی های درک زبان طبیعی (NLU) یا گفتار به متن (STT) را آزمایش نمی کند.
- وقتی آزمایشها در ماژولهایی غیر از ماژول برنامه پیشفرض هستند، AATL کار نمیکند.
- AATL فقط با Android 7.0 "Nougat" (سطح API 24) و جدیدتر سازگار است.
کتابخانه آزمایشی App Actions (AATL) قابلیتهایی را فراهم میکند تا توسعهدهندگان را قادر میسازد تا اجرای App Action را به صورت برنامهریزی آزمایش کنند، آزمایشهایی را خودکار میکند که معمولاً با استفاده از جستارهای صوتی واقعی یا ابزار تست App Actions انجام میشود.
این کتابخانه کمک میکند تا اطمینان حاصل شود که پیکربندی shortcut.xml
درست است و فراخوانی هدف Android توصیفشده با موفقیت انجام میشود. App Actions Test Library مکانیزمی را برای آزمایش توانایی برنامه شما در انجام اهداف و پارامترهای دستیار Google با تبدیل آنها به پیوند عمیق Android یا قصد Android ارائه میکند، که میتواند برای نمونهبرداری از یک فعالیت Android استفاده شود.
تست به صورت واحد Robolectric یا تست های ابزاردار در محیط اندروید انجام می شود. این به توسعه دهندگان اجازه می دهد تا برنامه خود را با شبیه سازی رفتار واقعی برنامه به طور جامع آزمایش کنند. برای آزمایش BII ها، مقاصد سفارشی یا انجام پیوند عمیق، می توان از هر چارچوب تست ابزاردار (UI Automator، Espresso، JUnit4، Appium، Detox، Calabash) استفاده کرد.
اگر برنامه چند زبانه باشد، توسعه دهندگان می توانند تأیید کنند که عملکرد برنامه در مناطق مختلف به درستی عمل می کند.
چگونه کار می کند
برای ادغام App Actions Test Library در محیط آزمایش برنامه، توسعهدهندگان باید آزمایشهای Robolectric یا ابزاردار موجود را در ماژول app
برنامه ایجاد یا بهروزرسانی کنند.
کد تست شامل بخش های زیر است:
- راهاندازی نمونه کتابخانه، در روش راهاندازی رایج یا در موارد آزمایشی فردی.
- هر آزمون فردی روش
fulfill
نمونه کتابخانه را برای تولید نتیجه ایجاد قصد فراخوانی می کند. - سپس توسعهدهنده پیوند عمیق را تأیید میکند یا اجرای برنامه را فعال میکند و اعتبارسنجی سفارشی را در وضعیت برنامه اجرا میکند.
الزامات راه اندازی
برای استفاده از کتابخانه آزمایشی، قبل از افزودن آزمایشات به برنامه شما، پیکربندی اولیه برنامه مورد نیاز است.
پیکربندی
برای استفاده از App Actions Test Library، مطمئن شوید که برنامه شما به صورت زیر پیکربندی شده است:
- پلاگین Android Gradle (AGP) را نصب کنید
- یک فایل
shortcuts.xml
را در پوشهres/xml
در ماژولapp
قرار دهید. - مطمئن شوید که
AndroidManifest.xml
شامل<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />
در زیر است:- تگ
<application>
- تگ لانچر
<activity>
- تگ
- عنصر
<capability>
را در داخل عنصر<shortcuts>
درshortcuts.xml
قرار دهید
افزودن وابستگیهای کتابخانه آزمایشی اقدامات برنامه
مخزن Google را به لیست مخازن پروژه در
settings.gradle
اضافه کنید:allprojects { repositories { … google() } }
در فایل
build.gradle
ماژول برنامه، وابستگی های AATL را اضافه کنید:androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.
ایجاد تست های یکپارچه سازی
تست های جدید را در
app/src/androidTest
ایجاد کنید. برای تست های روبولکتریک، آنها را در زیرapp/src/test
ایجاد کنید:کاتلین
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…") }
اگر از اسپرسو استفاده می کنید، باید نحوه راه اندازی فعالیت را بر اساس نتایج AATL تغییر دهید. در اینجا یک مثال برای اسپرسو با استفاده از روش
ActivityScenario
آورده شده است:کاتلین
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
مطابقت دارد.نمونه API را با پارامتر Context Android (به دست آمده از
ApplicationProvider
یاInstrumentationRegistry
):- معماری اپلیکیشن تک ماژول:
کاتلین
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); }
- معماری اپلیکیشن چند ماژول:
کاتلین
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)); }
متد
fulfill
API را اجرا کنید و شیAppActionsFulfillmentResult
را بدست آورید.
اظهارات را انجام دهید
روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:
- نوع تحقق
AppActionsFulfillmentResult
را مشخص کنید. بایدFulfillmentType.INTENT
یاFulfillmentType.UNFULFILLED
باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند. - 2 طعم برای تحقق وجود دارد: تحقق
INTENT
وDEEPLINK
.- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
shortcuts.xml
بین اجراهایINTENT
وDEEPLINK
که با راهاندازی کتابخانه انجام میشوند، تفاوت قائل شود. - اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که
DEEPLINK
این هدف را برآورده می کند. - اگر متد
getData()
intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحققDEEPLINK
است. به همین ترتیب، اگرgetData
null
را برگرداند، به این معنی است که یک تحققINTENT
است.
- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
- برای مورد
INTENT
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید، با فراخوانی متدgetIntent
، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:- فیلدهای فردی Android Intent را وارد کنید.
- uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
- برای مورد
DEEPLINK
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید (همانطور که در سناریویINTENT
بالا)، Intent Android را با فراخوانی متدgetIntent
واکشی کنید و URL deeplink را وارد کنید (از طریقintent.getData.getHost
قابل دسترسی است). - هم برای
INTENT
و همDEEPLINK
، میتوانید از قصد بهدستآمده برای راهاندازی فعالیت با چارچوب تست انتخابی Android استفاده کنید.
بین المللی شدن
اگر برنامه شما دارای چندین منطقه است، میتوانید آزمایشها را برای اجرای زیرآزمایش یک منطقه خاص پیکربندی کنید. از طرف دیگر، می توانید مستقیماً منطقه را تغییر دهید:
کاتلین
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);
در اینجا نمونه ای از تست AATL است که برای زبان اسپانیایی (ES) پیکربندی شده است:
کاتلین
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"); }
عیب یابی
اگر تست یکپارچه سازی شما به طور غیرمنتظره ای با شکست مواجه شد، می توانید به دنبال پیام های گزارش AATL در پنجره ورود به سیستم Android Studio بگردید تا پیام اخطار یا سطح خطا را دریافت کنید. همچنین می توانید سطح ثبت را افزایش دهید تا خروجی بیشتری از کتابخانه بگیرید.
محدودیت ها
اینها محدودیتهای فعلی کتابخانه آزمایشی اقدامات برنامه هستند:
- AATL ویژگی های درک زبان طبیعی (NLU) یا گفتار به متن (STT) را آزمایش نمی کند.
- وقتی آزمایشها در ماژولهایی غیر از ماژول برنامه پیشفرض هستند، AATL کار نمیکند.
- AATL فقط با Android 7.0 "Nougat" (سطح API 24) و جدیدتر سازگار است.
کتابخانه آزمایشی App Actions (AATL) قابلیتهایی را فراهم میکند تا توسعهدهندگان را قادر میسازد تا اجرای App Action را به صورت برنامهریزی آزمایش کنند، آزمایشهایی را خودکار میکند که معمولاً با استفاده از جستارهای صوتی واقعی یا ابزار تست App Actions انجام میشود.
این کتابخانه کمک میکند تا اطمینان حاصل شود که پیکربندی shortcut.xml
درست است و فراخوانی هدف Android توصیفشده با موفقیت انجام میشود. App Actions Test Library مکانیزمی را برای آزمایش توانایی برنامه شما در انجام اهداف و پارامترهای دستیار Google با تبدیل آنها به پیوند عمیق Android یا قصد Android ارائه میکند، که میتواند برای نمونهبرداری از یک فعالیت Android استفاده شود.
تست به صورت واحد روبولکتریک یا تست های ابزاردار در محیط اندروید انجام می شود. این به توسعه دهندگان اجازه می دهد تا برنامه خود را با شبیه سازی رفتار واقعی برنامه به طور جامع آزمایش کنند. برای آزمایش BII ها، مقاصد سفارشی یا انجام پیوند عمیق، می توان از هر چارچوب تست ابزاردار (UI Automator، Espresso، JUnit4، Appium، Detox، Calabash) استفاده کرد.
اگر برنامه چند زبانه باشد، توسعه دهندگان می توانند تأیید کنند که عملکرد برنامه در مناطق مختلف به درستی عمل می کند.
چگونه کار می کند
برای ادغام App Actions Test Library در محیط آزمایش برنامه، توسعهدهندگان باید آزمایشهای Robolectric یا ابزاردار موجود را در ماژول app
برنامه ایجاد یا بهروزرسانی کنند.
کد تست شامل بخش های زیر است:
- راهاندازی نمونه کتابخانه، در روش راهاندازی رایج یا در موارد آزمایشی فردی.
- هر آزمون فردی روش
fulfill
نمونه کتابخانه را برای تولید نتیجه ایجاد قصد فراخوانی می کند. - سپس توسعهدهنده پیوند عمیق را تأیید میکند یا اجرای برنامه را فعال میکند و اعتبارسنجی سفارشی را در وضعیت برنامه اجرا میکند.
الزامات راه اندازی
برای استفاده از کتابخانه آزمایشی، قبل از افزودن آزمایشات به برنامه شما، پیکربندی اولیه برنامه مورد نیاز است.
پیکربندی
برای استفاده از App Actions Test Library، مطمئن شوید که برنامه شما به صورت زیر پیکربندی شده است:
- پلاگین Android Gradle (AGP) را نصب کنید
- یک فایل
shortcuts.xml
را در پوشهres/xml
در ماژولapp
قرار دهید. - مطمئن شوید که
AndroidManifest.xml
شامل<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />
در زیر است:- تگ
<application>
- تگ لانچر
<activity>
- تگ
- عنصر
<capability>
را در داخل عنصر<shortcuts>
درshortcuts.xml
قرار دهید
افزودن وابستگیهای کتابخانه آزمایشی اقدامات برنامه
مخزن Google را به لیست مخازن پروژه در
settings.gradle
اضافه کنید:allprojects { repositories { … google() } }
در فایل
build.gradle
ماژول برنامه، وابستگی های AATL را اضافه کنید:androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.
ایجاد تست های یکپارچه سازی
تست های جدید را در
app/src/androidTest
ایجاد کنید. برای تست های روبولکتریک، آنها را در زیرapp/src/test
ایجاد کنید:کاتلین
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…") }
اگر از اسپرسو استفاده می کنید، باید نحوه راه اندازی فعالیت را بر اساس نتایج AATL تغییر دهید. در اینجا یک مثال برای اسپرسو با استفاده از روش
ActivityScenario
آورده شده است:کاتلین
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
مطابقت دارد.نمونه API را با پارامتر Context Android (به دست آمده از
ApplicationProvider
یاInstrumentationRegistry
):- معماری اپلیکیشن تک ماژول:
کاتلین
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); }
- معماری اپلیکیشن چند ماژول:
کاتلین
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)); }
متد
fulfill
API را اجرا کنید و شیAppActionsFulfillmentResult
را بدست آورید.
اظهارات را انجام دهید
روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:
- نوع تحقق
AppActionsFulfillmentResult
را مشخص کنید. بایدFulfillmentType.INTENT
یاFulfillmentType.UNFULFILLED
باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند. - 2 طعم برای تحقق وجود دارد: تحقق
INTENT
وDEEPLINK
.- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
shortcuts.xml
بین اجراهایINTENT
وDEEPLINK
که با راهاندازی کتابخانه انجام میشوند، تفاوت قائل شود. - اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که
DEEPLINK
این هدف را برآورده می کند. - اگر متد
getData()
intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحققDEEPLINK
است. به همین ترتیب، اگرgetData
null
را برگرداند، به این معنی است که یک تحققINTENT
است.
- به طور معمول، توسعهدهنده میتواند با مشاهده تگ intent در
- برای مورد
INTENT
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید، با فراخوانی متدgetIntent
، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:- فیلدهای فردی Android Intent را وارد کنید.
- uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
- برای مورد
DEEPLINK
،AppActionsFulfillmentResult
بهAppActionsIntentFulfillmentResult
تایپ کنید (همانطور که در سناریویINTENT
بالا)، Intent Android را با فراخوانی متدgetIntent
واکشی کنید و URL deeplink را وارد کنید (از طریقintent.getData.getHost
قابل دسترسی است). - هم برای
INTENT
و همDEEPLINK
، میتوانید از قصد بهدستآمده برای راهاندازی فعالیت با چارچوب تست انتخابی Android استفاده کنید.
بین المللی شدن
اگر برنامه شما دارای چندین منطقه است، میتوانید آزمایشها را برای اجرای زیرآزمایش یک منطقه خاص پیکربندی کنید. از طرف دیگر، می توانید مستقیماً منطقه را تغییر دهید:
کاتلین
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);
در اینجا نمونه ای از تست AATL است که برای زبان اسپانیایی (ES) پیکربندی شده است:
کاتلین
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"); }
عیب یابی
اگر تست یکپارچه سازی شما به طور غیرمنتظره ای با شکست مواجه شد، می توانید به دنبال پیام های گزارش AATL در پنجره ورود به سیستم Android Studio بگردید تا پیام اخطار یا سطح خطا را دریافت کنید. همچنین می توانید سطح ثبت را افزایش دهید تا خروجی بیشتری از کتابخانه بگیرید.
محدودیت ها
اینها محدودیتهای فعلی کتابخانه آزمایشی اقدامات برنامه هستند:
- AATL ویژگی های درک زبان طبیعی (NLU) یا گفتار به متن (STT) را آزمایش نمی کند.
- وقتی آزمایشها در ماژولهایی غیر از ماژول برنامه پیشفرض هستند، AATL کار نمیکند.
- AATL فقط با Android 7.0 "Nougat" (سطح API 24) و جدیدتر سازگار است.