Test Structure


Android testing is based on JUnit. In general, a JUnit test is a method whose statements test a part of the application. You organize test methods into classes called test cases. You can further organize these classes into test suites.
In JUnit, you build one or more test classes and use a test runner to execute them. In Android, you use Android Studio (or the Android Plugin for Gradle) to build one or more test source files into an Android test app.
From your testing environment, you can run your test in one of the following ways:
  • On your local machine: Compile the test classes and execute them locally on the Java Virtual Machine (JVM) using the JUnit test runner.
  • On a device or emulator: Install the test app and the app under test to a physical device or emulator, and then execute your tests using an Android-specific test runner (such as AndroidJUnitRunner).
The structure of your test code and the way you build and run the tests in Android Studio depend on the type of testing you are performing. The following table summarizes the common testing types for Android:
Based on the type of test you want to create, you need to configure the test code source location and the project dependencies in Android Studio as described in Getting Started with Testing.

Local Unit Testing


Local unit tests - tests which can run on the JVM. Local Unit testing is about testing a particular component (i.e. an activity or model object) in isolation of other components. In Android, local unit tests do not require a device or emulator. These tests are typically placed in the app/src/test/java folder.

  • Robolectric - Popular Android unit test framework that allows faster test execution by running tests on the JVM (no device or emulator needed).
  • JUnit - Popular Java unit test framework. Most of the Android test frameworks are built on top of JUnit.

JUnit

You should write your unit or integration test class as a JUnit 4 test class. JUnit is the most popular and widely-used unit testing framework for Java. The framework offers a convenient way to perform common setup, teardown, and assertion operations in your test.
JUnit 4 allows you to write tests in a cleaner and more flexible way than its predecessor versions. Unlike the previous approach to Android unit testing based on JUnit 3, with JUnit 4, you do not need to extend thejunit.framework.TestCase class. You also do not need to prepend the test keyword to your test method name, or use any classes in the junit.framework or junit.extensions package.
A basic JUnit 4 test class is a Java class that contains one or more test methods. A test method begins with the @Testannotation and contains the code to exercise and verify a single functionality (that is, a logical unit) in the component that you want to test.
The following snippet shows an example JUnit 4 integration test that uses the Espresso APIs to perform a click action on a UI element, then checks to see if an expected string is displayed.
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {
    @Rule
    public ActivityTestRule mActivityRule = new ActivityTestRule<>(
            MainActivity.class);
    @Test
    public void sayHello(){
        onView(withText("Say hello!")).perform(click());
        onView(withId(R.id.textView)).check(matches(
withText("Hello, World!")));
    }
}
In your JUnit 4 test class, you can call out sections in your test code for special processing by using the following annotations:
  • @Before: Use this annotation to specify a block of code that contains test setup operations. The test class invokes this code block before each test. You can have multiple @Before methods but the order in which the test class calls these methods is not guaranteed.
  • @After: This annotation specifies a block of code that contains test tear-down operations. The test class calls this code block after every test method. You can define multiple @After operations in your test code. Use this annotation to release any resources from memory.
  • @Test: Use this annotation to mark a test method. A single test class can contain multiple test methods, each prefixed with this annotation.
  • @Rule: Rules allow you to flexibly add or redefine the behavior of each test method in a reusable way. In Android testing, use this annotation together with one of the test rule classes that the Android Testing Support Library provides, such as ActivityTestRule or ServiceTestRule.
  • @BeforeClass: Use this annotation to specify static methods for each test class to invoke only once. This testing step is useful for expensive operations such as connecting to a database.
  • @AfterClass: Use this annotation to specify static methods for the test class to invoke only after all tests in the class have run. This testing step is useful for releasing any resources allocated in the @BeforeClass block.
  • @Test(timeout=<milliseconds>): Some annotations support the ability to pass in elements for which you can set values. For example, you can specify a timeout period for the test. If the test starts but does not complete within the given timeout period, it automatically fails. You must specify the timeout period in milliseconds, for example:@Test(timeout=5000).
