Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could not launch intent within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time?

I am writing Espresso Test. Here is the test case

OnClick of Fab, the app launches QuizActivity.

Let me explain to you little about my app.

So the app requirement was -

  1. There is JSON file in assets folder
  2. I have to parse it and store the data in database
  3. On Main Activity load this data from database into recyclerview. There is Fab button, on click of it app pass a random list of data (which I have loaded in recyclerview) to QuizActivity

Here is how I did coding -

  1. In MainActivity's onCreate() used AsyncTask to parse and insert data into database only once.
  2. Once data is available, loaded it in recyclerview via AsyncTaskLoader
  3. set Onclick listener on Fab. and passed required data to QuizActivity.

Below is my test

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
   /* @Rule
    public IntentsTestRule<MainActivity> intentsTestRule =
            new IntentsTestRule<MainActivity>(MainActivity.class);
*/

    @Rule
    public ActivityTestRule<MainActivity> intentsTestRule =
            new ActivityTestRule<MainActivity>(MainActivity.class,false,true);

    @Test
    public void fabTest(){
        onView(withId(R.id.fab)).perform(click());
        //Check if the text_question textview is displayed
        onView(withId(R.id.text_question)).check(matches(isDisplayed()));
    }

   /* @Test
    public void clickFloatingActionButton() {
        onView(withId(R.id.fab))
                .perform(click());
        intended(hasComponent(new ComponentName(getTargetContext(), QuizActivity.class)));
    }*/
}

My approach is -

  1. Find Fab
  2. Perform click
  3. Check if the text_question textview is displayed. Note this textview is on QuizActivity.

After I run the test I am getting

java.lang.RuntimeException: Could not launch intent Intent { act=android.intent.action.MAIN flg=0x14000000 cmp=my_package_name/.MainActivity } 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 1505287862579 and now the last time the queue went idle was: 1505287862579. If these numbers are the same your activity might be hogging the event queue.

PS - I have turned off all the animations. I don't have progress bar in code.

Also one more note , if I comment out the AsyncTask, AsyncTaskLoader, RecyclerView part in onCreate() method then the test is passing.

I suspect that it might be causing due to background task.

Anyone faced similar problem? Please let me know if you know the solution. I am struggling from two days. I searched for similar threads on stackoverflow but nothing worked for me.

like image 675
Programmer Avatar asked Sep 13 '17 08:09

Programmer


1 Answers

I finally got the solution!

Actually, the culprit was custom view in my adapter.

Espresso waits until the AsyncTask or AsyncTaskLoader loads the data, but it looks like custom view causing this problem as stated in the exception :

the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen.

Anyways to overcome this problem, what I need to do is -

"If the test is running set the visibility of Custom view to GONE"

How would you do that?

 private AtomicBoolean isTestRunning;

    public synchronized boolean isTestRunning () {
        if (null == isTestRunning) {
            boolean istest;

            try {

                Class.forName ("Full path of your TestName"); // for e.g. com.example.MyTest

                istest = true;
            } catch (ClassNotFoundException e) {
                istest = false;
            }

            isTestRunning = new AtomicBoolean (istest);
        }

        return isRunningTest.get ();
    }

Now here I am using Recyclerview so in ViewHolder,

public InsectHolder(View itemView)
        {
            super(itemView);
                       customView = (DangerLevelView) itemView.findViewById(R.id.danger_level_tv);

            if(isRunningTest()) {
                customView.setVisibility(View.GONE);
            }
        }

And yay! your test will be passed.

Hope someone finds it helpful!

Please let me know if you have any questions in comment section below!

like image 154
Programmer Avatar answered Nov 03 '22 19:11

Programmer