Android Programming The Big Nerd Ranch Guide by Bill Phillips, Chris Stewart, Kristin Marsicano (z-lib.org)

(gtxtreme123) #1

Chapter 21  Unit Testing and Audio Playback


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.


For the More Curious: Mocks and Testing


Mocking has a much different role in integration testing than it does in unit testing. Mock objects exist
to isolate the component under test by pretending to be other unrelated components. Unit tests test an
individual class; each class will have its own distinct dependencies, so each test class has a different set
of mock objects. Since the mock objects are different in each test class, and the behavior rarely matters,
mock frameworks that make it easy to create simple mock objects (like Mockito) are a great fit for unit
tests.


Integration tests, on the other hand, are meant to test the entire app as a single piece. Instead of
isolating pieces of the app from each other, you use mocks to isolate the app from anything external
it might interact with – for example, by providing a web service with fake data and responses. In
BeatBox, you would provide a fake SoundPool that could tell you when a particular sound file was
played. Because the mocks are larger and shared among many tests, and because it is more common to
implement mock behavior, it is better to avoid automatic mocking frameworks for integration tests and
instead manually write mock objects.


In either case, the same rule applies: Mock out the entities at the boundary of the component under
test. This focuses the scope of your test and keeps it from breaking except when the component itself is
broken.

Free download pdf