การทดสอบ UI ผู้ส่งของ Android โดยอัตโนมัติ

การทดสอบแอปเป็นส่วนที่จำเป็นในกระบวนการพัฒนา Cast แอปของคุณ ต้องเป็นไปตาม Cast UX หลักเกณฑ์และการออกแบบ รายการตรวจสอบเพื่อให้แน่ใจว่า ผู้ใช้ได้รับประสบการณ์การแคสต์ที่สอดคล้องกัน

สำหรับแอป Android ให้ใช้ UI Automator และ การทดสอบ Espresso เพื่อจำลองการโต้ตอบของผู้ใช้ในแอป และทำการทดสอบ UI ใน อัตโนมัติและทำซ้ำได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการทดสอบ UI อัตโนมัติได้ที่ ทำให้อินเทอร์เฟซผู้ใช้เป็นแบบอัตโนมัติ การทดสอบ

คำแนะนำนี้จะอธิบายวิธีเพิ่มการทดสอบ UI อัตโนมัติลงในแอปผู้ส่ง Android

ตั้งค่าสภาพแวดล้อมการทดสอบ

ขอแนะนำ Android Studio สำหรับการสร้างและเรียกใช้แอปและการทดสอบ

ในอุปกรณ์จริงที่ใช้สำหรับการทดสอบ ในส่วนการตั้งค่า > ตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์ ปิดภาพเคลื่อนไหวของระบบต่อไปนี้

  • อัตราการเคลื่อนไหวของหน้าต่าง
  • อัตราการเคลื่อนไหวของการเปลี่ยนภาพ
  • อัตราความเร็วตามตัวสร้างภาพเคลื่อนไหว

ตัวอย่างไฟล์บิลด์ Gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 34

    defaultConfig {
        applicationId "com.example.package"
        minSdkVersion 23
        targetSdkVersion 34
        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'
}

เพิ่มการทดสอบ UI ของแคสต์ครั้งแรก

โดยค่าเริ่มต้น Android Studio จะมีไดเรกทอรีซอร์สโค้ดไว้ที่ src/androidTest/java/ เพื่อทดสอบเครื่องวัดและการทดสอบ UI สำหรับข้อมูลเพิ่มเติม โปรดดูประเภทการทดสอบและ ตำแหน่ง

วิธีทดสอบว่าไอคอน 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()));
    }
}

ทดสอบการเชื่อมต่อการแคสต์

ตัวอย่างนี้แสดงวิธีจำลองการดำเนินการของผู้ใช้ที่เชื่อมต่อกับอุปกรณ์แคสต์

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);
    }
}

คุณสามารถดูเซสชันการแคสต์และสถานะการเชื่อมต่อได้โดยเริ่มเรียกใช้ เทรดหลักของแอปพลิเคชัน:

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);
    }
}