1# Running Android instrumentation tests with Mobly
2
3This tutorial shows how to write and execute Mobly tests for running Android
4instrumentation tests. For more details about instrumentation tests, please refer to
5https://developer.android.com/studio/test/index.html.
6
7## Setup Requirements
8
9*   A computer with at least 1 USB ports.
10*   Mobly package and its system dependencies installed on the computer.
11*   One Android device that is compatible with your instrumentatation and
12    application apks.
13*   Your instrumentation and applications apks for installing.
14*   A working adb setup. To check, connect one Android device to the computer
15    and make sure it has "USB debugging" enabled. Make sure the device shows up
16    in the list printed by `adb devices`.
17
18## Example Name Substitutions
19
20Here are the names that we use in this tutorial, substitute these names with
21your actual apk package and file names when using your real files:
22
23*   The application apk : `application.apk`
24*   The instrumentation apk : `instrumentation_test.apk`
25*   The instrumentation test package : `com.example.package.test`
26
27## Example 1: Running Instrumentation Tests
28
29Assuming your apks are already installed on devices. You can just subclass the
30instrumentation test class and run against your package.
31
32You will need a configuration file for Mobly to find your devices.
33
34***sample_config.yml***
35
36```yaml
37TestBeds:
38  - Name: BasicTestBed
39    Controllers:
40        AndroidDevice: '*'
41```
42
43***instrumentation_test.py***
44
45```python
46from mobly import base_instrumentation_test
47from mobly import test_runner
48from mobly.controllers import android_device
49
50class InstrumentationTest(base_instrumentation_test.BaseInstrumentationTestClass):
51    def setup_class(self):
52        self.dut = self.register_controller(android_device)[0]
53
54    def test_instrumentation(self):
55        self.run_instrumentation_test(self.dut, 'com.example.package.test')
56
57
58if __name__ == '__main__':
59  test_runner.main()
60```
61
62*To execute:*
63
64```
65$ python instrumentation_test.py -c sample_config.yml
66```
67
68*Expect*:
69
70The output from normally running your instrumentation tests along with a summary
71of the test results.
72
73## Example 2: Specifying Instrumentation Options
74
75If your instrumentation tests use instrumentation options for controlling
76behaviour, then you can put these options into your configuration file and then
77fetch them when you run your instrumentatation tests.
78
79***sample_config.yml***
80
81```yaml
82TestBeds:
83  - Name: BasicTestBed
84    Controllers:
85        AndroidDevice: '*'
86    TestParams:
87        instrumentation_option_annotation: android.support.test.filters.LargeTest
88        instrumentation_option_nonAnnotation: android.support.test.filters.SmallTest
89```
90
91***instrumentation_test.py***
92
93```python
94from mobly import base_instrumentation_test
95from mobly import test_runner
96from mobly.controllers import android_device
97
98class InstrumentationTest(base_instrumentation_test.BaseInstrumentationTestClass):
99    def setup_class(self):
100        self.dut = self.register_controller(android_device)[0]
101        self.options = self.parse_instrumentation_options(self.user_params)
102
103    def test_instrumentation(self):
104        self.run_instrumentation_test(self.dut, 'com.example.package.test',
105            options=self.options)
106
107
108if __name__ == '__main__':
109  test_runner.main()
110```
111
112*To execute:*
113
114```
115$ python instrumentation_test.py -c sample_config.yml
116```
117
118*Expect*:
119
120The output of your *LargeTest* instrumentation tests with no *SmallTest*
121instrumentation test being run.
122
123## Example 3 Using a Custom Runner
124
125If you have a custom runner that you use for instrumentation tests, then you can
126specify it in the *run_instrumentation_test* method call. Replace
127`com.example.package.test.CustomRunner` with the fully qualified package name of
128your real instrumentation runner.
129
130```python
131def test_instrumentation(self):
132  self.run_instrumentation_test(self.dut, 'com.example.package.test',
133      runner='com.example.package.test.CustomRunner')
134```
135
136## Example 4: Multiple Instrumentation Runs
137
138If you have multiple devices that you want to run instrumentation tests
139against, then you can simply call the *run_instrumentation_test* method
140multiple times. If you need to distinguish between runs, then you can specify
141a prefix.
142
143***sample_config.yml***
144
145```yaml
146TestBeds:
147  - Name: TwoDeviceTestBed
148    Controllers:
149        AndroidDevice:
150          - serial: xyz
151            label: dut
152          - serial: abc
153            label: dut
154```
155
156***instrumentation_test.py***
157
158```python
159from mobly import base_instrumentation_test
160from mobly import test_runner
161from mobly.controllers import android_device
162
163class InstrumentationTest(base_instrumentation_test.BaseInstrumentationTestClass):
164    def setup_class(self):
165        self.ads = self.register_controller(android_device)
166        # Get all of the dut devices to run instrumentation tests against.
167        self.duts = android_device.get_devices(self.ads, label='dut')
168
169    def test_instrumentation(self):
170        # Iterate over the dut devices with a corresponding index.
171        for index, dut in enumerate(self.duts):
172            # Specify a prefix to help disambiguate the runs.
173            self.run_instrumentation_test(dut, 'com.example.package.tests',
174                prefix='test_run_%s' % index)
175
176
177if __name__ == '__main__':
178  test_runner.main()
179```
180
181*To execute:*
182
183```
184$ python instrumentation_test.py -c sample_config.yml
185```
186
187*Expect*:
188
189The output from both instrumentation runs along with an aggregated summary of
190the results from both runs.
191