בדיקת האפליקציה היא חלק חיוני בתהליך הפיתוח של Cast. האפליקציה צריכה לעמוד בהנחיות בנושא חוויית המשתמש (cast) וברשימת המשימות לעיצוב כדי להבטיח שהמשתמשים ייהנו מחוויית העברה עקבית.
באפליקציות ל-Android, תוכלו להשתמש ב-frameworks של UI Automator וב-Espresso כדי לדמות את האינטראקציות של המשתמשים באפליקציה ולהריץ את הבדיקות של ממשק המשתמש באופן אוטומטי ועקבי. במאמר בדיקות אוטומטיות של ממשק משתמש תוכלו לקרוא מידע נוסף על בדיקות אוטומטיות של ממשק המשתמש.
במדריך זה מוסבר איך להוסיף בדיקות אוטומטיות של ממשק המשתמש לאפליקציית השולח ב-Android.
הגדרה של סביבת הבדיקה
Android Studio מומלץ ליצירה ולהפעלה של האפליקציה והבדיקות.
במכשיר הפיזי שמשמש לבדיקה, בקטע הגדרות > אפשרויות למפתחים, משביתים את אנימציות המערכת הבאות:
- קנה מידה לאנימציה של חלון
- קנה מידה לאנימציית מעבר
- קנה מידה למשך זמן אנימציה
דוגמה לקובץ build של Gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.package"
minSdkVersion 21
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
...
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test:rules:1.1.1'
}
הוספת הבדיקה הראשונה של ממשק Cast
כברירת מחדל, ב-Android Studio יש ספרייה של קוד מקור ב-src/androidTest/java/
, שבה ניתן למקם את הבדיקות של המכשירים ושל ממשק המשתמש. מידע נוסף זמין במאמר סוגי בדיקות ומיקום.
כדי לבדוק אם סמל ההעברה (cast) מוצג באפליקציה:
package com.example.package;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.mediarouter.app.MediaRouteButton;
import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
import androidx.test.rule.ActivityTestRule;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
@RunWith(AndroidJUnit4ClassRunner.class)
public class MyCastUITest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule =
new ActivityTestRule<>(MainActivity.class);
@Test
public void testCastButtonDisplay() throws InterruptedException {
// wait for Cast button
Thread.sleep(2000);
onView(isAssignableFrom(MediaRouteButton.class)).check(matches(isDisplayed()));
}
}
בדיקת החיבור של Cast
בדוגמה הזו מוסבר איך לדמות פעולות של משתמשים שמתחברים למכשיר Cast:
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
@RunWith(AndroidJUnit4ClassRunner.class)
public class MyCastUITest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule =
new ActivityTestRule<>(MainActivity.class);
/**
* Connecting to Cast device
* - Open Cast menu dialog when tapping the Cast icon
* - Select target Cast device and connect
* - Assert the Cast state is connected
*/
@Test
public void testConnectToCastDevice()
throws InterruptedException, UiObjectNotFoundException {
// wait for Cast button ready
Thread.sleep(2000);
// click on Cast icon and show a dialog
onView(isAssignableFrom(MediaRouteButton.class))
.perform(click());
onView(withId(R.id.action_bar_root))
.check(matches(isDisplayed()));
// select target Cast device to connect
UiDevice mDevice = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation());
mDevice.findObject(new UiSelector().text(TARGET_DEVICE)).click();
// assert the Cast state is connected
assertCastStateIsConnected(MAX_TIMEOUT_MS);
}
}
אפשר לאחזר את סשן הפעלת ה-Cast ואת החיבור על ידי ביצוע קריאה ל-thread הראשי של האפליקציה:
import android.content.Context;
import android.os.SystemClock;
import com.google.android.gms.cast.framework.CastContext;
import com.google.android.gms.cast.framework.CastSession;
import com.google.android.gms.cast.framework.SessionManager;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4ClassRunner.class)
public class MyCastUITest {
private CastContext mCastContext;
private CastSession mCastSession;
private SessionManager mSessionManager;
private boolean isCastConnected;
@Rule
public ActivityTestRule<MainActivity> mActivityRule =
new ActivityTestRule<>(MainActivity.class);
/**
* Connecting to Cast device
*/
@Test
public void testConnectToCastDevice()
throws InterruptedException, UiObjectNotFoundException {
......
// assert the Cast state is connected
assertCastStateIsConnected(MAX_TIMEOUT_MS);
}
/**
* Check connection status from Cast session
*/
private void assertCastStateIsConnected(long timeout)
throws InterruptedException {
long startTime = SystemClock.uptimeMillis();
isCastConnected = false;
while (!isCastConnected && SystemClock.uptimeMillis() - startTime < timeout) {
Thread.sleep(500);
// get cast instance and cast session from the app's main thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(
new Runnable() {
@Override
public void run() {
Context mTargetContext =
InstrumentationRegistry.getInstrumentation().getTargetContext();
mCastContext =
CastContext.getSharedInstance(mTargetContext);
mSessionManager = mCastContext.getSessionManager();
mCastSession =
mSessionManager.getCurrentCastSession();
isCastConnected = mCastSession.isConnected();
}
}
);
}
assertTrue(isCastConnected);
}
}