2

I have two Activities A and B. I am running a background thread for 500ms and update a TextView. Once the TextView is updated, I click on the TextView to go to B Activity. In Activity B I have another background thread which is running for 500ms and update a TextView in the B Activity. I am testing this flow using Espresso. I wait for the background thread to complete the execution using Idling Resource. I am facing a problem on using Idling Resource in B Activity. I have put down my code below:

MainActivityTest.java:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
    @Rule
    public ActivityTestRule<MainActivity> mainActivityActivityTestRule = new ActivityTestRule<>(MainActivity.class);

    private IdlingResource mIdlingResource;

    @Before
    public void registerIdlingResource(){
        mIdlingResource = mainActivityActivityTestRule.getActivity().getIdlingResource();
        // To prove that the test fails, omit this call:
//        Espresso.registerIdlingResources(mIdlingResource);
        IdlingRegistry.getInstance().register(mIdlingResource);
    }

    @Test
    public void mainScreenLoads(){
        onView(withId(R.id.my_text)).check(matches(ViewMatchers.withText("Boom")));
        onView(withId(R.id.my_text)).perform(click());
        onView(withId(R.id.second_text)).check(matches(ViewMatchers.withText("Boom")));
    }

    @After
    public void unregisterIdlingResource() {
        if (mIdlingResource != null) {
//            Espresso.unregisterIdlingResources(mIdlingResource);
            IdlingRegistry.getInstance().unregister(mIdlingResource);
        }
    }
}

A Activity:

public class MainActivity extends AppCompatActivity {

    CountingIdlingResource countingIdlingResource = new CountingIdlingResource("DATA_LOADER");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();

        countingIdlingResource.increment();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(500);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ((TextView)findViewById(R.id.my_text)).setText("Boom");
                        ((TextView)findViewById(R.id.my_text)).setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                                startActivity(intent);
                            }
                        });
                        countingIdlingResource.decrement();
                    }
                });
            }
        }).start();
    }

    /**
     * Only called from test, creates and returns a new {@link SimpleIdlingResource}.
     */
    @VisibleForTesting
    @NonNull
    public IdlingResource getIdlingResource() {
        return countingIdlingResource;
    }
}

B Activity:

public class SecondActivity extends AppCompatActivity {

    CountingIdlingResource countingIdlingResource = new CountingIdlingResource("DATA_LOADER");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    @Override
    protected void onResume() {
        super.onResume();
        countingIdlingResource.increment();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(500);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ((TextView)findViewById(R.id.second_text)).setText("Boom");
//                        if (mIdlingResource != null) {
//                            mIdlingResource.setIdleState(true);
//                        }
                        countingIdlingResource.decrement();
                    }
                });
            }
        }).start();
    }
}

I am getting below error:

android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'with text: is "Boom"' doesn't match the selected view.
Expected: with text: is "Boom"
Got: "AppCompatTextView{id=2131165282, res-name=second_text, visibility=VISIBLE, width=246, height=51, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@94bfcec, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=Second Screen, input-type=0, ime-target=false, has-links=false}"

at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1566)
at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:90)
at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:52)
at android.support.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:314)
at android.support.test.espresso.ViewInteraction.check(ViewInteraction.java:291)
at com.example.sagarsuri.rxjavademo.MainActivityTest.mainScreenLoads(MainActivityTest.java:47)
sagar suri
  • 4,351
  • 12
  • 59
  • 122

2 Answers2

2

You can use singleton class and control the idling resource from there.

class EspressoKIdlingResource {
companion object {
    val countingIdlingResource = CountingIdlingResource("data_loaded")

    fun getInstance() : CountingIdlingResource{
        return countingIdlingResource
    }

    fun increment(){
        countingIdlingResource.increment()
    }

    fun decrement(){
        countingIdlingResource.decrement()
    }
}
1

The reason is that you have two different CountingIdlingResource instances in both activties, and only one from Activity A was registered. You should implement the same method for returning IdlingResource in Activity B and use this answer to get correct Activity while running test.