Reputation: 1092
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
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