For more annotations, see the documentation for JUnit annotations and the Android-specific annotations.
You use the JUnit Assert class to verify the correctness of an object's state. The assert methods compare values you expect from a test to the actual results and throw an exception if the comparison fails. Assertion classes describes these methods in more detail.

Richer Validation Support

Simple JUnit assertions leave a lot to be desired when working on Android. The following libraries and classes help fill this gap.
  • Assertj-Android - An extension of AssertJ (fluent assertions for Java) extended for Android (formerly known as FEST Android).
  • MoreAsserts - Extension of JUnit assertions to add assertions for sets, lists, etc.
  • ViewAsserts - Helper methods to validate view layout

Assertion classes

Because Android Testing Support Library APIs extend JUnit, you can use assertion methods to display the results of tests. An assertion method compares an actual value returned by a test to an expected value, and throws an AssertionException if the comparison test fails. Using assertions is more convenient than logging, and provides better test performance.
To simplify your test development, we recommend that you use the Hamcrest library, which lets you create more flexible tests using the Hamcrest matcher APIs.

Instrumentation Unit Testing

Instrumented unit tests require the Android system. Android instrumentation is a set of control methods or hooks in the Android system that allow you to control the lifecycle of Android components (i.e. drive the activity lifecycle yourself instead of having these driven by the system). These hooks control an Android component independently of its normal lifecycle. They also control how Android loads applications. These tests require an actual device or emulator to run and are typically placed in the app/src/androidTest/java folder.
The following diagram summarizes the testing framework:

Normally, an Android component runs in a lifecycle that the system determines. For example, an Activity object's lifecycle starts when an Intent activates the Activity. The system calls the object's onCreate() method, on then the onResume() method. When the user starts another application, the system calls the onPause() method. If theActivity code calls the finish() method, the system calls the onDestroy() method. The Android framework API does not provide a way for your code to invoke these callback methods directly, but you can do so using instrumentation.
The system runs all the components of an application in the same process. You can allow some components, such as content providers, to run in a separate process, but you can't force an application to run in the same process as another application that is already running.
Instrumentation can load both a test package and the app under test into the same process. Since the application components and their tests are in the same process, your tests can invoke methods in the components, and modify and examine fields in the components.

Functional Tests


The SDK provides two tools for functional-level application testing:
  • The UI/Application Exerciser Monkey, usually called "monkey", is a command-line tool that sends pseudo-random streams of keystrokes, touches, and gestures to a device. This Program runs on the device and performs random clicks, text input, etc. You run it with the Android Debug Bridge (adb) tool. You use it to stress-test your application and report back errors that are encountered. You can repeat a stream of events by running the tool each time with the same random number seed.
  • The monkeyrunner tool is an API and execution environment for test programs written in Python. It allows controlling the Android device. The API includes functions for connecting to a device, installing and uninstalling packages, taking screenshots, comparing two images, and running a test package against an application. Using the API, you can write a wide range of large, powerful, and complex tests. You run programs that use the API with the monkeyrunner command-line tool.
  • Espresso - Extensible Android UI Test Framework provided by Google that handles test synchronization very well.
  • UIAutomator - Android UI Test Framework provided by Google for testing across multiple apps at the same time.
  • Google Android Testing - This is the testing framework included as part of the platform.
  • Robotium - Third party Android UI Test Framework (comparison with Espresso)
  • Selendroid - Selenium for Android

Mocking Frameworks


Mocking out dependencies is a very powerful capability when writing tests. These frameworks provide rich mocking support on Android.
  • Mockito - Popular mocking framework for Java
  • EasyMock - Mocking framework that has record / replay support 

Android Testing Support Library APIs


The Android Testing Support Library provides a set of APIs that allow you to quickly build and run test code for your apps, including JUnit 4 and functional user interface (UI) tests. The library includes the following instrumentation-based APIs that are useful when you want to automate your tests:
  • AndroidJUnitRunner: JUnit 4-compatible test runner for Android
  • Espresso: UI testing framework; suitable for functional UI testing within an app
  • UI Automator: UI testing framework; suitable for cross-app functional UI testing across system and installed apps