3.2: App testing

Contents:

In this chapter you get an overview of Android testing, and you learn about creating and running local unit tests in Android Studio with JUnit.

About testing

Even though you have an app that compiles and runs and looks the way you want it to on different devices, you must make sure that your app will behave the way you expect it to in every situation, especially as your app grows and changes. Even if you try to manually test your app every time you make a change—a tedious prospect at best—you might miss something or not anticipate what end users might do with your app to cause it to fail.

Writing and running tests is a critical part of the software development process. Test-driven development (TDD) is a popular software development philosophy that places tests at the core of all software development for an app or service.This does not negate the need for further testing, it merely gives you a solid baseline to work with.

Testing your code can help you catch issues early in development—when they are the least expensive to address—and improve the robustness of your code as your app gets larger and more complex. With tests in your code, you can exercise small portions of your app in isolation, and in an automatable and repeatable manner for more efficient testing.

The code you write to test your app doesn't end up in the production version of your app; it lives only on your development machine, alongside your app's code in Android Studio.

Types of tests

Android supports several different kinds of tests and testing frameworks. Two basic forms of testing Android Studio supports are local unit tests and instrumented tests.

Local unit tests are tests that are compiled and run entirely on your local machine with the Java Virtual Machine (JVM). Use local unit tests to test the parts of your app (such as the internal logic) that do not need access to the Android framework or an Android-powered device or emulator, or those for which you can create fake ("mock" or stub) objects that pretend to behave like the framework equivalents.

Instrumented tests are tests that run on an Android-powered device or emulator. These tests have access to the Android framework and to Instrumentation information such as the app's Context. You can use instrumented tests for unit testing, user interface (UI) testing, or integration testing, making sure that the components of your app interact correctly with other apps. Most commonly, you use instrumented tests for UI testing, which allows you to test that your app behaves correctly when a user interacts with your app or enters a specific input.

For most forms of user interface testing, you use the Espresso framework, which allows you to write automated UI tests. You'll learn about instrumented tests and Espresso in another chapter.

Unit Testing

Unit tests should be the fundamental tests in your app testing strategy. By creating and running unit tests against your code, you can verify that the logic of individual functional code areas or units is correct. Running unit tests after every build helps you catch and fix problems introduced by code changes to your app.

A unit test generally exercises the functionality of the smallest possible unit of code (which could be a method, class, or component) in a repeatable way. Create unit tests when you need to verify the logic of specific code in your app. For example, if you unit test a class, your test might check that the class is in the right state. For a method, you might test its behavior for different values of its parameters, especially null.

Typically, you test the unit of code in isolation, and your test monitors changes only to that unit. You can use a mocking framework such as Mockito to isolate your unit from its dependencies.You can also write your unit tests for Android in JUnit 4, a common unit testing framework for Java code.

The Android Testing Support Library

The Android Testing Support Library provides the infrastructure and APIs for testing Android apps, including support for JUnit 4. With the testing support library you can build and run test code for your apps.

You may already have the Android Testing Support Library installed with Android Studio. To check for the Android Support Repository, follow these steps:

  1. In Android Studio choose Tools > Android > SDK Manager.
  2. Click the SDK Tools tab, and look for the Support Repository.
  3. If necessary, update or install the library.

The Android Testing Support Library classes are located under the android.support.test package. There are also older testing APIs in android.test. You should use the support libraries first, when given a choice between the support libraries and the older APIs, as the support libraries help build and distribute tests in a cleaner and more reliable fashion than directly coding against the API itself.

Setting up testing

To prepare your project for testing in Android Studio, you need to:

  • Organize your tests in a source set.
  • Configure your project's Gradle dependencies to include testing-related APIs.

Android Studio source sets

Source sets are collections of code in your project that are for different build targets or other "flavors" of your app. When Android Studio creates your project, it creates three source sets for you:

  • The main source set, for your app's code and resources.
  • The (test) source set, for your app's local unit tests. The source set shows (test) after the package name.
  • The (androidTest) source set, for Android instrumented tests. The source set shows (androidTest) after the package name.

Source sets appear in the Android Studio Project > Android pane under the package name for your app. The main source set includes just the package name. The test and androidTest source sets have the package name followed by (test) or (androidTest), respectively.  Default testing source sets

These source sets correspond to folders in the src directory for your project. For example, the files for the test source set are located in src/test/java.

Configuring Gradle for test dependencies

