lin
2025-08-21 57113df3a0e2be01232281fad9a5f2c060567981
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
#!/usr/bin/env python
#
# Copyright 2018, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
 
"""
Atest Argument Parser class for atest.
"""
 
import argparse
 
import atest_utils
import constants
 
 
class AtestArgParser(argparse.ArgumentParser):
    """Atest wrapper of ArgumentParser."""
 
    def __init__(self):
        """Initialise an ArgumentParser instance."""
        atest_utils.print_data_collection_notice()
        super(AtestArgParser, self).__init__(
            description=constants.HELP_DESC,
            epilog=self.EPILOG_TEXT,
            formatter_class=argparse.RawTextHelpFormatter)
 
    def add_atest_args(self):
        """A function that does ArgumentParser.add_argument()"""
        self.add_argument('tests', nargs='*', help='Tests to build and/or run.')
        self.add_argument('-b', '--build', action='append_const', dest='steps',
                          const=constants.BUILD_STEP, help='Run a build.')
        self.add_argument('-i', '--install', action='append_const', dest='steps',
                          const=constants.INSTALL_STEP, help='Install an APK.')
        self.add_argument('--info', action='store_true',
                          help='Show module information.')
        self.add_argument('--dry-run', action='store_true',
                          help='Dry run atest without building, installing and running '
                               'tests in real.')
        self.add_argument('-t', '--test', action='append_const', dest='steps',
                          const=constants.TEST_STEP,
                          help='Run the tests. WARNING: Many test configs force cleanup '
                               'of device after test run. In this case, -d must be used in '
                               'previous test run to disable cleanup, for -t to work. '
                               'Otherwise, device will need to be setup again with -i.')
        self.add_argument('-s', '--serial', help='The device to run the test on.')
        self.add_argument('-L', '--list-modules', help='List testable modules for the given suite.')
        self.add_argument('-d', '--disable-teardown', action='store_true',
                          help='Disables test teardown and cleanup.')
        self.add_argument('-m', constants.REBUILD_MODULE_INFO_FLAG, action='store_true',
                          help='Forces a rebuild of the module-info.json file. '
                               'This may be necessary following a repo sync or '
                               'when writing a new test.')
        self.add_argument('-w', '--wait-for-debugger', action='store_true',
                          help='Only for instrumentation tests. Waits for '
                               'debugger prior to execution.')
        self.add_argument('-v', '--verbose', action='store_true',
                          help='Display DEBUG level logging.')
        self.add_argument('-a', '--all-abi', action='store_true',
                          help='Set to run tests for all abi.')
        self.add_argument('--generate-baseline', nargs='?', type=int, const=5, default=0,
                          help='Generate baseline metrics, run 5 iterations by default. '
                               'Provide an int argument to specify # iterations.')
        self.add_argument('--generate-new-metrics', nargs='?', type=int, const=5, default=0,
                          help='Generate new metrics, run 5 iterations by default. '
                               'Provide an int argument to specify # iterations.')
        self.add_argument('--detect-regression', nargs='*',
                          help='Run regression detection algorithm. Supply '
                               'path to baseline and/or new metrics folders.')
        # Options related to module parameterization
        self.add_argument('--instant', action='store_true',
                          help='Run the instant_app version of the module, '
                               'if the module supports it. Note: running a test '
                               'that does not support instant with --instant '
                               'will result in nothing running.')
        # Options related to Test Mapping
        self.add_argument('-p', '--test-mapping', action='store_true',
                          help='Run tests in TEST_MAPPING files.')
        self.add_argument('--include-subdirs', action='store_true',
                          help='Include tests in TEST_MAPPING files in sub directories.')
        # Options related to deviceless testing.
        self.add_argument('--host', action='store_true',
                          help='Run the test completely on the host without '
                               'a device. (Note: running a host test that '
                               'requires a device with --host will fail.)')
        # This arg actually doesn't consume anything, it's primarily used for the
        # help description and creating custom_args in the NameSpace object.
        self.add_argument('--', dest='custom_args', nargs='*',
                          help='Specify custom args for the test runners. '
                               'Everything after -- will be consumed as custom args.')
 
    def get_args(self):
        """This method is to get args from actions and return optional args.
 
        Returns:
            A list of optional arguments.
        """
        argument_list = []
        # The output of _get_optional_actions(): [['-t', '--test'], [--info]]
        # return an argument list: ['-t', '--test', '--info']
        for arg in self._get_optional_actions():
            argument_list.extend(arg.option_strings)
        return argument_list
 
 
    EPILOG_TEXT = '''
 
- - - - - - - - -
IDENTIFYING TESTS
- - - - - - - - -
 
    The positional argument <tests> should be a reference to one or more
    of the tests you'd like to run. Multiple tests can be run in one command by
    separating test references with spaces.
 
    Usage template: atest <reference_to_test_1> <reference_to_test_2>
 
    A <reference_to_test> can be satisfied by the test's MODULE NAME,
    MODULE:CLASS, CLASS NAME, TF INTEGRATION TEST, FILE PATH or PACKAGE NAME.
    Explanations and examples of each follow.
 
 
    < MODULE NAME >
 
        Identifying a test by its module name will run the entire module. Input
        the name as it appears in the LOCAL_MODULE or LOCAL_PACKAGE_NAME
        variables in that test's Android.mk or Android.bp file.
 
        Note: Use < TF INTEGRATION TEST > to run non-module tests integrated
        directly into TradeFed.
 
        Examples:
            atest FrameworksServicesTests
            atest CtsJankDeviceTestCases
 
 
    < MODULE:CLASS >
 
        Identifying a test by its class name will run just the tests in that
        class and not the whole module. MODULE:CLASS is the preferred way to run
        a single class. MODULE is the same as described above. CLASS is the
        name of the test class in the .java file. It can either be the fully
        qualified class name or just the basic name.
 
        Examples:
            atest FrameworksServicesTests:ScreenDecorWindowTests
            atest FrameworksServicesTests:com.android.server.wm.ScreenDecorWindowTests
            atest CtsJankDeviceTestCases:CtsDeviceJankUi
 
 
    < CLASS NAME >
 
        A single class can also be run by referencing the class name without
        the module name.
 
        Examples:
            atest ScreenDecorWindowTests
            atest CtsDeviceJankUi
 
        However, this will take more time than the equivalent MODULE:CLASS
        reference, so we suggest using a MODULE:CLASS reference whenever
        possible. Examples below are ordered by performance from the fastest
        to the slowest:
 
        Examples:
            atest FrameworksServicesTests:com.android.server.wm.ScreenDecorWindowTests
            atest FrameworksServicesTests:ScreenDecorWindowTests
            atest ScreenDecorWindowTests
 
    < TF INTEGRATION TEST >
 
        To run tests that are integrated directly into TradeFed (non-modules),
        input the name as it appears in the output of the "tradefed.sh list
        configs" cmd.
 
        Examples:
           atest example/reboot
           atest native-benchmark
 
 
    < FILE PATH >
 
        Both module-based tests and integration-based tests can be run by
        inputting the path to their test file or dir as appropriate. A single
        class can also be run by inputting the path to the class's java file.
        Both relative and absolute paths are supported.
 
        Example - 2 ways to run the `CtsJankDeviceTestCases` module via path:
        1. run module from android <repo root>:
            atest cts/tests/jank/jank
 
        2. from <android root>/cts/tests/jank:
            atest .
 
        Example - run a specific class within CtsJankDeviceTestCases module
        from <android repo> root via path:
           atest cts/tests/jank/src/android/jank/cts/ui/CtsDeviceJankUi.java
 
        Example - run an integration test from <android repo> root via path:
           atest tools/tradefederation/contrib/res/config/example/reboot.xml
 
 
    < PACKAGE NAME >
 
        Atest supports searching tests from package name as well.
 
        Examples:
           atest com.android.server.wm
           atest android.jank.cts
 
 
- - - - - - - - - - - - - - - - - - - - - - - - - -
SPECIFYING INDIVIDUAL STEPS: BUILD, INSTALL OR RUN
- - - - - - - - - - - - - - - - - - - - - - - - - -
 
    The -b, -i and -t options allow you to specify which steps you want to run.
    If none of those options are given, then all steps are run. If any of these
    options are provided then only the listed steps are run.
 
    Note: -i alone is not currently support and can only be included with -t.
    Both -b and -t can be run alone.
 
    Examples:
        atest -b <test>    (just build targets)
        atest -t <test>    (run tests only)
        atest -it <test>   (install apk and run tests)
        atest -bt <test>   (build targets, run tests, but skip installing apk)
 
 
    Atest now has the ability to force a test to skip its cleanup/teardown step.
    Many tests, e.g. CTS, cleanup the device after the test is run, so trying to
    rerun your test with -t will fail without having the --disable-teardown
    parameter. Use -d before -t to skip the test clean up step and test iteratively.
 
        atest -d <test>    (disable installing apk and cleanning up device)
        atest -t <test>
 
    Note that -t disables both setup/install and teardown/cleanup of the
    device. So you can continue to rerun your test with just
 
        atest -t <test>
 
    as many times as you want.
 
 
- - - - - - - - - - - - -
RUNNING SPECIFIC METHODS
- - - - - - - - - - - - -
 
    It is possible to run only specific methods within a test class. To run
    only specific methods, identify the class in any of the ways supported for
    identifying a class (MODULE:CLASS, FILE PATH, etc) and then append the
    name of the method or method using the following template:
 
      <reference_to_class>#<method1>
 
    Multiple methods can be specified with commas:
 
      <reference_to_class>#<method1>,<method2>,<method3>...
 
    Examples:
      atest com.android.server.wm.ScreenDecorWindowTests#testMultipleDecors
 
      atest FrameworksServicesTests:ScreenDecorWindowTests#testFlagChange,testRemoval
 
 
- - - - - - - - - - - - -
RUNNING MULTIPLE CLASSES
- - - - - - - - - - - - -
 
    To run multiple classes, deliminate them with spaces just like you would
    when running multiple tests.  Atest will handle building and running
    classes in the most efficient way possible, so specifying a subset of
    classes in a module will improve performance over running the whole module.
 
 
    Examples:
    - two classes in same module:
      atest FrameworksServicesTests:ScreenDecorWindowTests FrameworksServicesTests:DimmerTests
 
    - two classes, different modules:
      atest FrameworksServicesTests:ScreenDecorWindowTests CtsJankDeviceTestCases:CtsDeviceJankUi
 
 
- - - - - - - - - - -
REGRESSION DETECTION
- - - - - - - - - - -
 
    Generate pre-patch or post-patch metrics without running regression detection:
 
    Example:
        atest <test> --generate-baseline <optional iter>
        atest <test> --generate-new-metrics <optional iter>
 
    Local regression detection can be run in three options:
 
    1) Provide a folder containing baseline (pre-patch) metrics (generated
       previously). Atest will run the tests n (default 5) iterations, generate
       a new set of post-patch metrics, and compare those against existing metrics.
 
    Example:
        atest <test> --detect-regression </path/to/baseline> --generate-new-metrics <optional iter>
 
    2) Provide a folder containing post-patch metrics (generated previously).
       Atest will run the tests n (default 5) iterations, generate a new set of
       pre-patch metrics, and compare those against those provided. Note: the
       developer needs to revert the device/tests to pre-patch state to generate
       baseline metrics.
 
    Example:
        atest <test> --detect-regression </path/to/new> --generate-baseline <optional iter>
 
    3) Provide 2 folders containing both pre-patch and post-patch metrics. Atest
       will run no tests but the regression detection algorithm.
 
    Example:
        atest --detect-regression </path/to/baseline> </path/to/new>
 
 
- - - - - - - - - - - -
TESTS IN TEST MAPPING
- - - - - - - - - - - -
 
    Atest can run tests in TEST_MAPPING files:
 
    1) Run presubmit tests in TEST_MAPPING files in current and parent
       directories. You can also specify a target directory.
 
    Example:
        atest  (run presubmit tests in TEST_MAPPING files in current and parent directories)
        atest --test-mapping </path/to/project>
               (run presubmit tests in TEST_MAPPING files in </path/to/project> and its parent directories)
 
    2) Run a specified test group in TEST_MAPPING files.
 
    Example:
        atest :postsubmit
              (run postsubmit tests in TEST_MAPPING files in current and parent directories)
        atest :all
              (Run tests from all groups in TEST_MAPPING files)
        atest --test-mapping </path/to/project>:postsubmit
              (run postsubmit tests in TEST_MAPPING files in </path/to/project> and its parent directories)
 
    3) Run tests in TEST_MAPPING files including sub directories
 
    By default, atest will only search for tests in TEST_MAPPING files in
    current (or given directory) and its parent directories. If you want to run
    tests in TEST_MAPPING files in the sub-directories, you can use option
    --include-subdirs to force atest to include those tests too.
 
    Example:
        atest --include-subdirs [optional </path/to/project>:<test_group_name>]
              (run presubmit tests in TEST_MAPPING files in current, sub and parent directories)
    A path can be provided optionally if you want to search for tests in a give
    directory, with optional test group name. By default, the test group is
    presubmit.
 
'''