java 在Android Espresso测试中使用屏幕机器人

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 在Android Espresso测试中使用屏幕机器人相关的知识,希望对你有一定的参考价值。

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

以上是关于java 在Android Espresso测试中使用屏幕机器人的主要内容,如果未能解决你的问题,请参考以下文章

Android Espresso UI 测试 - 测试运行失败:仪器运行因“java.lang.IllegalAccessError”而失败

在ANDROID STUDIO环境下使用Espresso 测试框架进行UI测试

在Android Studio环境下使用ESPRESSO 测试框架进行UI测试

Android测试:Espresso 自动化测试

Android Espresso单元测试

Android Studio 2.2 Espresso Test Recorder-----解放双手,通过录制测试过程实现测试