Atest Developer Guide

You‘re here because you’d like to contribute to atest. To start off, we‘ll explain how atest is structured and where the major pieces live and what they do. If you’re more interested in how to use atest, go to the README.

Table of Contents
  1. Overall Structure
  2. Major Files and Dirs
  3. Test Finders
  4. Test Runners
  5. Constants Override

Overall Structure

Atest is primarily composed of 2 components: test finders and test runners. At a high level, atest does the following:

  1. Parse args and verify environment
  2. Find test(s) based on user input
  3. Build test dependencies
  4. Run test(s)

Let's walk through an example run and highlight what happens under the covers.

# atest hello_world_test

Atest will first check the environment is setup and then load up the module-info.json file (and build it if it's not detected or we want to rebuild it). That is a critical piece that atest depends on. Module-info.json contains a list of all modules in the android repo and some relevant info (e.g. compatibility_suite, auto_gen_config, etc) that is used during the test finding process. We create the results dir for our test runners to dump results in and proceed to the first juicy part of atest, finding tests.

The tests specified by the user are passed into the CLITranslator to transform the user input into a TestInfo object that contains all of the required and optional bits used to run the test as how the user intended. Required info would be the test name, test dependencies, and the test runner used to run the test. Optional bits would be additional args for the test and method/class filters.

Once TestInfo objects have been constructed for all the tests passed in by the user, all of the test dependencies are built. This step can by bypassed if the user specifies only -t or -i.

The final step is to run the tests which is where the test runners do their job. All of the TestInfo objects get passed into the test_runner_handler which invokes each TestInfo specified test runner. In this specific case, the AtestTradefedTestRunner is used to kick off hello_world_test.

Read on to learn more about the classes mentioned.

Major Files and Dirs

Here is a list of major files and dirs that are important to point out:

  • atest.py - Main entry point.
  • cli_translator.py - Home of CLITranslator class. Translates the user input into something the test runners can understand.
  • test_finder_handler.py - Module that collects all test finders, determines which test finder methods to use and returns them for CLITranslator to utilize.
  • test_finders/ - Location of test finder classes. More details on test finders below.
  • test_finders/test_info.py - Module that defines TestInfo class.
  • test_runner_handler.py - Module that collects all test runners and contains logic to determine what test runner to use for a particular TestInfo.
  • test_runners/ - Location of test runner classes. More details on test runners below.
  • constants_default.py - Location of constant defaults. Need to override some of these constants for your private repo? Instructions below.

Test Finders

Test finders are classes that host find methods. The find methods are called by atest to find tests in the android repo based on the user's input (path, filename, class, etc). Find methods will also find the corresponding test dependencies for the supplied test, translating it into a form that a test runner can understand, and specifying the test runner.

For more details and instructions on how to create new test finders, go here

Test Runners

Test Runners are classes that execute the tests. They consume a TestInfo and execute the test as specified.

For more details and instructions on how to create new test runners, go here

Constants Override

You'd like to override some constants but not sure how? Override them with your own constants_override.py that lives in your own private repo.

  1. Create new constants_override.py (or whatever you‘d like to name it) in your own repo. It can live anywhere but just for example purposes, let’s specify the path to be <private repo>/path/to/constants_override/constants_override.py.
  2. Add a vendorsetup.sh script in //vendor/<somewhere> to export the path of constants_override.py base path into PYTHONPATH.
# This file is executed by build/envsetup.sh
_path_to_constants_override="$(gettop)/path/to/constants_override"
if [[ ! $PYTHONPATH == *${_path_to_constants_override}* ]]; then
  export PYTHONPATH=${_path_to_constants_override}:$PYTHONPATH
fi
  1. Try-except import constants_override in constants.py.
try:
    from constants_override import *
except ImportError:
    pass
  1. You're done! To pick up the override, rerun build/envsetup.sh to kick off the vendorsetup.sh script.