کتابخانه آزمایشی اقدامات برنامه

کتابخانه آزمایشی 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 قرار دهید

افزودن وابستگی‌های کتابخانه آزمایشی اقدامات برنامه

  1. مخزن Google را به لیست مخازن پروژه در settings.gradle اضافه کنید:

        allprojects {
            repositories {
                
                google()
            }
        }
    
  2. در فایل build.gradle ماژول برنامه، وابستگی های AATL را اضافه کنید:

        androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
    

    حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.

ایجاد تست های یکپارچه سازی

  1. تست های جدید را در 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…")))
        
  2. نام و ویژگی های کلید در نگاشت پارامترها با پارامترهای BII مطابقت داشته باشد. برای مثال، exercisePlan.forExercise.name با مستندات مربوط به پارامتر در GET_EXERCISE_PLAN مطابقت دارد.

  3. نمونه 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));
          }
        
      
  4. متد fulfill API را اجرا کنید و شی AppActionsFulfillmentResult را بدست آورید.

اظهارات را انجام دهید

روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:

  1. نوع تحقق AppActionsFulfillmentResult را مشخص کنید. باید FulfillmentType.INTENT یا FulfillmentType.UNFULFILLED باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند.
  2. 2 طعم برای تحقق وجود دارد: تحقق INTENT و DEEPLINK .
    • به طور معمول، توسعه‌دهنده می‌تواند با مشاهده تگ intent در shortcuts.xml بین اجراهای INTENT و DEEPLINK که با راه‌اندازی کتابخانه انجام می‌شوند، تفاوت قائل شود.
    • اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که DEEPLINK این هدف را برآورده می کند.
    • اگر متد getData() intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحقق DEEPLINK است. به همین ترتیب، اگر getData null را برگرداند، به این معنی است که یک تحقق INTENT است.
  3. برای مورد INTENT ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید، با فراخوانی متد getIntent ، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:
    • فیلدهای فردی Android Intent را وارد کنید.
    • uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
  4. برای مورد DEEPLINK ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید (همانطور که در سناریوی INTENT بالا)، Intent Android را با فراخوانی متد getIntent واکشی کنید و URL deeplink را وارد کنید (از طریق intent.getData.getHost قابل دسترسی است).
  5. هم برای 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 قرار دهید

افزودن وابستگی‌های کتابخانه آزمایشی اقدامات برنامه

  1. مخزن Google را به لیست مخازن پروژه در settings.gradle اضافه کنید:

        allprojects {
            repositories {
                
                google()
            }
        }
    
  2. در فایل build.gradle ماژول برنامه، وابستگی های AATL را اضافه کنید:

        androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
    

    حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.

ایجاد تست های یکپارچه سازی

  1. تست های جدید را در 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…")))
        
  2. نام و ویژگی های کلید در نگاشت پارامترها با پارامترهای BII مطابقت داشته باشد. برای مثال، exercisePlan.forExercise.name با مستندات مربوط به پارامتر در GET_EXERCISE_PLAN مطابقت دارد.

  3. نمونه 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));
          }
        
      
  4. متد fulfill API را اجرا کنید و شی AppActionsFulfillmentResult را بدست آورید.

اظهارات را انجام دهید

روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:

  1. نوع تحقق AppActionsFulfillmentResult را مشخص کنید. باید FulfillmentType.INTENT یا FulfillmentType.UNFULFILLED باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند.
  2. 2 طعم برای تحقق وجود دارد: تحقق INTENT و DEEPLINK .
    • به طور معمول، توسعه‌دهنده می‌تواند با مشاهده تگ intent در shortcuts.xml بین اجراهای INTENT و DEEPLINK که با راه‌اندازی کتابخانه انجام می‌شوند، تفاوت قائل شود.
    • اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که DEEPLINK این هدف را برآورده می کند.
    • اگر متد getData() intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحقق DEEPLINK است. به همین ترتیب، اگر getData null را برگرداند، به این معنی است که یک تحقق INTENT است.
  3. برای مورد INTENT ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید، با فراخوانی متد getIntent ، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:
    • فیلدهای فردی Android Intent را وارد کنید.
    • uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
  4. برای مورد DEEPLINK ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید (همانطور که در سناریوی INTENT بالا)، Intent Android را با فراخوانی متد getIntent واکشی کنید و URL deeplink را وارد کنید (از طریق intent.getData.getHost قابل دسترسی است).
  5. هم برای 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 قرار دهید

افزودن وابستگی‌های کتابخانه آزمایشی اقدامات برنامه

  1. مخزن Google را به لیست مخازن پروژه در settings.gradle اضافه کنید:

        allprojects {
            repositories {
                
                google()
            }
        }
    
  2. در فایل build.gradle ماژول برنامه، وابستگی های AATL را اضافه کنید:

        androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
    

    حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.

