Skip to content

Instantly share code, notes, and snippets.

@adavis
Last active April 7, 2022 13:58
Show Gist options
  • Save adavis/f35c12bdafbf2e20f66485235f9d423f to your computer and use it in GitHub Desktop.
Save adavis/f35c12bdafbf2e20f66485235f9d423f to your computer and use it in GitHub Desktop.
Using Screen Robots with Android Espresso Tests
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 ) ) );
}
}
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 );
}
}
}
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