Tự động kiểm thử giao diện người dùng cho Trình gửi Android

Kiểm thử ứng dụng là một phần cần thiết trong quá trình phát triển Cast. Ứng dụng của bạn phải tuân thủ Nguyên tắc về trải nghiệm người dùng của tính năng TruyềnDanh sách kiểm tra thiết kế để đảm bảo người dùng có được trải nghiệm nhất quán khi sử dụng tính năng Truyền.

Đối với ứng dụng Android, hãy tận dụng các khung kiểm thử UI AutomatorEspresso để mô phỏng các hoạt động tương tác của người dùng trên ứng dụng, đồng thời chạy các quy trình kiểm thử giao diện người dùng theo cách tự động và lặp lại. Để tìm hiểu thêm về các quy trình kiểm thử giao diện người dùng tự động, hãy xem phần Tự động hoá việc kiểm thử giao diện người dùng.

Hướng dẫn này mô tả cách thêm bài kiểm thử giao diện người dùng tự động vào ứng dụng dành cho người gửi Android.

Thiết lập môi trường kiểm thử

Bạn nên sử dụng Android Studio để tạo và chạy ứng dụng cũng như các bài kiểm thử.

Trên thiết bị thực dùng để kiểm thử, trong phần Settings > Developer options (Cài đặt > Tuỳ chọn cho nhà phát triển), hãy tắt các ảnh động hệ thống sau đây:

  • Tỷ lệ hình động của cửa sổ
  • Tỷ lệ hình động chuyển tiếp
  • Tỷ lệ thời lượng của trình tạo hình động

Ví dụ về tệp bản dựng 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'
}

Thêm chương trình kiểm thử giao diện người dùng truyền đầu tiên

Theo mặc định, Android Studio cung cấp một thư mục mã nguồn tại src/androidTest/java/ để đặt các hoạt động kiểm thử được đo lường và giao diện người dùng. Để biết thêm thông tin, hãy xem bài viết Loại và vị trí kiểm thử.

Cách kiểm tra xem biểu tượng Truyền có hiển thị trên ứng dụng hay không:

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

Kiểm tra kết nối Cast

Dưới đây là ví dụ minh hoạ cách mô phỏng các hành động của người dùng khi kết nối với một Thiết bị truyền:

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

Bạn có thể truy xuất phiên Truyền và trạng thái kết nối bằng cách thực thi lệnh gọi trên luồng chính của ứng dụng:

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