根據預設,Android Studio 會在 src/androidTest/java/ 中提供原始碼目錄,用於放置檢測設備和 UI 測試。詳情請參閱「測試類型和位置」一文。
如要測試應用程式是否顯示「投放」圖示,請按照下列步驟操作:
packagecom.example.package;importorg.junit.Rule;importorg.junit.Test;importorg.junit.runner.RunWith;importandroidx.mediarouter.app.MediaRouteButton;importandroidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;importandroidx.test.rule.ActivityTestRule;import staticandroidx.test.espresso.Espresso.onView;import staticandroidx.test.espresso.assertion.ViewAssertions.matches;import staticandroidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;import staticandroidx.test.espresso.matcher.ViewMatchers.isDisplayed;@RunWith(AndroidJUnit4ClassRunner.class)publicclassMyCastUITest{@RulepublicActivityTestRule<MainActivity>mActivityRule=newActivityTestRule<>(MainActivity.class);@TestpublicvoidtestCastButtonDisplay()throwsInterruptedException{// wait for Cast buttonThread.sleep(2000);onView(isAssignableFrom(MediaRouteButton.class)).check(matches(isDisplayed()));}}
測試投放連線
本例說明如何模擬使用者連線至投放裝置的動作:
importandroidx.test.platform.app.InstrumentationRegistry;importandroidx.test.uiautomator.UiDevice;importandroidx.test.uiautomator.UiObjectNotFoundException;importandroidx.test.uiautomator.UiSelector;import staticandroidx.test.espresso.action.ViewActions.click;import staticandroidx.test.espresso.matcher.ViewMatchers.withId;@RunWith(AndroidJUnit4ClassRunner.class)publicclassMyCastUITest{@RulepublicActivityTestRule<MainActivity>mActivityRule=newActivityTestRule<>(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 */@TestpublicvoidtestConnectToCastDevice()throwsInterruptedException,UiObjectNotFoundException{// wait for Cast button readyThread.sleep(2000);// click on Cast icon and show a dialogonView(isAssignableFrom(MediaRouteButton.class)).perform(click());onView(withId(R.id.action_bar_root)).check(matches(isDisplayed()));// select target Cast device to connectUiDevicemDevice=UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());mDevice.findObject(newUiSelector().text(TARGET_DEVICE)).click();// assert the Cast state is connectedassertCastStateIsConnected(MAX_TIMEOUT_MS);}}
您可以在應用程式的主要執行緒上執行呼叫,藉此擷取 Cast 工作階段和連線狀態:
importandroid.content.Context;importandroid.os.SystemClock;importcom.google.android.gms.cast.framework.CastContext;importcom.google.android.gms.cast.framework.CastSession;importcom.google.android.gms.cast.framework.SessionManager;import staticorg.junit.Assert.assertTrue;@RunWith(AndroidJUnit4ClassRunner.class)publicclassMyCastUITest{privateCastContextmCastContext;privateCastSessionmCastSession;privateSessionManagermSessionManager;privatebooleanisCastConnected;@RulepublicActivityTestRule<MainActivity>mActivityRule=newActivityTestRule<>(MainActivity.class);/** * Connecting to Cast device */@TestpublicvoidtestConnectToCastDevice()throwsInterruptedException,UiObjectNotFoundException{......// assert the Cast state is connectedassertCastStateIsConnected(MAX_TIMEOUT_MS);}/** * Check connection status from Cast session */privatevoidassertCastStateIsConnected(longtimeout)throwsInterruptedException{longstartTime=SystemClock.uptimeMillis();isCastConnected=false;while(!isCastConnected && SystemClock.uptimeMillis()-startTime < timeout){Thread.sleep(500);// get cast instance and cast session from the app's main threadInstrumentationRegistry.getInstrumentation().runOnMainSync(newRunnable(){@Overridepublicvoidrun(){ContextmTargetContext=InstrumentationRegistry.getInstrumentation().getTargetContext();mCastContext=CastContext.getSharedInstance(mTargetContext);mSessionManager=mCastContext.getSessionManager();mCastSession=mSessionManager.getCurrentCastSession();isCastConnected=mCastSession.isConnected();}});}assertTrue(isCastConnected);}}
[null,null,["上次更新時間:2025-08-31 (世界標準時間)。"],[[["\u003cp\u003eAndroid sender apps should be tested for UI compliance with Cast UX Guidelines and Design Checklist.\u003c/p\u003e\n"],["\u003cp\u003eUI Automator and Espresso frameworks are recommended for simulating user interactions and automated UI testing.\u003c/p\u003e\n"],["\u003cp\u003eAndroid Studio facilitates building, running tests, and provides a dedicated directory (\u003ccode\u003esrc/androidTest/java/\u003c/code\u003e) for instrumented and UI tests.\u003c/p\u003e\n"],["\u003cp\u003eSample Cast test cases are available in the CastVideos-android repository on GitHub for reference.\u003c/p\u003e\n"],["\u003cp\u003eThe UI Automator framework necessitates Android 4.3 (API level 18) or higher for compatibility.\u003c/p\u003e\n"]]],["To test Cast functionality in Android apps, developers should use UI Automator and Espresso frameworks for automated, repeatable UI tests. Ensure compliance with Cast UX guidelines. Set up testing in Android Studio, disabling system animations on the test device. Use `src/androidTest/java/` for test code. Key actions include checking for the Cast icon's visibility, simulating connection to a Cast device, and verifying the Cast state using `CastContext` and `CastSession` through the app's main thread.\n"],null,["# Automate Android Sender UI Tests\n\nTesting your app is a necessary part of the Cast development process. Your app\nshould comply with the [Cast UX\nGuidelines](https://developers.google.com/cast/docs/ux_guidelines) and [Design\nChecklist](https://developers.google.com/cast/docs/design_checklist/) to ensure\nusers have a consistent Cast experience.\n\nFor Android apps, leverage the [UI\nAutomator](https://developer.android.com/training/testing/ui-automator) and\n[Espresso](https://developer.android.com/training/testing/espresso/) testing\nframeworks to simulate user interactions on your app and run your UI tests in an\nautomated and repeatable way. To learn more about automated UI tests, see\n[Automate user interface\ntests](https://developer.android.com/training/testing/ui-testing).\n\nThis guide describes how to add automated UI tests to your Android sender app.\n| **Note:** The sample Cast test cases are also available in the GitHub [CastVideos-android](https://github.com/googlecast/CastVideos-android#automated-ui-testing-on-cast-sender-app) sample app.\n\nSet up the test environment\n---------------------------\n\n[Android Studio](https://developer.android.com/studio/index.html) is recommended\nfor building and running your app and tests.\n\nOn the physical device used for testing, under **Settings \\\u003e Developer options**,\nturn off the following system animations:\n\n- Window animation scale\n- Transition animation scale\n- Animator duration scale\n\n### Example Gradle build file\n\n apply plugin: 'com.android.application'\n\n android {\n compileSdkVersion 34\n\n defaultConfig {\n applicationId \"com.example.package\"\n minSdkVersion 23\n targetSdkVersion 34\n testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n }\n }\n\n dependencies {\n ...\n\n testImplementation 'junit:junit:4.12'\n androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'\n androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'\n androidTestImplementation 'androidx.test:runner:1.1.1'\n androidTestImplementation 'androidx.test:rules:1.1.1'\n }\n\n| **Note:** The UI Automator framework requires **Android 4.3 (API level 18)** or higher.\n\nAdd the first Cast UI test\n--------------------------\n\nBy default, Android Studio provides a source code directory at\n`src/androidTest/java/` to place your instrumented and UI tests. For more\ninformation, see [Test types and\nlocation](https://developer.android.com/studio/test#test_types_and_location).\n\nTo test if a Cast icon is displayed on the app: \n\n package com.example.package;\n\n import org.junit.Rule;\n import org.junit.Test;\n import org.junit.runner.RunWith;\n\n import androidx.mediarouter.app.MediaRouteButton;\n import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;\n import androidx.test.rule.ActivityTestRule;\n\n import static androidx.test.espresso.Espresso.onView;\n import static androidx.test.espresso.assertion.ViewAssertions.matches;\n import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;\n import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;\n\n @RunWith(AndroidJUnit4ClassRunner.class)\n public class MyCastUITest {\n\n @Rule\n public ActivityTestRule\u003cMainActivity\u003e mActivityRule =\n new ActivityTestRule\u003c\u003e(MainActivity.class);\n\n @Test\n public void testCastButtonDisplay() throws InterruptedException {\n // wait for Cast button\n Thread.sleep(2000);\n\n onView(isAssignableFrom(MediaRouteButton.class)).check(matches(isDisplayed()));\n }\n }\n\nTest Cast connection\n--------------------\n\nThis example shows how to simulate user actions connecting to a Cast device: \n\n import androidx.test.platform.app.InstrumentationRegistry;\n import androidx.test.uiautomator.UiDevice;\n import androidx.test.uiautomator.UiObjectNotFoundException;\n import androidx.test.uiautomator.UiSelector;\n\n import static androidx.test.espresso.action.ViewActions.click;\n import static androidx.test.espresso.matcher.ViewMatchers.withId;\n\n @RunWith(AndroidJUnit4ClassRunner.class)\n public class MyCastUITest {\n\n @Rule\n public ActivityTestRule\u003cMainActivity\u003e mActivityRule =\n new ActivityTestRule\u003c\u003e(MainActivity.class);\n\n /**\n * Connecting to Cast device\n * - Open Cast menu dialog when tapping the Cast icon\n * - Select target Cast device and connect\n * - Assert the Cast state is connected\n */\n @Test\n public void testConnectToCastDevice()\n throws InterruptedException, UiObjectNotFoundException {\n\n // wait for Cast button ready\n Thread.sleep(2000);\n\n // click on Cast icon and show a dialog\n onView(isAssignableFrom(MediaRouteButton.class))\n .perform(click());\n onView(withId(R.id.action_bar_root))\n .check(matches(isDisplayed()));\n\n // select target Cast device to connect\n UiDevice mDevice = UiDevice.getInstance(\n InstrumentationRegistry.getInstrumentation());\n mDevice.findObject(new UiSelector().text(TARGET_DEVICE)).click();\n\n // assert the Cast state is connected\n assertCastStateIsConnected(MAX_TIMEOUT_MS);\n }\n }\n\nThe Cast session and connection state can be retrieved by executing a call on\nthe application's main thread: \n\n import android.content.Context;\n import android.os.SystemClock;\n\n import com.google.android.gms.cast.framework.CastContext;\n import com.google.android.gms.cast.framework.CastSession;\n import com.google.android.gms.cast.framework.SessionManager;\n\n import static org.junit.Assert.assertTrue;\n\n @RunWith(AndroidJUnit4ClassRunner.class)\n public class MyCastUITest {\n private CastContext mCastContext;\n private CastSession mCastSession;\n private SessionManager mSessionManager;\n private boolean isCastConnected;\n\n @Rule\n public ActivityTestRule\u003cMainActivity\u003e mActivityRule =\n new ActivityTestRule\u003c\u003e(MainActivity.class);\n\n /**\n * Connecting to Cast device\n */\n @Test\n public void testConnectToCastDevice()\n throws InterruptedException, UiObjectNotFoundException {\n ......\n\n // assert the Cast state is connected\n assertCastStateIsConnected(MAX_TIMEOUT_MS);\n }\n\n /**\n * Check connection status from Cast session\n */\n private void assertCastStateIsConnected(long timeout)\n throws InterruptedException {\n\n long startTime = SystemClock.uptimeMillis();\n isCastConnected = false;\n\n while (!isCastConnected && SystemClock.uptimeMillis() - startTime \u003c timeout) {\n\n Thread.sleep(500);\n\n // get cast instance and cast session from the app's main thread\n InstrumentationRegistry.getInstrumentation().runOnMainSync(\n new Runnable() {\n @Override\n public void run() {\n Context mTargetContext =\n InstrumentationRegistry.getInstrumentation().getTargetContext();\n mCastContext =\n CastContext.getSharedInstance(mTargetContext);\n mSessionManager = mCastContext.getSessionManager();\n mCastSession =\n mSessionManager.getCurrentCastSession();\n isCastConnected = mCastSession.isConnected();\n }\n }\n );\n }\n\n assertTrue(isCastConnected);\n }\n }"]]