Friday 19 May 2017

HB Blog 136: Android Automation Testing Using Espresso Framework.

Android tests are based on JUnit, and you can run them either as local unit tests on the JVM or as instrumented tests on an Android device. This post provides an introduction to the concepts and tools for building Android tests.
When using Android Studio to write any of your tests, your test code must go into one of two different code directories (source sets). For each module in your project, Android Studio includes both source sets, corresponding to the following test types:
Local unit tests:-
Located at module-name/src/test/java/.
These tests run on the local JVM and do not have access to functional Android framework APIs.

Instrumented tests:-
Located at module-name/src/androidTest/java/.
These are all tests that must run on an Android hardware device or an Android emulator.
Instrumented tests are built into an APK that runs on the device alongside your app under test. The system runs your test APK and your app under tests in the same process, so your tests can invoke methods and modify fields in the app, and automate user interaction with your app.
        Building Instrumented Unit Tests: Build complex unit tests with Android dependencies that cannot be satisfied with mock objects.
        Automating User Interface Tests: Create tests to verify that the user interface behaves correctly for user interactions within a single app or for interactions across multiple apps.
        Testing App Component Integrations: Verify the behavior of components that users do not directly interact with, such as a Service or a Content Provider.
However, the local unit tests and instrumented tests described above are just terms that help distinguish the tests that run on your local JVM from the tests that run on the Android platform (on a hardware device or emulator). The real testing types that you should understand when building a complete test suite are described in the following table.

TypeSubtype Description
Unit tests
Local Unit Tests Unit tests that run locally on the Java Virtual Machine (JVM). Use these tests to minimize execution time when your tests have no Android framework dependencies or when you can mock the Android framework dependencies.
Instrumented unit tests Unit tests that run on an Android device or emulator. These tests have access to Instrumentation information, such as the Context of the app you are testing. Use these tests when your tests have Android dependencies that mock objects cannot satisfy.
Integration Tests
Components within your app only This type of test verifies that the target app behaves as expected when a user performs a specific action or enters a specific input in its activities. For example, it allows you to check that the target app returns the correct UI output in response to user interactions in the app’s activities. UI testing frameworks like Espresso allow you to programmatically simulate user actions and test complex intra-app user interactions.
Cross-app Components This type of test verifies the correct behavior of interactions between different user apps or between user apps and system apps. For example, you might want to test that your app behaves correctly when the user performs an action in the Android Settings menu. UI testing frameworks that support cross-app interactions, such as UI Automator, allow you to create tests for such scenarios.
JUnit
You should write your unit or integration test class as a JUnit test class. The framework offers a convenient way to perform common setup, teardown, and assertion operations in your test.
A basic JUnit test class is a Java class that contains one or more test methods. A test method begins with the @Test annotation 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 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.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@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=): 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).
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.

No comments:

Post a Comment