Existing Android UI tests stopped working after switching to AndroidJUnitRunner
Asked Answered
P

2

10

We have a few UI tests around our camera functionality, and after we made the switch from InstrumentationTestRunner to AndroidJUnitRunner as part of our move to Espresso/JUnit4, we can no longer run our existing tests reliably due to frequent RuntimeException when we call getActivity():

java.lang.RuntimeException: Could not launch intent Intent { flg=0x14000000 cmp=com.cookbrite.dev/com.cookbrite.ui.ReceiptCaptureActivity (has extras) } within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1434471981236 and now the last time the queue went idle was: 1434471981236. If these numbers are the same your activity might be hogging the event queue.
at android.support.test.runner.MonitoringInstrumentation.startActivitySync(MonitoringInstrumentation.java:315)
at android.test.InstrumentationTestCase.launchActivityWithIntent(InstrumentationTestCase.java:119)
at android.test.ActivityInstrumentationTestCase2.getActivity(ActivityInstrumentationTestCase2.java:106)
at com.cookbrite.step2_functional.ui.receipt.ReceiptCaptureTest.getActivity(ReceiptCaptureTest.java:43)

For better readibility, this is the error message on the RuntimeException as a quote:

Could not launch intent Intent { flg=0x14000000 cmp=com.cookbrite.dev/com.cookbrite.ui.ReceiptCaptureActivity (has extras) } within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1434471981236 and now the last time the queue went idle was: 1434471981236. If these numbers are the same your activity might be hogging the event queue.

Our existing tests use Robotium. An attempt to write the same test using Espresso yielded similar error, which is probably due to camera preview constantly updating the UI. However, even with preview set to INVISIBLE, we still run into this issue with Espresso.

Any ideas/pointers on how to fix this (other than go back to InstrumentationTestRunner)?

Pyrognostics answered 16/6, 2015 at 19:6 Comment(6)
does the robotium test run fine when you have the preview set to INVISIBLE or GONELoehr
my Robotium tests still fails with the same RuntimeException when review is set to INVISIBLE.Pyrognostics
ok.. we have experienced this before...in our case it was because we used to launch new activities on every button click.. and as a result roboitum would konk out.. we had to kill all the activities in the tearDown..Loehr
Unfortunately, this can happen even when launching the single activity we have, and can happen to the first test case in a test suite. We can see the activity being created correctly in the emulator or device, but nothing will happen. Still, thanks for leaving your experience @user2511882!Pyrognostics
What version of the test runner are you running? Stephan Linzner indicated another getActivity() timeout bug was fixed in 0.3. Hopefully your case was also addressed.Contributory
@Contributory we are using runner 0.3Pyrognostics
P
0

In the end, we change the UI to delay camera preview startup so MonitoringInstrumentation doesn't get upset with all the UI update. Also, both SurfaceView and TextureView post UI updates as soon as a camera is connected, even in INVISIBLE or GONE state. That's what causes MonitoringInstrumentation to give up in our case.

If you have a test that starts with constant UI update, you might want to consider pausing the action until startActivitySync() finishes and you get a non-null result from getActivity().

Pyrognostics answered 11/3, 2016 at 17:57 Comment(0)
C
0

The error output indicates that the test class extends ActivityInstrumentationTestCase2. I'm not sure whether moving to the new ActivityTestRule would make any difference in your case, but it's worth a quick check. Putting this in an answer rather than a comment in order to include sample code:

@RunWith(AndroidJUnit4.class)
public class ReceiptCaptureTestNew {
    private ReceiptCaptureActivity mReceiptCaptureActivity;

    @Rule
    public ActivityTestRule<mReceiptCaptureActivity> mActivityRule =
            new ActivityTestRule<>(mReceiptCaptureActivity.class);

    @Before
    public void setUp() throws Exception {
        mReceiptCaptureActivity = mActivityRule.getActivity();
    }

    @After
    public void tearDown() throws Exception {
        // Call finish() on all activities in @After to avoid exceptions in
        // later calls to getActivity() in subsequent tests
        mReceiptCaptureActivity.finish();
    }

    @Test
    public void testPreconditions() {
        assertNotNull(mReceiptCaptureActivity);
        assertThat(mReceiptCaptureActivity.hasWindowFocus(), is(true));
    }
}
Contributory answered 21/6, 2015 at 4:17 Comment(1)
Unfortunately when I write the same test in Espresso, I used ActivityRule + Junit4Runner and I got the same result. But thanks for the answer!Pyrognostics
P
0

In the end, we change the UI to delay camera preview startup so MonitoringInstrumentation doesn't get upset with all the UI update. Also, both SurfaceView and TextureView post UI updates as soon as a camera is connected, even in INVISIBLE or GONE state. That's what causes MonitoringInstrumentation to give up in our case.

If you have a test that starts with constant UI update, you might want to consider pausing the action until startActivitySync() finishes and you get a non-null result from getActivity().

Pyrognostics answered 11/3, 2016 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.