Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Espresso: Testing error message is shown?

I have a test that is supposed to test the visibility of an error msg when there is no network connection, but I dunno how to get it to show?

@RunWith(AndroidJUnit4.class)
@LargeTest
public class PostsActivityTest {

@Rule
public final ActivityRule<PostsActivity> rule = new ActivityRule<>(PostsActivity.class);

PostsActivity postsActivity;

@Before
public void init() {
    postsActivity = rule.get();
}

@Test
public void testShouldShowErrorViewOnNetworkError() {
    postsActivity.showErrorMsg(); // doesn't work
    onView(withId(R.id.error_view)).check(matches(isDisplayed()));
}

When calling postsActivity.showErrorMsg(); I get a crash stating android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

This is the showErrorMsg() in PostsActivity:

public void showErrorMsg() {
    errorView.setVisibility(View.VISIBLE);
}

Any help appreciated. Thanks!

Edit: Using runOnUiThread seems to be working. I dunno if this is the preferred way though.

@Test
public void testShouldShowErrorViewOnNetworkError() {
    postsActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            postsActivity.showErrorMsg();
        }
    });
    onView(withId(R.id.error_view)).check(matches(isDisplayed()));
}
like image 936
mco Avatar asked Jun 20 '16 05:06

mco


People also ask

What is Espresso UI testing?

Espresso is an open source android user interface (UI) testing framework developed by Google. The term Espresso is of Italian origin, meaning Coffee. Espresso is a simple, efficient and flexible testing framework.

How do you check espresso visibility?

One simple way to check for a View or its subclass like a Button is to use method getVisibility from View class. I must caution that visibility attribute is not clearly defined in the GUI world. A view may be considered visible but may be overlapped with another view, for one example, making it hidden.

How do I get Textview espresso from text?

The basic idea is to use a method with an internal ViewAction that retrieves the text in its perform method. Anonymous classes can only access final fields, so we cannot just let it set a local variable of getText() , but instead an array of String is used to get the string out of the ViewAction .


1 Answers

In your Espresso tests you should not directly call methods of your Activity. You should use Espresso to interact with the UI like a real user.

Why runOnUiThread is required:

When running instrumentation tests (e.g. Espresso tests) there are actually two apps involved. First the app that is being tested and the app that executes the tests. Both use different main threads.

If you call PostsActivity#showErrorMsg from your test, it is running in the testing apps thread. But manipulating views in Android is only allowed from the apps UI Thread. If you really have to call PostsActivity#showErrorMsg from your test, runOnUiThread is the right choice.

How to improve

So instead of calling PostsActivity#showErrorMsg directly from your test, use Espresso to click() e.g. on a Button that will call that method for you:

@Test
public void testShouldShowErrorViewOnNetworkError() {
    onView(withId(R.id.post_button)).perform(click());
    onView(withId(R.id.error_view)).check(matches(isDisplayed()));
}
like image 72
thaussma Avatar answered Sep 26 '22 08:09

thaussma