For the More Curious: Espresso and Integration Testing

You may recall that SoundViewModelTest from earlier was a unit test. Your other option was to create an integration test. So: What is an integration test?

In a unit test, the item under test is an individual class. In an integration, the item under test is your whole app. They are usually written screen by screen. For example, you might test that when the BeatBoxActivity screen is fired up, the first button displays the name of the first file from sample_sounds: 65_cjipie.

Integration tests should pass when the app does what you expect, not when the app is implemented how you expect. Changing the name of a button ID does not affect what the application does, but if you write an integration test that says, Call findViewById(R.id.button) and make sure the button it finds is displaying the right text, that test will break. So instead of using standard Android framework tools like findViewById(int), integration tests are most often written with a UI testing framework that makes it easier to say things like, Make sure there is a button with the text I expect on the screen somewhere.

Espresso is a UI testing framework from Google for testing Android apps. You can include it by adding com.android.support.test.espresso:espresso-core as an androidTestCompile artifact in your app/build.gradle file.

Once you have Espresso included as a dependency, you can use it to make assertions about an activity you have fired up to test. Here is an example test showing how to assert that a view exists on the screen with the first sample_sounds test file name:

@RunWith(AndroidJUnit4.class)
public class BeatBoxActivityTest {
    @Rule
    public ActivityTestRule<BeatBoxActivity> mActivityRule =
            new ActivityTestRule<>(BeatBoxActivity.class);

    @Test
    public void showsFirstFileName() {
        onView(withText("65_cjipie"))
                .check(matches(anything()));
    }
}

A couple of annotations get this code up and running. The @RunWith(AndroidJUnit4.class) annotation up top specifies that this is an Android instrumentation test that might want to work with activities and other Android runtime toys. After that, the @Rule annotation on mActivityRule signals to JUnit that it should fire up an instance of BeatBoxActivity before running each test.

With that setup done, you can make assertions about BeatBoxActivity in your test. In showsFirstFileName(), the line onView(withText("65_cjipie")) finds a view with the text "65_cjipie" on it to perform a test operation on. The call to check(matches(anything())) after that then asserts that the view exists – if there is no view with that text, the check will fail. The check(…) method is Espresso’s way to make assertThat(…)-type assertions about views.

Often you will want to click on a view, then make an assertion to verify the result of your click. You can also use Espresso to click on views or otherwise interact with them:

onView(withText("65_cjipie"))
        .perform(click());

When you interact with a view, Espresso will wait until your application is idle before continuing your test. Espresso has built in ways of detecting when your UI is done updating, but if you need Espresso to wait longer, you can use a subclass of IdlingResource to signal to Espresso that your app has not settled down quite yet.

For more information about how to use Espresso to manipulate the UI and test it, see the Espresso documentation at google.github.io/​android-testing-support-library/​docs/​espresso.

Integration tests and unit tests each serve different purposes. Most people prefer to start with unit tests because they run quickly enough to be run mindlessly, making it easy to establish a habit. Integration tests take long enough that they cannot be run as frequently. Each gives you a distinct, important view of the health of your app, though, so the best shops do both kinds of tests.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.35.60