Uygulama İşlemleri test kitaplığı (AATL), geliştiricilerin Uygulama İşlemi karşılama durumunu programatik olarak test etmesini sağlayan özellikler sunar. Böylece, normalde gerçek sesli sorgular veya Uygulama İşlemleri test aracı kullanılarak yapılacak testleri otomatik hale getirir.
Kitaplık, shortcut.xml
yapılandırmasının doğru olduğundan ve açıklanan Android amaç çağrısının başarılı olduğundan emin olunmasına yardımcı olur. Uygulama İşlemleri Test Kitaplığı, uygulamanızın belirli Google Asistan amacını ve parametrelerini yerine getirme becerisini test etmek için bir mekanizma sağlar. Bunu, bunları bir Android derin bağlantısına veya Android amacına dönüştürerek, üzerinde hak iddia edip bir Android etkinliğini örneklendirmek için kullanabilirsiniz.
Test, Android ortamında Robofactric birimi veya donanımlı testler şeklinde gerçekleştirilir. Bu sayede geliştiriciler, gerçek uygulama davranışına öykünerek uygulamalarını kapsamlı bir şekilde test edebilirler. BiI'ları, özel niyetleri veya derin bağlantı karşılamayı test etmek için herhangi bir araçlı test çerçevesi kullanılabilir (UI Automator, Espresso, JUnit4, Appium, Detox, Calabash).
Uygulama çok dilliyse geliştiriciler uygulamanın işlevselliğinin farklı yerel ayarlarda düzgün çalıştığını doğrulayabilirler.
Nasıl çalışır?
Geliştiriciler, Uygulama İşlemleri Test Kitaplığı'nı uygulamanın test ortamına entegre etmek için uygulamanın app
modülünde yeni Robofactric veya enstrümanlı testler oluşturmalı ya da mevcut testleri güncellemelidir.
Test kodu aşağıdaki bölümleri içerir:
- Ortak kurulum yönteminde veya bağımsız test durumlarında kitaplık örneğinin başlatılması.
- Her bir test, amaç oluşturma sonucunu oluşturmak için kitaplık örneğinin
fulfill
yöntemini çağırır. - Geliştirici daha sonra derin bağlantıyı onaylar veya Uygulama istek karşılamayı tetikler ve uygulama durumunda özel doğrulama çalıştırır.
Kurulum gereksinimleri
Test kitaplığını kullanmak için testleri uygulamanıza eklemeden önce bazı başlangıç uygulama yapılandırması gerekir.
Yapılandırma
Uygulama İşlemleri Test Kitaplığı'nı kullanmak için uygulamanızın aşağıdaki gibi yapılandırıldığından emin olun:
- Android Gradle Eklentisi'ni (AGP) yükleyin
app
modülündekires/xml
klasörüne birshortcuts.xml
dosyası ekleyin.AndroidManifest.xml
öğesinin, şunlardan birinin altında<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />
içerdiğinden emin olun:<application>
etiketi- başlatıcı
<activity>
etiketi
<capability>
öğesinishortcuts.xml
alt kısmındaki<shortcuts>
öğesinin içine yerleştirin
Uygulama İşlemleri Test Kitaplığı bağımlılıkları ekleme
Google deposunu
settings.gradle
bölgesindeki proje depoları listesine ekleyin:allprojects { repositories { … google() } }
Uygulama modülü
build.gradle
dosyasına AATL bağımlılıklarını ekleyin:androidTestImplementation 'com.google.assistant.appactions:testing:1.0.0'
İndirdiğiniz kitaplığın sürüm numarasını kullandığınızdan emin olun.
Entegrasyon testleri oluşturma
app/src/androidTest
altında yeni testler oluşturun. Roboecric testleri için bunlarıapp/src/test
altında oluşturun:Kotlin
import android.content.Context import android.content.Intent import android.widget.TextView import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ActivityScenario import com.google.assistant.appactions.testing.aatl.AppActionsTestManager import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType import com.google.common.collect.ImmutableMap import org.junit.Assert.assertEquals import org.junit.Before import org.junit.runner.RunWith import org.junit.Test import org.robolectric.RobolectricTestRunner … @Test fun IntentTestExample() { val intentParams = mapOf("feature" to "settings") val intentName = "actions.intent.OPEN_APP_FEATURE" val result = aatl.fulfill(intentName, intentParams) assertEquals(FulfillmentType.INTENT, result.getFulfillmentType()) val intentResult = result as AppActionsFulfillmentIntentResult val intent = intentResult.intent // Developer can choose to assert different relevant properties of the returned intent, such as the action, activity, package, scheme and so on assertEquals("youtube", intent.scheme) assertEquals("settings", intent.getStringExtra("featureParam")) assertEquals("actions.intent.OPEN_APP_FEATURE", intent.action) assertEquals("com.google.android.youtube/.MainActivity", intent.component.flattenToShortString()) assertEquals("com.google.myapp", intent.package) // Developers can choose to use returned Android Intent to launch and assess the activity. Below are examples for how it will look like for Robolectric and Espresso tests. // Please note that the below part is just a possible example of how Android tests are validating Activity functionality correctness for given Android Intent. // Robolectric example: val activity = Robolectric.buildActivity(MainActivity::class.java, intentResult.intent).create().resume().get() val title: TextView = activity.findViewById(R.id.startActivityTitle) assertEquals(title?.text?.toString(), "Launching…") }
Java
import android.content.Context; import android.content.Intent; import android.widget.TextView; import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ActivityScenario; import com.google.assistant.appactions.testing.aatl.AppActionsTestManager; import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult; import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult; import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType; import com.google.common.collect.ImmutableMap; import org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.Test; import org.robolectric.RobolectricTestRunner; ... @Test public void IntentTestExample() throws Exception { Map<String, String> intentParams = ImmutableMap.of("feature", "settings"); String intentName = "actions.intent.OPEN_APP_FEATURE"; AppActionsFulfillmentResult result = aatl.fulfill(intentName, intentParams); assertEquals(FulfillmentType.INTENT, result.getFulfillmentType()); AppActionsFulfillmentIntentResult intentResult = (AppActionsFulfillmentIntentResult) result; Intent intent = intentResult.getIntent(); // Developer can choose to assert different relevant properties of the returned intent, such as the action, activity, package, or scheme assertEquals("settings", intent.getStringExtra("featureParam")); assertEquals("actions.intent.OPEN_APP_FEATURE", intent.getAction()); assertEquals("com.google.android.youtube/.MainActivity", intent.getComponent().flattenToShortString()); assertEquals("com.google.myapp", intent.getPackage()); // Developers can choose to use returned Android Intent to launch and assess the activity. Below are examples for how it will look like for Robolectric and Espresso tests. // Please note that the below part is just a possible example of how Android tests are validating Activity functionality correctness for given Android Intent. // Robolectric example: MainActivity activity = Robolectric.buildActivity(MainActivity.class,intentResult.intent).create().resume().get(); TextView title: TextView = activity.findViewById(R.id.startActivityTitle) assertEquals(title?.getText()?.toString(), "Launching…") }
Espresso kullanıyorsanız AATL sonuçlarına göre Etkinliği başlatma şeklinizi değiştirmeniz gerekir. Aşağıda,
ActivityScenario
yöntemi kullanılan bir Espresso örneği verilmiştir:Kotlin
ActivityScenario.launch<MainActivity>(intentResult.intent); Espresso.onView(ViewMatchers.withId(R.id.startActivityTitle)) .check(ViewAssertions.matches(ViewMatchers.withText("Launching…")))
Java
ActivityScenario.launch<MainActivity>(intentResult.intent); Espresso.onView(ViewMatchers.withId(R.id.startActivityTitle)) .check(ViewAssertions.matches(ViewMatchers.withText("Launching…")))
Parametre eşlemelerindeki ad ve anahtar özelliklerinin BII'deki parametrelerle eşleşmesini sağlayın. Örneğin
order.orderedItem.name
,GET_ORDER
içindeki parametreyle ilgili dokümanlarla eşleşir.API örneğini Android Bağlam parametresiyle örneklendirme (
ApplicationProvider
veyaInstrumentationRegistry
üzerinden alınır):- Tek modüllü uygulama mimarisi:
Kotlin
private lateinit var aatl: AppActionsTestManager @Before fun init() { val appContext = ApplicationProvider.getApplicationContext() aatl = AppActionsTestManager(appContext) }
Java
private AppActionsTestManager aatl; @Before public void init() { Context appContext = ApplicationProvider.getApplicationContext(); aatl = new AppActionsTestManager(appContext); }
- Çok modüllü uygulama mimarisi:
Kotlin
private lateinit var aatl: AppActionsTestManager @Before fun init() { val appContext = ApplicationProvider.getApplicationContext() val lookupPackages = listOf("com.myapp.mainapp", "com.myapp.resources") aatl = AppActionsTestManager(appContext, lookupPackages) }
Java
private AppActionsTestManager aatl; @Before public void init() throws Exception { Context appContext = ApplicationProvider.getApplicationContext(); List<String> lookupPackages = Arrays.asList("com.myapp.mainapp","com.myapp.resources"); aatl = new AppActionsTestManager(appContext, Optional.of(lookupPackages)); }
API'nin
fulfill
yöntemini yürütün veAppActionsFulfillmentResult
nesnesini alın.
Onaylama işlemleri gerçekleştirme
Uygulama İşlemleri Test Kitaplığı'nı doğrulamak için önerilen yöntem:
AppActionsFulfillmentResult
sipariş karşılama türünü belirtin. Beklenmeyen BII istekleri durumunda uygulamanın nasıl davrandığını test etmek içinFulfillmentType.INTENT
veyaFulfillmentType.UNFULFILLED
olmalıdır.- İki farklı sipariş karşılama türü vardır:
INTENT
veDEEPLINK
sipariş karşılama.- Normalde geliştirici, kitaplığı tetikleyerek yerine getirdiği
shortcuts.xml
intent etiketine bakarakINTENT
veDEEPLINK
istek karşılamalarını ayırt edebilir. - Niyet etiketi altında bir URL şablonu etiketi varsa bu,
DEEPLINK
öğesinin bu amacı yerine getirdiğini gösterir. - Sonuç amacının
getData()
yöntemi null olmayan bir nesne döndürürse bu,DEEPLINK
karşılamayı da gösterir. Benzer şekilde,getData
null
değerini döndürürse bu, bunun birINTENT
karşılama olduğu anlamına gelir.
- Normalde geliştirici, kitaplığı tetikleyerek yerine getirdiği
INTENT
durumunda,AppActionsFulfillmentResult
türünüAppActionsIntentFulfillmentResult
'e yazın,getIntent
yöntemini çağırarak Android Intent'i getirin ve aşağıdakilerden birini yapın:- Android Intent'in bağımsız alanları üzerinde hak iddia edin.
- intent.getData.getHost yöntemiyle erişilen bir amacın URI'sini talep edin.
DEEPLINK
destek kaydı içinAppActionsFulfillmentResult
türünüAppActionsIntentFulfillmentResult
adresine yazın (yukarıdakiINTENT
senaryosuyla aynı şekilde),getIntent
yöntemini çağırarak Android Intent'i getirin ve derin bağlantı URL'sini (intent.getData.getHost
üzerinden erişildi) onaylayın.- Hem
INTENT
hem deDEEPLINK
için, sonuçta elde edilen amacı kullanarak etkinliği seçilen Android test çerçevesiyle başlatabilirsiniz.
Uluslararası hale getirme
Uygulamanızda birden fazla yerel ayar varsa testleri, belirli bir yerel ayarda test altında çalıştırılacak şekilde yapılandırabilirsiniz. Alternatif olarak, yerel ayarı doğrudan değiştirebilirsiniz:
Kotlin
import android.content.res.Configuration import java.util.Locale ... val newLocale = Locale("es") val conf = context.resources.configuration conf = Configuration(conf) conf.setLocale(newLocale)
Java
Locale newLocale = new Locale("es"); Configuration conf = context.getResources().getConfiguration(); conf = new Configuration(conf); conf.setLocale(newLocale);
Burada, İspanyolca (ES) yerel ayarı için yapılandırılmış bir AATL testi örneği verilmiştir:
Kotlin
import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertEquals import android.content.Context import android.content.res.Configuration import androidx.test.platform.app.InstrumentationRegistry import com.google.assistant.appactions.testing.aatl.AppActionsTestManager import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentIntentResult import com.google.assistant.appactions.testing.aatl.fulfillment.AppActionsFulfillmentResult import com.google.assistant.appactions.testing.aatl.fulfillment.FulfillmentType import com.google.common.collect.ImmutableMap import java.util.Locale import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class ShortcutForDifferentLocaleTest { @Before fun setUp() { val context = InstrumentationRegistry.getInstrumentation().getContext() // change the device locale to 'es' val newLocale = Locale("es") val conf = context.resources.configuration conf = Configuration(conf) conf.setLocale(newLocale) val localizedContext = context.createConfigurationContext(conf) } @Test fun shortcutForDifferentLocale_succeeds() { val aatl = AppActionsTestManager(localizedContext) val intentName = "actions.intent.ORDER_MENU_ITEM" val intentParams = ImmutableMap.of("menuItem.name", "hamburguesa con queso") val result = aatl.fulfill(intentName, intentParams) assertThat(result.getFulfillmentType()).isEqualTo(FulfillmentType.INTENT) val intentResult = result as AppActionsFulfillmentIntentResult assertThat(intentResult.getIntent().getData().toString()) .isEqualTo("myfoodapp://browse?food=food_hamburger") } }
Java
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.ORDER_MENU_ITEM"; ImmutableMap<String, String> intentParams = ImmutableMap.of("menuItem.name", "hamburguesa con queso"); AppActionsFulfillmentResult result = aatl.fulfill(intentName, intentParams); assertThat(result.getFulfillmentType()).isEqualTo(FulfillmentType.INTENT); AppActionsFulfillmentIntentResult intentResult = (AppActionsFulfillmentIntentResult) result; assertThat(intentResult.getIntent().getData().toString()) .isEqualTo("myfoodapp://browse?food=food_hamburger"); }
Sorunu giderin
Entegrasyon testiniz beklenmedik bir şekilde başarısız olursa uyarı veya hata düzeyi mesajı almak için Android Studio logcat penceresinde AATL günlük mesajlarını arayabilirsiniz. Kitaplıktan daha fazla çıkış yakalamak için günlük kaydı düzeyini de artırabilirsiniz.
Sınırlamalar
Uygulama İşlemleri Test Kitaplığı'nın mevcut sınırlamaları şunlardır :
- AATL, Doğal Dil Anlama (NLU) veya Sesle Yazma (STT) özelliklerini test etmez.
- Testler, varsayılan uygulama modülünün dışındaki modüllerde olduğunda AATL çalışmaz.
- AATL yalnızca Android 7.0 "Nougat" (API düzeyi 24) ve daha yeni sürümlerle uyumludur.