Uygulama İşlemleri test kitaplığı (AATL), geliştiricilerin normalde gerçek sesli sorgular veya Uygulama İşlemleri test aracı kullanılarak yapılacak testleri otomatikleştirerek uygulama işleminin yerine getirilmesini programatik olarak test etmelerini sağlayan özellikler sunar.
Kitaplık, shortcut.xml
yapılandırmasının doğru olmasını ve açıklanan Android intent çağrısının başarılı olmasını sağlar. Uygulama İşlemleri Test Kitaplığı
uygulamanızın, belirli Google
Asistan amacını ve parametrelerini Android derin bağlantısına dönüştürerek veya
Android'i örneklendirmek için iddia edilebilen ve kullanılabilecek Android niyeti
etkinliği'ne dokunun.
Test, Android ortamında Robolectric birim veya araçla test şeklinde gerçekleştirilir. Bu, geliştiricilerin kullandıkları her bir gerçek uygulama davranışını taklit ederek. BII'leri, özel intent'leri veya derin bağlantı yerine getirmeyi test etmek için herhangi bir enstrümante test çerçevesi (UI Automator, Espresso, JUnit4, Appium, Detox, Calabash) kullanılabilir.
Uygulama çok dilliyse geliştiriciler, uygulamanın işlevinin farklı yerel ayarlarda doğru şekilde çalıştığını doğrulayabilir.
İşleyiş şekli
Geliştiricilerin, uygulamanın test ortamına App Actions Test Kitaplığı'nı entegre edebilmesi için uygulamanın app
modülünde yeni Robolectric veya enstrümante edilmiş testler oluşturması ya da mevcut testleri güncellemesi gerekir.
Test kodu aşağıdaki bölümleri içerir:
- Ortak kurulum yönteminde veya ayrı test durumlarında kitaplık örneğinin başlatılması.
- Her test, intent oluşturma sonucunu üretmek için kitaplık örneğinin
fulfill
yöntemini çağırır. - Geliştirici daha sonra derin bağlantıyı belirtir veya uygulama yerine getirme işlemini tetikler ve uygulama durumunda özel doğrulama yapar.
Kurulum gereksinimleri
Test kitaplığını kullanmak için testleri uygulamanıza eklemeden önce bazı başlangıç uygulama yapılandırmaları yapmanız gerekir.
Yapılandırma
Uygulama İşlemleri Test Kitaplığı'nı kullanmak için uygulamanızın aşağıdaki şekilde yapılandırıldığından emin olun:
- Android Gradle Eklentisi'ni (AGP) yükleme
app
modülündekires/xml
klasörüne birshortcuts.xml
dosyası ekleyin.AndroidManifest.xml
öğesinin<meta-data android:name="android.app.shortcuts" android:resource=”@xml/shortcuts” />
içerdiğinden emin olun şunlardan birinin altında:<application>
etiketi- başlatıcı
<activity>
etiketi
<capability>
öğesini<shortcuts>
öğesinin içine yerleştirin:shortcuts.xml
Uygulama İşlemleri Test Kitaplığı bağımlılıkları ekleme
Google deposunu şuradaki proje depoları listesine ekleyin:
settings.gradle
: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. Robolectric testleriniapp/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.
ActivityScenario
yöntemini kullanan Espresso örneğini aşağıda bulabilirsiniz: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 parametrelerini değiştirebilirsiniz. Örneğin,
exercisePlan.forExercise.name
,GET_EXERCISE_PLAN
parametresinin dokümanıyla eşleşir.Android Bağlam parametresiyle (alınan kaynak:
ApplicationProvider
veyaInstrumentationRegistry
):- 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
nesne algılandı.
İddialarda bulunma
Uygulama İşlemleri Test Kitaplığı'nı doğrulamak için önerilen yöntem şu şekildedir:
AppActionsFulfillmentResult
sipariş karşılama türünü belirtin. Yapması gerekenlerFulfillmentType.INTENT
veyaFulfillmentType.UNFULFILLED
olması beklenmedik BII istekleri durumunda uygulamanın nasıl davrandığını test etmek için kullanılır.- 2 tür istek karşılama vardır:
INTENT
veDEEPLINK
istek karşılamaları.- Normalde geliştirici, kitaplığı tetikleyerek yerine getirdiği
shortcuts.xml
'deki intent etiketine bakarakINTENT
veDEEPLINK
yerine getirmeleri arasında ayrım yapabilir. - Niyet etiketinin altında bir url şablonu etiketi varsa bu durum
DEEPLINK
, bu amacı gerçekleştiriyor. - Sonuç amacının
getData()
yöntemi boş olmayan bir nesne döndürüyorsa bu,DEEPLINK
yerine getirildiğini de gösterir. Benzer şekilde,getData
null
değerini döndürürseINTENT
sipariş karşılama olduğu anlamına gelir.
- Normalde geliştirici, kitaplığı tetikleyerek yerine getirdiği
INTENT
durumu içinAppActionsFulfillmentResult
'uAppActionsIntentFulfillmentResult
olarak türüne dönüştürün,getIntent
yöntemini çağırarak Android Intent'i alın ve aşağıdakilerden birini yapın:- Android Intent'in bağımsız alanlarını iddia edin.
- Üzerinden erişilen bir intent'in URI'sını iddia edin intent.getData.getHost yöntemini kullanarak devam edin.
DEEPLINK
destek kaydı içinAppActionsFulfillmentResult
yazıp şu değere yazın:AppActionsIntentFulfillmentResult
(INTENT
senaryosuyla aynı) yukarıda belirtilen şekilde)getIntent
yöntemini çağırarak Android Intent'i getirin ve derin bağlantı URL'sini (intent.getData.getHost
üzerinden erişilir).- Hem
INTENT
hem deDEEPLINK
için, elde edilen niyeti kullanarak lansman yapabilirsiniz. bu etkinliği, seçilen Android test çerçevesiyle oluşturuyoruz.
Uluslararası hale getirme
Uygulamanızın birden fazla yerel ayarı varsa testleri belirli bir uygulamayı çalıştıracak şekilde yapılandırabilirsiniz. yerel ayar altında test ediliyor. 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);
İspanyolca (ES) yerel ayarı için yapılandırılmış bir AATL testi örneği aşağıda 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.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") } }
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.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"); }
Sorunu giderin
Entegrasyon testiniz beklenmedik bir şekilde başarısız olursa uyarı veya hata düzeyi mesajını 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 kaydetme düzeyini de artırabilirsiniz.
Sınırlamalar
Uygulama İşlemleri Test Kitaplığı'ndaki mevcut sınırlamalar şunlardır :
- AATL, doğal dil anlama (NLU) veya konuşma metne dönüştürme (STT) özelliklerini test etmez.
- Testler varsayılan uygulamanın dışındaki modüllerde olduğunda AATL çalışmaz modülünü kullanabilirsiniz.
- AATL yalnızca Android 7.0 "Nougat" (API düzeyi 24) ve sonraki sürümlerle uyumludur.