ایجاد تست های یکپارچه سازی

  1. تست های جدید را در 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…")))
        
  2. نام و ویژگی های کلید در نگاشت پارامترها با پارامترهای BII مطابقت داشته باشد. برای مثال، exercisePlan.forExercise.name با مستندات مربوط به پارامتر در GET_EXERCISE_PLAN مطابقت دارد.

  3. نمونه 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));
          }
        
      
  4. متد fulfill API را اجرا کنید و شی AppActionsFulfillmentResult را بدست آورید.

اظهارات را انجام دهید

روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:

  1. نوع تحقق AppActionsFulfillmentResult را مشخص کنید. باید FulfillmentType.INTENT یا FulfillmentType.UNFULFILLED باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند.
  2. 2 طعم برای تحقق وجود دارد: تحقق INTENT و DEEPLINK .
    • به طور معمول، توسعه‌دهنده می‌تواند با مشاهده تگ intent در shortcuts.xml بین اجراهای INTENT و DEEPLINK که با راه‌اندازی کتابخانه انجام می‌شوند، تفاوت قائل شود.
    • اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که DEEPLINK این هدف را برآورده می کند.
    • اگر متد getData() intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحقق DEEPLINK است. به همین ترتیب، اگر getData null را برگرداند، به این معنی است که یک تحقق INTENT است.
  3. برای مورد INTENT ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید، با فراخوانی متد getIntent ، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:
    • فیلدهای فردی Android Intent را وارد کنید.
    • uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
  4. برای مورد DEEPLINK ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید (همانطور که در سناریوی INTENT بالا)، Intent Android را با فراخوانی متد getIntent واکشی کنید و URL deeplink را وارد کنید (از طریق intent.getData.getHost قابل دسترسی است).
  5. هم برای 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 قرار دهید

افزودن وابستگی‌های کتابخانه آزمایشی اقدامات برنامه

  1. مخزن Google را به لیست مخازن پروژه در settings.gradle اضافه کنید:

        allprojects {
            repositories {
                
                google()
            }
        }
    
  2. در فایل build.gradle ماژول برنامه، وابستگی های AATL را اضافه کنید:

        androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
    

    حتما از شماره نسخه کتابخانه ای که دانلود کرده اید استفاده کنید.

ایجاد تست های یکپارچه سازی

  1. تست های جدید را در 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…")))
        
  2. نام و ویژگی های کلید در نگاشت پارامترها با پارامترهای BII مطابقت داشته باشد. برای مثال، exercisePlan.forExercise.name با مستندات مربوط به پارامتر در GET_EXERCISE_PLAN مطابقت دارد.

  3. نمونه 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));
          }
        
      
  4. متد fulfill API را اجرا کنید و شی AppActionsFulfillmentResult را بدست آورید.

اظهارات را انجام دهید

روش پیشنهادی برای تأیید کتابخانه آزمایشی اقدامات برنامه این است:

  1. نوع تحقق AppActionsFulfillmentResult را مشخص کنید. باید FulfillmentType.INTENT یا FulfillmentType.UNFULFILLED باشد تا نحوه عملکرد برنامه در صورت درخواست های غیرمنتظره BII را آزمایش کند.
  2. 2 طعم برای تحقق وجود دارد: تحقق INTENT و DEEPLINK .
    • به طور معمول، توسعه‌دهنده می‌تواند با مشاهده تگ intent در shortcuts.xml بین اجراهای INTENT و DEEPLINK که با راه‌اندازی کتابخانه انجام می‌شوند، تفاوت قائل شود.
    • اگر یک تگ url-template زیر تگ intent وجود داشته باشد، این نشان می دهد که DEEPLINK این هدف را برآورده می کند.
    • اگر متد getData() intent نتیجه یک شی غیر تهی را برمی گرداند، این نیز نشان دهنده تحقق DEEPLINK است. به همین ترتیب، اگر getData null را برگرداند، به این معنی است که یک تحقق INTENT است.
  3. برای مورد INTENT ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید، با فراخوانی متد getIntent ، Android Intent را واکشی کنید و یکی از کارهای زیر را انجام دهید:
    • فیلدهای فردی Android Intent را وارد کنید.
    • uri یک intent که از طریق متد intent.getData.getHost قابل دسترسی است را مشخص کنید.
  4. برای مورد DEEPLINK ، AppActionsFulfillmentResult به AppActionsIntentFulfillmentResult تایپ کنید (همانطور که در سناریوی INTENT بالا)، Intent Android را با فراخوانی متد getIntent واکشی کنید و URL deeplink را وارد کنید (از طریق intent.getData.getHost قابل دسترسی است).
  5. هم برای 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) و جدیدتر سازگار است.