Jim Tang | dcbcc17 | 2019-11-25 17:21:28 +0800 | [diff] [blame] | 1 | # Atest Developer Guide |
| 2 | |
| 3 | You're here because you'd like to contribute to atest. To start off, we'll |
| 4 | explain how atest is structured and where the major pieces live and what they |
| 5 | do. If you're more interested in how to use atest, go to the [README](../README.md). |
| 6 | |
| 7 | ##### Table of Contents |
| 8 | 1. [Overall Structure](#overall-structure) |
| 9 | 2. [Major Files and Dirs](#major-files-and-dirs) |
| 10 | 3. [Test Finders](#test-finders) |
| 11 | 4. [Test Runners](#test-runners) |
| 12 | 5. [Constants Override](#constants-override) |
| 13 | |
| 14 | ## <a name="overall-structure">Overall Structure</a> |
| 15 | |
| 16 | Atest is primarily composed of 2 components: [test finders](#test-finders) and |
| 17 | [test runners](#test-runners). At a high level, atest does the following: |
| 18 | 1. Parse args and verify environment |
| 19 | 2. Find test(s) based on user input |
| 20 | 3. Build test dependencies |
| 21 | 4. Run test(s) |
| 22 | |
| 23 | Let's walk through an example run and highlight what happens under the covers. |
| 24 | |
| 25 | > ```# atest hello_world_test``` |
| 26 | |
| 27 | Atest will first check the environment is setup and then load up the |
| 28 | module-info.json file (and build it if it's not detected or we want to rebuild |
| 29 | it). That is a critical piece that atest depends on. Module-info.json contains a |
| 30 | list of all modules in the android repo and some relevant info (e.g. |
| 31 | compatibility_suite, auto_gen_config, etc) that is used during the test finding |
| 32 | process. We create the results dir for our test runners to dump results in and |
| 33 | proceed to the first juicy part of atest, finding tests. |
| 34 | |
| 35 | The tests specified by the user are passed into the ```CLITranslator``` to |
| 36 | transform the user input into a ```TestInfo``` object that contains all of the |
| 37 | required and optional bits used to run the test as how the user intended. |
| 38 | Required info would be the test name, test dependencies, and the test runner |
| 39 | used to run the test. Optional bits would be additional args for the test and |
| 40 | method/class filters. |
| 41 | |
| 42 | Once ```TestInfo``` objects have been constructed for all the tests passed in |
| 43 | by the user, all of the test dependencies are built. This step can by bypassed |
| 44 | if the user specifies only _-t_ or _-i_. |
| 45 | |
| 46 | The final step is to run the tests which is where the test runners do their job. |
| 47 | All of the ```TestInfo``` objects get passed into the ```test_runner_handler``` |
| 48 | which invokes each ```TestInfo``` specified test runner. In this specific case, |
| 49 | the ```AtestTradefedTestRunner``` is used to kick off ```hello_world_test```. |
| 50 | |
| 51 | Read on to learn more about the classes mentioned. |
| 52 | |
| 53 | ## <a name="major-files-and-dirs">Major Files and Dirs</a> |
| 54 | |
| 55 | Here is a list of major files and dirs that are important to point out: |
| 56 | * ```atest.py``` - Main entry point. |
| 57 | * ```cli_translator.py``` - Home of ```CLITranslator``` class. Translates the |
| 58 | user input into something the test runners can understand. |
| 59 | * ```test_finder_handler.py``` - Module that collects all test finders, |
| 60 | determines which test finder methods to use and returns them for |
| 61 | ```CLITranslator``` to utilize. |
| 62 | * ```test_finders/``` - Location of test finder classes. More details on test |
| 63 | finders [below](#test-finders). |
| 64 | * ```test_finders/test_info.py``` - Module that defines ```TestInfo``` class. |
| 65 | * ```test_runner_handler.py``` - Module that collects all test runners and |
| 66 | contains logic to determine what test runner to use for a particular |
| 67 | ```TestInfo```. |
| 68 | * ```test_runners/``` - Location of test runner classes. More details on test |
| 69 | runners [below](#test-runners). |
| 70 | * ```constants_default.py``` - Location of constant defaults. Need to override |
| 71 | some of these constants for your private repo? [Instructions below](#constants-override). |
| 72 | |
| 73 | ## <a name="test-finders">Test Finders</a> |
| 74 | |
| 75 | Test finders are classes that host find methods. The find methods are called by |
| 76 | atest to find tests in the android repo based on the user's input (path, |
| 77 | filename, class, etc). Find methods will also find the corresponding test |
| 78 | dependencies for the supplied test, translating it into a form that a test |
| 79 | runner can understand, and specifying the test runner. |
| 80 | |
| 81 | For more details and instructions on how to create new test finders, |
| 82 | [go here](./develop_test_finders.md) |
| 83 | |
| 84 | ## <a name="test-runners">Test Runners</a> |
| 85 | |
| 86 | Test Runners are classes that execute the tests. They consume a ```TestInfo``` |
| 87 | and execute the test as specified. |
| 88 | |
| 89 | For more details and instructions on how to create new test runners, [go here](./develop_test_runners.md) |
| 90 | |
| 91 | ## <a name="constants-override">Constants Override</a> |
| 92 | |
| 93 | You'd like to override some constants but not sure how? Override them with your |
| 94 | own constants_override.py that lives in your own private repo. |
| 95 | |
| 96 | 1. Create new ```constants_override.py``` (or whatever you'd like to name it) in |
| 97 | your own repo. It can live anywhere but just for example purposes, let's |
| 98 | specify the path to be ```<private repo>/path/to/constants_override/constants_override.py```. |
| 99 | 2. Add a ```vendorsetup.sh``` script in ```//vendor/<somewhere>``` to export the |
| 100 | path of ```constants_override.py``` base path into ```PYTHONPATH```. |
| 101 | ```bash |
| 102 | # This file is executed by build/envsetup.sh |
| 103 | _path_to_constants_override="$(gettop)/path/to/constants_override" |
| 104 | if [[ ! $PYTHONPATH == *${_path_to_constants_override}* ]]; then |
| 105 | export PYTHONPATH=${_path_to_constants_override}:$PYTHONPATH |
| 106 | fi |
| 107 | ``` |
| 108 | 3. Try-except import ```constants_override``` in ```constants.py```. |
| 109 | ```python |
| 110 | try: |
| 111 | from constants_override import * |
| 112 | except ImportError: |
| 113 | pass |
| 114 | ``` |
| 115 | 4. You're done! To pick up the override, rerun build/envsetup.sh to kick off the |
| 116 | vendorsetup.sh script. |