Anton Kizema
Anton Kizema

Reputation: 1092

Android Espresso wrong set up, or work not stable?

I have been implementing android espresso test for a week. What is the real thing - is implementing server call and wait for it with espresso. This is called Idle Resource call, and we have to follow rules, which are pretty straight forward. Actually I found solution, but the result is shocking - I am succeed only if I do comment lines

Espresso.onView(ViewMatchers.withId(R.id.email)).perform(ViewActions.typeText("some shit"));
Espresso.onView(ViewMatchers.withId(R.id.password)).perform(ViewActions.typeText("123"));

and replacing them with "huck":

final EditText email = (EditText) act.findViewById(R.id.email);
        final EditText password = (EditText) act.findViewById(R.id.password);
        getInstrumentation().runOnMainSync(new Runnable() {
            public void run() {
                email.setText("Engineer");
                password.setText("2342");
            }
        });

..before clicking on button that launch new activity after emulated call to the server. This are my whole files: build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "shoppinglist.kizema.anton.testappespresso"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    packagingOptions {
        exclude 'LICENSE.txt'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/DEPENDENCIES'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'

    // App's dependencies, including test
    compile 'com.android.support:support-annotations:21.0.3'

    // Testing-only dependencies
    androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
}

LoginActivity (First activity):

//set up initial listener
private void initLoginHelper(){
    loginHelper = new Server() {
        @Override
        public void login(String email, String code, String phone, String password, boolean loginByPhoneNumber) {
            //ask server
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //done
            Intent intent = new Intent(LoginActivity.this, SecondActivity.class);
            startActivityForResult(intent, 0);
        }
    };
}

//onButtonClick handler
public void btnLogInSuka(View v) {
    performLogin();
}
void performLogin() {
    new Thread(new Runnable() {
        @Override
        public void run() {
                loginHelper.login(emailParam,codeParam,phoneParam,passwordParam,false);
        }
    }).start();
}

And AplicationTest.java (espresso tests): @LargeTest public class ApplicationTest extends ActivityInstrumentationTestCase2 {

public ApplicationTest() {
    super(LoginActivity.class);
}

CountingIdlingResource idleRes;

@Override
public void setUp() throws Exception {
    super.setUp();
    getActivity();

    idleRes = new CountingIdlingResource("server");
    Espresso.registerIdlingResources(idleRes);
}

public void testSample(){
    final LoginActivity act = (LoginActivity) getCurrentActivity();
    Server aHelper = act.getUserHelper();

    MyUserHelperExternalIdleRes helper2 = new MyUserHelperExternalIdleRes(idleRes, aHelper);
    act.setUserHelper(helper2);


    //if comment this and uncomment next two lines we receive PerformException
    final EditText email = (EditText) act.findViewById(R.id.email);
    final EditText password = (EditText) act.findViewById(R.id.password);
    getInstrumentation().runOnMainSync(new Runnable() {
        public void run() {
            email.setText("Engineer");
            password.setText("2342");
        }
    });

//        Espresso.onView(ViewMatchers.withId(R.id.email)).perform(ViewActions.typeText("some shit"));
//        Espresso.onView(ViewMatchers.withId(R.id.password)).perform(ViewActions.typeText("123"));

    Espresso.closeSoftKeyboard();
    Espresso.onView(ViewMatchers.withId(R.id.btnLogIn)).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));

    Espresso.onView(ViewMatchers.withId(R.id.btnLogIn)).perform(ViewActions.click());
    Espresso.onView(ViewMatchers.withId(R.id.secondActivityOpened)).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
    Espresso.pressBack();

    Espresso.closeSoftKeyboard();
    Espresso.onView(ViewMatchers.withId(R.id.btnLogIn)).perform(ViewActions.click());
}

Activity getCurrentActivity() {
    getInstrumentation().waitForIdleSync();
    final Activity[] activity = new Activity[1];
    try {
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                java.util.Collection<Activity> activites = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
                activity[0] = Iterables.getOnlyElement(activites);
            }});
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    return activity[0];
}

class MyUserHelperExternalIdleRes implements Server {
    private Server aHelper;
    private CountingIdlingResource udleRes;

    public MyUserHelperExternalIdleRes(CountingIdlingResource udleRes, Server aHelper) {
        this.aHelper = aHelper;
        this.udleRes = udleRes;
    }

    @Override
    public void login(String email, String code, String phone, String password, boolean loginByPhoneNumber) {

        udleRes.increment();
        try {
            aHelper.login(email,code, phone,password,loginByPhoneNumber);
        } finally {
            udleRes.decrement();
        }
    }
}

}

So, if we do actually basic espresso operation: Espresso.onView(ViewMatchers.withId(R.id.password)).perform(ViewActions.typeText ("123"));

We receive PerformException : can not find button by id. If we do a huck, (with setting Runnable on UI thread) we are succeed with this simple demo. In my main app there are other bugs with espresso (the "huck" written above did not work, we receive the same mistake). For sure I am having some very tricky mistake, I suppose something with project(espresso ) settings is wrong - I am too bad with gradle. Please help me with this, ore provide a link to android studio sample app with espresso tests (I found none, all apps are badly configured (no gradle), and after import them to android studio, I can not launch them with

gradlew connectedAndroidTest

Upvotes: 3

Views: 1598

Answers (1)

H_DANILO
H_DANILO

Reputation: 321

I'm having the same issue, and I think the main problem is that, the button, opens a new Indent, but seems that this alone don't cause the bug, which is very strange, it only happens when you typeText on an EditText before calling the click().

P.S: I managed to work that out, seems like I had a couple of doubled dependency problems, once I solved that, the tests worked out without any problem and without the need to do any work around.

My build.gradle part of the espresso ended like this:

dependencies {
    repositories {
        mavenCentral()
    }
    // Espresso
    compile 'org.apache.commons:commons-lang3:3.1'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') {
        exclude group: 'com.google.guava'
        exclude module: 'espresso-idling-resource'
    }
    androidTestCompile('com.android.support.test:testing-support-lib:0.1') {
        exclude group: 'com.google.guava'
        exclude module: 'espresso-idling-resource'
    }
}

I also added this before dependencies:

configurations {
  androidTestCompile.exclude group: 'com.android.support'
  androidTestCompile.exclude module: 'support-v4'
  androidTestCompile.exclude module: 'appcompat-v7'
}

Upvotes: 2

Related Questions