Automate Android Sender UI Tests

Testing your app is a necessary part of the Cast development process. Your app should comply with the Cast UX Guidelines and Design Checklist to ensure users have a consistent Cast experience.

For Android apps, leverage the UI Automator and Espresso testing frameworks to simulate user interactions on your app and run your UI tests in an automated and repeatable way. To learn more about automated UI tests, see Automate user interface tests .

This guide describes how to add automated UI tests to your Android sender app.

Set up the test environment

Android Studio is recommended for building and running your app and tests.

On the physical device used for testing, under Settings > Developer options, turn off the following system animations:

  • Window animation scale
  • Transition animation scale
  • Animator duration scale

Example Gradle build file

  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 
 ' 
 } 
 

Add the first Cast UI test

By default, Android Studio provides a source code directory at src/androidTest/java/ to place your instrumented and UI tests. For more information, see Test types and location .

To test if a Cast icon is displayed on the app:

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

Test Cast connection

This example shows how to simulate user actions connecting to a Cast device:

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

The Cast session and connection state can be retrieved by executing a call on the application's main 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 
 ); 
  
 } 
 } 
 
Create a Mobile Website
View Site in Mobile | Classic
Share by: