앱 테스트는 Cast 개발 과정에서 필수적인 부분입니다. 사용자에게 일관된 Cast 환경을 제공하려면 앱이 Cast UX 가이드라인 및 디자인 체크리스트를 준수해야 합니다.
Android 앱의 경우 UI Automator 및 Espresso 테스트 프레임워크를 활용하여 앱에서 사용자 상호작용을 시뮬레이션하고 자동화되고 반복 가능한 방식으로 UI 테스트를 실행하세요. 자동화된 UI 테스트에 관해 자세히 알아보려면 사용자 인터페이스 테스트 자동화를 참고하세요.
이 가이드에서는 Android 전송자 앱에 자동 UI 테스트를 추가하는 방법을 설명합니다.
기본적으로 Android 스튜디오는 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()));}}
Cast 연결 테스트
이 예시에서는 Cast 기기에 연결하는 사용자 작업을 시뮬레이션하는 방법을 보여줍니다.
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);}}
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-05(UTC)"],[[["\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 }"]]