summaryrefslogtreecommitdiff
path: root/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
blob: 38321eed93b302193d3e144d5f5190a78ee18fe8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
page.title=Building Instrumented Unit Tests
page.tags=testing,androidjunitrunner,junit,unit test,mock,instrumentation
trainingnavtop=true

@jd:body

<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
  <h2>Dependencies and Prerequisites</h2>

  <ul>
    <li>Android 2.2 (API level 8) or higher</li>
    <li><a href="{@docRoot}tools/testing-support-library/index.html">
      Android Testing Support Library</a></li>
    <li><a href="{@docRoot}tools/studio/index.html">Android Studio (latest version)</a>.</li>
  </ul>

  <h2>This lesson teaches you to</h2>

  <ol>
    <li><a href="#setup">Set Up Your Testing Environment</a></li>
    <li><a href="#build">Create a Instrumented Unit Test Class</a></li>
    <li><a href="#run">Run Instrumented Unit Tests</a></li>
  </ol>

  <h2>Try it out</h2>

  <ul>
    <li>
<a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicUnitAndroidTest"
class="external-link">Instrumented Unit Tests Code Samples</a></li>
    <li><a href="https://www.code-labs.io/codelabs/android-studio-testing/index.html?index=..%2F..%2Findex#0"
class="external-link">Unit and UI Testing in Android Studio (codelab)</a></li>
  </ul>
</div>
</div>

<p>
Instrumented unit tests are unit tests that run on physical devices and emulators, instead of
the Java Virtual Machine (JVM) on your local machine. You should create instrumented unit tests
if your tests need access to instrumentation information (such as the target app's
{@link android.content.Context}) or if they require the real implementation of an Android framework
component (such as a {@link android.os.Parcelable} or {@link android.content.SharedPreferences}
object). Using instrumented unit tests also helps to reduce the effort required to write and
maintain mock code. You are still free to use a mocking framework, if you choose, to simulate any
dependency relationships. Instrumented unit tests can take advantage of the Android framework APIs
and supporting APIs, such as the Android Testing Support Library.
</p>

<h2 id="setup">Set Up Your Testing Environment</h2>
<p>Before building your instrumented unit test, make sure to configure your test source code
location and project dependencies, as described in
<a href="{@docRoot}training/testing/start/index.html#config-instrumented-tests">
Getting Started with Testing</a>.</p>

<h2 id="build">Create an Instrumented Unit Test Class</h2>
<p>
Your instrumented unit test class should be written as a JUnit 4 test class. To learn more about
creating JUnit 4 test classes and using JUnit 4 assertions and annotations, see
<a href="local-unit-tests.html#build">Create a Local Unit Test Class</a>.
</p>
<p>To create an instrumented JUnit 4 test class, add the {@code &#64;RunWith(AndroidJUnit4.class)}
annotation at the beginning of your test class definition. You also need to specify the
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
{@code AndroidJUnitRunner}</a> class
provided in the Android Testing Support Library as your default test runner. This step is described
in more detail in <a href="{@docRoot}training/testing/start/index.html#run-instrumented-tests">
Getting Started with Testing</p>

<p>The following example shows how you might write an instrumented unit test to test that
the {@link android.os.Parcelable} interface is implemented correctly for the
{@code LogHistory} class:</p>

<pre>
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
import android.util.Pair;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

&#64;RunWith(AndroidJUnit4.class)
&#64;SmallTest
public class LogHistoryAndroidUnitTest {

    public static final String TEST_STRING = "This is a string";
    public static final long TEST_LONG = 12345678L;
    private LogHistory mLogHistory;

    &#64;Before
    public void createLogHistory() {
        mLogHistory = new LogHistory();
    }

    &#64;Test
    public void logHistory_ParcelableWriteRead() {
        // Set up the Parcelable object to send and receive.
        mLogHistory.addEntry(TEST_STRING, TEST_LONG);

        // Write the data.
        Parcel parcel = Parcel.obtain();
        mLogHistory.writeToParcel(parcel, mLogHistory.describeContents());

        // After you're done with writing, you need to reset the parcel for reading.
        parcel.setDataPosition(0);

        // Read the data.
        LogHistory createdFromParcel = LogHistory.CREATOR.createFromParcel(parcel);
        List&lt;Pair&lt;String, Long&gt;&gt; createdFromParcelData = createdFromParcel.getData();

        // Verify that the received data is correct.
        assertThat(createdFromParcelData.size(), is(1));
        assertThat(createdFromParcelData.get(0).first, is(TEST_STRING));
        assertThat(createdFromParcelData.get(0).second, is(TEST_LONG));
    }
}
</pre>

<h3 id="test-suites">Creating a test suite</h3>
<p>
To organize the execution of your instrumented unit tests, you can group a collection of test
classes in a <em>test suite</em> class and run these tests together. Test suites can be nested;
your test suite can group other test suites and run all their component test classes together.
</p>

<p>
A test suite is contained in a test package, similar to the main application package. By
convention, the test suite package name usually ends with the {@code .suite} suffix (for example,
{@code com.example.android.testing.mysample.suite}).
</p>

<p>
To create a test suite for your unit tests, import the JUnit
<a href="http://junit.sourceforge.net/javadoc/org/junit/runner/RunWith.html"
class="external-link">{@code RunWith}</a> and
<a href="http://junit.sourceforge.net/javadoc/org/junit/runners/Suite.html"
class="external-link">{@code Suite}</a> classes. In your test suite, add the
{@code &#64;RunWith(Suite.class)} and the {@code &#64;Suite.SuitClasses()} annotations. In
the {@code &#64;Suite.SuiteClasses()} annotation, list the individual test classes or test
suites as arguments.
</p>

<p>
The following example shows how you might implement a test suite called {@code UnitTestSuite}
that groups and runs the {@code CalculatorInstrumentationTest} and
{@code CalculatorAddParameterizedTest} test classes together.
</p>

<pre>
import com.example.android.testing.mysample.CalculatorAddParameterizedTest;
import com.example.android.testing.mysample.CalculatorInstrumentationTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

// Runs all unit tests.
&#64;RunWith(Suite.class)
&#64;Suite.SuiteClasses({CalculatorInstrumentationTest.class,
        CalculatorAddParameterizedTest.class})
public class UnitTestSuite {}
</pre>

<h2 id="run">Run Instrumented Unit Tests</h2>
<p>
To run your test, follow the steps for running instrumented tests
described in <a href="{@docRoot}training/testing/start/index.html#run-instrumented-tests">
Getting Started with Testing</a>.
</p>