3

I have a problem setting up Robotium tests to run on Travis without random false posivities.

Every couple of builds I get

pl.mg6.agrtt.TestActivityTests > testCanEnterTextAndPressButton[test(AVD) - 4.4.2] FAILED
    junit.framework.AssertionFailedError: EditText is not found!
    at com.robotium.solo.Waiter.waitForAndGetView(Waiter.java:540)

on all my tests.

I have created a simple project on GitHub to show the issue.
You may see how it builds on Travis. Note build #7 failed after modyfing unrelated file.

I'm suspecting this to be caused by emulator being locked or its sceeen dimmed. I could reproduce this issue on local machine by turning connected device's screen off and then running

./gradlew connectedAndroidTest

After modyfing tests I got a different error message, which is somewhat more informative, so I'm adding it just in case someone tries to find a solution:

pl.mg6.agrtt.TestActivityTests > testCanFindViewsEnterTextAndPressButton[test(AVD) - 4.4.2] FAILED
    junit.framework.AssertionFailedError: Click at (160.0, 264.0) can not be completed! (java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission)
    at com.robotium.solo.Clicker.clickOnScreen(Clicker.java:106)
MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
  • Check out these `http://stackoverflow.com/questions/22392654/getting-started-with-robotium-edittext-not-found` and `http://stackoverflow.com/questions/16683702/junit-framework-assertionfailederror-while-testing-back-button-on-android`.It might be helpful to you. – Stephen Apr 01 '14 at 10:25
  • @Stephen Thank you for pointing these cases, but they are about errors in test code, which cause tests to always fail. If you look at travis, you can see my "test" always passes, but can randomly fail (build #7). – MaciejGórski Apr 01 '14 at 11:38

3 Answers3

7

While the root cause of this problem is still unknown to me, after some investigation and with a help from Robotium's author Renas Reda I could confirm what I initially suspected that emulator indeed locks itself.

A workaround I'm using now is this code put in setUp method:

getInstrumentation().runOnMainSync(new Runnable() {
    @Override
    public void run() {
        getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
    }
});
Community
  • 1
  • 1
MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
  • In the [Android documentation](http://developer.android.com/tools/testing/activity_testing.html#UnlockDevice) on Activity testing, to unlock the device, you need to call `KeyguardManager.KeyguardLock.disableKeyguard()`. This method requires the `DISABLE_KEYGUARD` permission. It seems like yours is a better alternative. Any idea why your alternative isn't used in the documentation? – nhaarman Apr 09 '14 at 22:06
  • @NiekHaarman It is also stated in [documentation](http://developer.android.com/reference/android/app/KeyguardManager.KeyguardLock.html) that `KeyguardLock` is deprecated. I guess they just don't have enough people to always update whole documentation. There are many examples of this. – MaciejGórski Apr 10 '14 at 18:24
3

Robotium discards invisible views when using enterText(int, String). Instead use getView(int) of Solo to use resulting view in enterText(View, String).

Like this:

public void testCanEnterTextAndPressButton() {
    solo.enterText(((EditText) solo.getView(R.id.editText1)), "my login");
    solo.enterText(((EditText) solo.getView(R.id.editText2)), "my password");
    solo.clickOnView(solo.getView(R.id.button));
}

And if the device screen is locked Robotium fails to run those instructions you gave. You might want to disable screen locking.

By code above my tests pass.

interlude
  • 843
  • 8
  • 29
  • When you turn off the screen Android doesn't destroy `View`s. They are only destroyed after `onDestroy` is called. Do you have any explanation for why only a single build fails on Travis when "Stay Awake" is not used? – MaciejGórski Apr 07 '14 at 15:08
  • Do you know of a way to disable screen locking in this setup? – MaciejGórski Apr 08 '14 at 14:13
  • You can do this by using Settings app. Settings > Security > Screen Lock > None. Or you can do this by code : `mKeyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); mLock = mKeyGuardManager.newKeyguardLock("activity_classname"); mLock.disableKeyguard();` which is covered [here](http://developer.android.com/tools/testing/activity_testing.html#UITesting) – interlude Apr 08 '14 at 14:20
  • Works for me too, on my physical device (Nexus 5 with KitKat). Thanks interlude. – daffycricket Aug 25 '14 at 16:06
1

Your guess is probably right. One way to be sure that it is is to catch the exception that is thrown and call

solo.takeScreenshot("screenshotFileName");

and then take a look at the screenshot that is saved to your phone's SD card to see what your phone was doing at the time of the error.

I solved this problem by turning on the device's "Stay Awake" setting so it won't sleep while recharging.

Dave C
  • 928
  • 6
  • 12
  • Thanks for the suggestion. I'll try to figure out how to get back a screenshot from an emulator on Travis. – MaciejGórski Mar 31 '14 at 10:26
  • Sadly cannot use `takeScreenshot`, because it does `if(decorView == null) return;` in it's internals and looks like it just cannot find decor view the same way it cannot find my `EditText`. – MaciejGórski Mar 31 '14 at 17:26