Reputation: 17083
I need to tell Espresso to wait until my Activity is idle. I'm using the interface IdlingResource
to achieve this. Here's the code I'm using for testing:
public class MyActivity extends Activity implements IdlingResource {
private boolean isIdle;
ResourceCallback resourceCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
final Button myButton = (Button) findViewById(R.id.myButton);
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
myButton.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
isIdle = true;
}
}, 3000);
}
public void ButtonClicked(View view) {
Toast.makeText(MyActivity.this, "OK", Toast.LENGTH_SHORT).show();
}
@Override
public String getName() {
return getClass().getName();
}
@Override
public boolean isIdleNow() {
if(isIdle){
resourceCallback.onTransitionToIdle();
return true;
}
return false;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
}
Espresso automatically waits for an AsyncTask to finish, so if I use AnsycTask I don't even need to implement this interface. The problem is that I'm using a library to communicate to the network and it seems to not use AnsyncTasks or Espresso doesn't know that.
My problem is that the code above works fine only on my device (Motorola XT1058 or Moto X) if I run the very same test on the emulator (Genymotion) or any other device, I end up with the following exception:
junit.framework.AssertionFailedError: Exception in constructor: testA (java.lang.NoClassDefFoundError: rapnaveia.com.br.myapplication.MyActivity
at rapnaveia.com.br.myapplication.ApplicationTest.<init>(ApplicationTest.java:16)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at junit.runner.BaseTestRunner.getTest(BaseTestRunner.java:118)
at android.test.AndroidTestRunner.getTest(AndroidTestRunner.java:149)
at android.test.AndroidTestRunner.setTestClassName(AndroidTestRunner.java:57)
at android.test.suitebuilder.TestSuiteBuilder.addTestClassByName(TestSuiteBuilder.java:80)
at android.test.InstrumentationTestRunner.parseTestClass(InstrumentationTestRunner.java:443)
at android.test.InstrumentationTestRunner.parseTestClasses(InstrumentationTestRunner.java:424)
at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:370)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onCreate(GoogleInstrumentationTestRunner.java:114)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4435)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
An here the code of my test class:
public class ApplicationTest extends ActivityInstrumentationTestCase2<MyActivity> {
public ApplicationTest() {
super(MyActivity.class);
}
public void testA(){
Espresso.registerIdlingResources(getActivity());
Espresso.onView(withId(R.id.myButton)).perform(click());
}
}
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "rapnaveia.com.br.myapplication"
minSdkVersion 15
targetSdkVersion 20
versionCode 1
versionName "1.0"
testApplicationId 'br.com.rapnaveia'
testInstrumentationRunner 'com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner'
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile files('libs/espresso-1.1-bundled.jar')
}
Upvotes: 4
Views: 834
Reputation: 913
The problem is in the gradle configuration. Your project is trying to compile the espresso jar twice.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile files('libs/espresso-1.1-bundled.jar')
}
With this configuration, the espresso jar is compiled both by your main project and your test project. So, when you try to execute the test, the main project fails to build properly, causing the error (And I think weird that you could run the test in your device).
To run your tests, all you have to do is remove the compile instruction from the dependency of your test target.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
The android test project will use the espresso jar compiled in the main project, since that the main project is "compiled" into the test project.
Upvotes: 4