To use the unit testing APIs, you may need to configure the dependencies for your project. The default Gradle build file, provided by Activity templates such as the Empty Activity template, includes some of these dependencies, but you may need to add more dependencies for additional testing features such as matching or mocking frameworks.

In your app project's build.gradle (Module: app) file, the following dependency should already be included (if not, you should add it):

testImplementation 'junit:junit:4.12'

The androidTestImplementation dependencies are required for UI testing with Espresso, described in another chapter:

androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 
                    'com.android.support.test.espresso:espresso-core:3.0.1'

Note that the version numbers for these libraries may have changed. If Android Studio reports a newer library, update the number to reflect the current version.

You may also want to add dependencies for the optional Hamcrest matchers and the Mokito framework:

testCompile 'org.hamcrest:hamcrest-library:1.3'
testCompile 'org.mockito:mockito-core:1.10.19'

After editing the build.gradle (Module: app) file, you must sync your project to continue. Click Sync Now in Android Studio when prompted.

Configuring a test runner

A test runner is a library or set of tools that enables testing to occur and the results to be printed to a log. Your Android project has access to a basic JUnit test runner as part of the JUnit4 APIs. The Android test support library includes a test runner for instrumented and Espresso tests, AndroidJUnitRunner, which also supports JUnit 3 and 4.

This chapter demonstrates the default runner for unit tests, which is supplied by Activity templates such as the Empty Activity template. In your app project's build.gradle (Module: app) file, the following test runner should already be included in the defaultConfig section (if not, you should add it):

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

Creating and running unit tests

Create your unit tests as a generic Java file using the JUnit 4 APIs, and store those tests in the (test) source set. Each Android Studio project template includes this source set and a sample Java test file called ExampleUnitTest.

Creating a new test class

To create a new test class file, add a Java file to the (test) source set for your project. Test class files for unit testing are typically named for the class in your app that you are testing, with "Test" appended. For example, if you have a class called Calculator in your app, the class for your unit tests would be CalculatorTest.

To add a new test class file, follow these steps:

  1. Expand the java folder and the folder for your app's test source set. The existing unit test class files are shown.
  2. Right-click (or Control-click) on the test source set folder and select New > Java Class.
  3. Name the file and click OK.

Writing your tests

Use JUnit 4 syntax and annotations to write your tests. For example, the test class shown below includes the following annotations:

  • The @RunWith annotation indicates the test runner that should be used for the tests in this class.
  • The @SmallTest annotation indicates that this is a small (and fast) test.
  • The @Before annotation marks a method as being the setup for the test.
  • The @Test annotation marks a method as an actual test.

For more information on JUnit annotations, see JUnit 4 API Reference.

@RunWith(JUnit4.class)
@SmallTest
public class CalculatorTest {
   private Calculator mCalculator;
   // Set up the environment for testing
   @Before
   public void setUp() {
      mCalculator = new Calculator();
   }

   // test for simple addition
   @Test
   public void addTwoNumbers() {
       double resultAdd = mCalculator.add(1d, 1d);
       assertThat(resultAdd, is(equalTo(2d)));
   }
}

The addTwoNumbers() method is the actual test. The key part of a unit test is the assertion, which is defined here by the assertThat() method. Assertions are expressions that must evaluate and result in a value of true for the test to pass. For more information on assertions, see the JUnit reference documentation for the Assert class.

JUnit 4 provides a number of assertion methods, but assertThat() is the most flexible, as it allows for general-purpose comparison methods called matchers. The Hamcrest framework is commonly used for matchers ("Hamcrest" is an anagram for matchers). Hamcrest includes a large number of comparison methods as well as enabling you to write your own. For more information on the Hamcrest framework, see the Java Hamcrest homepage.

Note that the addTwoNumbers() method in this example includes only one assertion. The general rule for unit tests is to provide a separate test method for every individual assertion. Grouping more than one assertion into a single method can make your tests harder to debug if only one assertion fails, and obscures the tests that do succeed.

Running your tests

To run your local unit tests, follow these steps:

  • To run a single test, right-click (or Control-click) that test method and select Run.
  • To test all the methods in a test class, right-click (or Control-click) the test file in the Android > Project pane, and select Run.
  • To run all tests in a directory, right-click (or Control-click) on the directory and select Run tests.

The project builds, if necessary, and the testing view appears at the bottom of the screen. If all the tests you ran are successful, the progress bar at the top of the view turns green. A status message in the footer also reports "Tests Passed."  All tests successful

The related practical is 3.2: Unit tests.

Learn more

Android Studio documentation:

Android developer documentation:

Other:

results matching ""

    No results matching ""