普通文本  |  369行  |  15.3 KB

#!/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.

'''