Home | History | Annotate | Download | only in unit-testing
      1 page.title=Building Instrumented Unit Tests
      2 page.tags=testing,androidjunitrunner,junit,unit test,mock,instrumentation
      3 trainingnavtop=true
      4 
      5 @jd:body
      6 
      7 <!-- This is the training bar -->
      8 <div id="tb-wrapper">
      9 <div id="tb">
     10   <h2>Dependencies and Prerequisites</h2>
     11 
     12   <ul>
     13     <li>Android 2.2 (API level 8) or higher</li>
     14     <li><a href="{@docRoot}tools/testing-support-library/index.html">
     15       Android Testing Support Library</a></li>
     16   </ul>
     17 
     18   <h2>This lesson teaches you to</h2>
     19 
     20   <ol>
     21     <li><a href="#setup">Set Up Your Testing Environment</a></li>
     22     <li><a href="#build">Create a Instrumented Unit Test Class</a></li>
     23     <li><a href="#run">Run Instrumented Unit Tests</a></li>
     24   </ol>
     25 
     26   <h2>Try it out</h2>
     27 
     28   <ul>
     29     <li>
     30 <a href="https://github.com/googlesamples/android-testing/tree/master/unittesting/BasicUnitAndroidTest"
     31 class="external-link">Instrumented Unit Tests Code Samples</a></li>
     32   </ul>
     33 </div>
     34 </div>
     35 
     36 <p>
     37 Instrumented unit tests are unit tests that run on physical devices and emulators, instead of
     38 the Java Virtual Machine (JVM) on your local machine. You should create instrumented unit tests
     39 if your tests need access to instrumentation information (such as the target app's
     40 {@link android.content.Context}) or if they require the real implementation of an Android framework
     41 component (such as a {@link android.os.Parcelable} or {@link android.content.SharedPreferences}
     42 object). Using instrumented unit tests also helps to reduce the effort required to write and
     43 maintain mock code. You are still free to use a mocking framework, if you choose, to simulate any
     44 dependency relationships. Instrumented unit tests can take advantage of the Android framework APIs
     45 and supporting APIs, such as the Android Testing Support Library.
     46 </p>
     47 
     48 <h2 id="setup">Set Up Your Testing Environment</h2>
     49 <p>Before building instrumented unit tests, you must:</p>
     50 
     51   <ul>
     52       <li>
     53         <strong>Install the Android Testing Support Library</strong>. The
     54         <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
     55         {@code AndroidJUnitRunner}</a> API, located under the
     56         {@code com.android.support.test.runner} package, allows you to
     57         create and run instrumented unit tests.  To learn how to install the
     58         library, see <a href="{@docRoot}tools/testing-support-library/index.html#setup">
     59         Testing Support Library Setup</a>.
     60       </li>
     61 
     62       <li>
     63         <strong>Set up your project structure.</strong> In your Gradle project, the source code for
     64         the target app that you want to test is typically placed under the {@code app/src/main/java}
     65         folder. The source code for instrumentatation tests, including your unit tests, must be
     66         placed under the <code>app/src/androidTest/java</code> folder.
     67         To learn more about setting up your project directory, see
     68         <a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.
     69       </li>
     70 
     71       <li>
     72         <strong>Specify your Android testing dependencies</strong>. In order for the
     73         <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for Gradle</a> to
     74         correctly build and run your instrumented unit tests, you must specify the following
     75         libraries in the {@code build.gradle} file of your Android app module:
     76 
     77         <pre>
     78 dependencies {
     79     androidTestCompile 'com.android.support.test:runner:0.3'
     80     androidTestCompile 'com.android.support.test:rules:0.3'
     81     // Set this dependency if you want to use Hamcrest matching
     82     androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
     83 }
     84 </pre>
     85       </li>
     86   </ul>
     87 
     88 <h2 id="build">Create an Instrumented Unit Test Class</h2>
     89 <p>
     90 Your instrumented unit test class should be written as a JUnit 4 test class. To learn more about
     91 creating JUnit 4 test classes and using JUnit 4 assertions and annotations, see
     92 <a href="local-unit-tests.html#build">Create a Local Unit Test Class</a>.
     93 </p>
     94 <p>To create an instrumented JUnit 4 test class, add the {@code &#64;RunWith(AndroidJUnit4.class)}
     95 annotation at the beginning of your test class definition. You also need to specify the
     96 <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
     97 {@code AndroidJUnitRunner}</a> class
     98 provided in the Android Testing Support Library as your default test runner. This step is described
     99 in more detail in <a href="#run">Run Instrumented Unit Tests</a>.
    100 </p>
    101 
    102 <p>The following example shows how you might write an instrumented unit test to test that
    103 the {@link android.os.Parcelable} interface is implemented correctly for the
    104 {@code LogHistory} class:</p>
    105 
    106 <pre>
    107 import android.os.Parcel;
    108 import android.support.test.runner.AndroidJUnit4;
    109 import android.util.Pair;
    110 import org.junit.Test;
    111 import org.junit.runner.RunWith;
    112 import java.util.List;
    113 import static org.hamcrest.Matchers.is;
    114 import static org.junit.Assert.assertThat;
    115 
    116 &#64;RunWith(AndroidJUnit4.class)
    117 public class LogHistoryAndroidUnitTest {
    118 
    119     public static final String TEST_STRING = "This is a string";
    120     public static final long TEST_LONG = 12345678L;
    121     private LogHistory mLogHistory;
    122 
    123     &#64;Before
    124     public void createLogHistory() {
    125         mLogHistory = new LogHistory();
    126     }
    127 
    128     &#64;Test
    129     public void logHistory_ParcelableWriteRead() {
    130         // Set up the Parcelable object to send and receive.
    131         mLogHistory.addEntry(TEST_STRING, TEST_LONG);
    132 
    133         // Write the data.
    134         Parcel parcel = Parcel.obtain();
    135         mLogHistory.writeToParcel(parcel, mLogHistory.describeContents());
    136 
    137         // After you're done with writing, you need to reset the parcel for reading.
    138         parcel.setDataPosition(0);
    139 
    140         // Read the data.
    141         LogHistory createdFromParcel = LogHistory.CREATOR.createFromParcel(parcel);
    142         List&lt;Pair&lt;String, Long&gt;&gt; createdFromParcelData = createdFromParcel.getData();
    143 
    144         // Verify that the received data is correct.
    145         assertThat(createdFromParcelData.size(), is(1));
    146         assertThat(createdFromParcelData.get(0).first, is(TEST_STRING));
    147         assertThat(createdFromParcelData.get(0).second, is(TEST_LONG));
    148     }
    149 }
    150 </pre>
    151 
    152 <h3 id="test-suites">Creating a test suite</h3>
    153 <p>
    154 To organize the execution of your instrumented unit tests, you can group a collection of test
    155 classes in a <em>test suite</em> class and run these tests together. Test suites can be nested;
    156 your test suite can group other test suites and run all their component test classes together.
    157 </p>
    158 
    159 <p>
    160 A test suite is contained in a test package, similar to the main application package. By
    161 convention, the test suite package name usually ends with the {@code .suite} suffix (for example,
    162 {@code com.example.android.testing.mysample.suite}).
    163 </p>
    164 
    165 <p>
    166 To create a test suite for your unit tests, import the JUnit
    167 <a href="http://junit.sourceforge.net/javadoc/org/junit/runner/RunWith.html"
    168 class="external-link">{@code RunWith}</a> and
    169 <a href="http://junit.sourceforge.net/javadoc/org/junit/runners/Suite.html"
    170 class="external-link">{@code Suite}</a> classes. In your test suite, add the
    171 {@code &#64;RunWith(Suite.class)} and the {@code &#64;Suite.SuitClasses()} annotations. In
    172 the {@code &#64;Suite.SuiteClasses()} annotation, list the individual test classes or test
    173 suites as arguments.
    174 </p>
    175 
    176 <p>
    177 The following example shows how you might implement a test suite called {@code UnitTestSuite}
    178 that groups and runs the {@code CalculatorInstrumentationTest} and
    179 {@code CalculatorAddParameterizedTest} test classes together.
    180 </p>
    181 
    182 <pre>
    183 import com.example.android.testing.mysample.CalculatorAddParameterizedTest;
    184 import com.example.android.testing.mysample.CalculatorInstrumentationTest;
    185 import org.junit.runner.RunWith;
    186 import org.junit.runners.Suite;
    187 
    188 // Runs all unit tests.
    189 &#64;RunWith(Suite.class)
    190 &#64;Suite.SuiteClasses({CalculatorInstrumentationTest.class,
    191         CalculatorAddParameterizedTest.class})
    192 public class UnitTestSuite {}
    193 </pre>
    194 
    195 <h2 id="run">Run Instrumented Unit Tests</h2>
    196 <p>
    197 The
    198 <a href="https://developer.android.com/tools/building/plugin-for-gradle.html">
    199   Android Plug-in for Gradle</a>
    200 provides a default directory ({@code src/androidTest/java}) for you to store the instrumented unit
    201 and integration test classes and test suites that you want to run on a device. The plug-in compiles
    202 the test code in that directory and then executes the test app using a test runner class. You must
    203 set the
    204 <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
    205 {@code AndroidJUnitRunner}</a> class provided in the
    206 <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>
    207 as your default test runner.</p>
    208 </p>
    209 
    210 <p>To specify
    211 <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
    212 {@code AndroidJUnitRunner}</a> as the default test instrumentation runner, add the following
    213 setting in your {@code build.gradle} file:</p>
    214 <pre>
    215 android {
    216     defaultConfig {
    217         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    218     }
    219 }
    220 </pre>
    221 
    222 <h3 id="run-from-Android-Studio">Running instrumented unit tests from Android Studio</h3>
    223 <p>
    224 To run instrumented unit tests in your Gradle project from Android Studio:
    225 </p>
    226 <ol>
    227 <li>Open the <strong>Build Variants</strong> window by clicking the left-hand tab, then set the
    228 test artifact to <em>Android Instrumentation Tests</em>.
    229 </li>
    230 <li>In the <strong>Project</strong> window, drill down to your unit test class or method, then
    231   right-click and run it using the Android Test configuration.
    232 </li>
    233 </ol>
    234 
    235 <p>Android Studio displays the results of the unit test execution in the <strong>Run</strong>
    236 window.</p>
    237 
    238 <h3 id="run-from-commandline">Running instrumented unit tests from the command-line</h3>
    239 
    240 <p>To run instrumented unit tests in your Gradle project from the command-line, call the
    241   {@code connectedCheck} (or {@code cC}) task:</p>
    242 
    243 <pre>
    244 ./gradlew cC
    245 </pre>
    246 
    247 <p>You can find the generated HTML test result reports in the
    248 {@code &lt;path_to_your_project&gt;/app/build/outputs/reports/androidTests/connected/} directory,
    249 and the corresponding XML files in the
    250 {@code &lt;path_to_your_project&gt;/app/build/outputs/androidTest-results/connected/} directory.</p>