Last active
April 7, 2022 13:58
-
-
Save adavis/f35c12bdafbf2e20f66485235f9d423f to your computer and use it in GitHub Desktop.
Using Screen Robots with Android Espresso Tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package <your_package>; | |
import android.support.test.espresso.intent.rule.IntentsTestRule; | |
import android.support.test.runner.AndroidJUnit4; | |
import android.test.suitebuilder.annotation.LargeTest; | |
import org.junit.After; | |
import org.junit.Rule; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import static android.support.test.espresso.intent.Intents.intended; | |
import static android.support.test.espresso.intent.matcher.ComponentNameMatchers.hasShortClassName; | |
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; | |
import static org.junit.Assert.assertNotNull; | |
@RunWith( AndroidJUnit4.class ) | |
@LargeTest | |
public class BeforeLoginActivityTest { | |
private static final String TEST_EMAIL = "annyce@mycompany.com"; | |
private static final String TEST_PASSWORD = "123456"; | |
private static final String PACKAGE_NAME = "my.package"; | |
@Rule | |
public IntentsTestRule<LoginActivity> activityRule = | |
new IntentsTestRule<>( LoginActivity.class ); | |
@Test | |
public void shouldProceedLoginWhenValid () { | |
onView( withId( R.id.login_username_entry ) ).perform( typeText( TEST_EMAIL ) ); | |
onView( withId( R.id.login_password_entry ) ).perform( typeText( TEST_PASSWORD ) ); | |
onView( withId( R.id.login_button ) ).perform( click() ); | |
intended( hasComponent( hasShortClassName( PACKAGE_NAME ) ) ); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package <your_package>; | |
import android.support.test.espresso.intent.rule.IntentsTestRule; | |
import android.support.test.runner.AndroidJUnit4; | |
import android.test.suitebuilder.annotation.LargeTest; | |
import org.junit.After; | |
import org.junit.Rule; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import static android.support.test.espresso.intent.Intents.intended; | |
import static android.support.test.espresso.intent.matcher.ComponentNameMatchers.hasShortClassName; | |
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; | |
import static <your_package>.ScreenRobot.withRobot; | |
import static org.junit.Assert.assertNotNull; | |
@RunWith( AndroidJUnit4.class ) | |
@LargeTest | |
public class LoginActivityTest { | |
private static final String TEST_EMAIL = "annyce@mycompany.com"; | |
private static final String TEST_PASSWORD = "123456"; | |
private static final String PACKAGE_NAME = "my.package"; | |
@Rule | |
public IntentsTestRule<LoginActivity> activityRule = | |
new IntentsTestRule<>( LoginActivity.class ); | |
@Test | |
public void shouldHaveUsernameAndPasswordHeader () { | |
withRobot( LoginScreenRobot.class ) | |
.checkAreHeadersDisplayed(); | |
} | |
@Test | |
public void shouldNotAllowLoginWhenInvalid () { | |
withRobot( LoginScreenRobot.class ) | |
.provideActivityContext( activityRule.getActivity() ) | |
.callLogin( "", "" ) | |
.checkIsInErrorState(); | |
} | |
@Test | |
public void shouldProceedLoginWhenValid () { | |
withRobot( LoginScreenRobot.class ) | |
.callLogin( TEST_EMAIL, TEST_PASSWORD ) | |
.checkIsLoggedIn(); | |
} | |
public static class LoginScreenRobot extends ScreenRobot<LoginScreenRobot> { | |
public LoginScreenRobot checkIsLoggedIn () { | |
intended( hasComponent( hasShortClassName( PACKAGE_NAME ) ) ); | |
return this; | |
} | |
public LoginScreenRobot checkIsInErrorState () { | |
return checkDialogWithTextIsDisplayed( R.string.login_error ); | |
} | |
public LoginScreenRobot checkAreHeadersDisplayed () { | |
return checkIsDisplayed( R.id.login_username_header, R.id.login_password_header ); | |
} | |
public LoginScreenRobot callLogin (String username, String password) { | |
return enterTextIntoView ( R.id.login_username_entry, username ) | |
.enterTextIntoView ( R.id.login_password_entry, password ) | |
.clickOkOnView( R.id.login_button ); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package <your_package>; | |
import android.app.Activity; | |
import android.support.annotation.IdRes; | |
import android.support.annotation.StringRes; | |
import static android.support.test.espresso.Espresso.onView; | |
import static android.support.test.espresso.action.ViewActions.click; | |
import static android.support.test.espresso.action.ViewActions.swipeLeft; | |
import static android.support.test.espresso.action.ViewActions.typeText; | |
import static android.support.test.espresso.assertion.ViewAssertions.matches; | |
import static android.support.test.espresso.matcher.RootMatchers.withDecorView; | |
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; | |
import static android.support.test.espresso.matcher.ViewMatchers.withHint; | |
import static android.support.test.espresso.matcher.ViewMatchers.withId; | |
import static android.support.test.espresso.matcher.ViewMatchers.withText; | |
import static org.hamcrest.Matchers.not; | |
@SuppressWarnings("unchecked") | |
public abstract class ScreenRobot<T extends ScreenRobot> { | |
private Activity activityContext; // Only required for some calls | |
public static <T extends ScreenRobot> T withRobot (Class<T> screenRobotClass) { | |
if ( screenRobotClass == null ) { | |
throw new IllegalArgumentException( "instance class == null" ); | |
} | |
try { | |
return screenRobotClass.newInstance(); | |
} | |
catch ( IllegalAccessException iae ) { | |
throw new RuntimeException( "IllegalAccessException", iae ); | |
} | |
catch ( InstantiationException ie ) { | |
throw new RuntimeException( "InstantiationException", ie ); | |
} | |
} | |
public T checkIsDisplayed (@IdRes int... viewIds) { | |
for ( int viewId : viewIds ) { | |
onView( withId( viewId ) ).check( matches( isDisplayed() ) ); | |
} | |
return (T) this; | |
} | |
public T checkIsHidden (@IdRes int... viewIds) { | |
for ( int viewId : viewIds ) { | |
onView( withId( viewId ) ).check( matches( not( isDisplayed() ) ) ); | |
} | |
return (T) this; | |
} | |
public T checkViewHasText (@IdRes int viewId, String expected) { | |
onView( withId( viewId ) ).check( matches( withText( expected ) ) ); | |
return (T) this; | |
} | |
public T checkViewHasText (@IdRes int viewId, @StringRes int messageResId) { | |
onView( withId( viewId ) ).check( matches( withText( messageResId ) ) ); | |
return (T) this; | |
} | |
public T checkViewHasHint (@IdRes int viewId, @StringRes int messageResId) { | |
onView( withId( viewId ) ).check( matches( withHint( messageResId ) ) ); | |
return (T) this; | |
} | |
public T clickOkOnView (@IdRes int viewId) { | |
onView( withId( viewId ) ).perform( click() ); | |
return (T) this; | |
} | |
public T enterTextIntoView (@IdRes int viewId, String text) { | |
onView( withId( viewId ) ).perform( typeText( text ) ); | |
return (T) this; | |
} | |
public T provideActivityContext (Activity activityContext) { | |
this.activityContext = activityContext; | |
return (T) this; | |
} | |
public T checkDialogWithTextIsDisplayed (@StringRes int messageResId) { | |
onView( withText( messageResId ) ) | |
.inRoot( withDecorView( not( activityContext.getWindow().getDecorView() ) ) ) | |
.check( matches( isDisplayed() ) ); | |
return (T) this; | |
} | |
public T swipeLeftOnView (@IdRes int viewId) { | |
onView( withId( viewId ) ).perform( swipeLeft() ); | |
return (T) this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment