mirror of https://github.com/python/cpython
gh-116622: Android test script improvements (#124012)
* Set Android test script stdout to line-buffered * Print warning logcat messages on stderr * Add a -vv option to display high-volume messages which are rarely useful * Documentation and comment improvements
This commit is contained in:
parent
a47cd21890
commit
1f9d163850
|
@ -12,8 +12,12 @@ approachable user experience:
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
Export the `ANDROID_HOME` environment variable to point at your Android SDK. If
|
First, make sure you have all the usual tools and libraries needed to build
|
||||||
you don't already have the SDK, here's how to install it:
|
Python for your development machine.
|
||||||
|
|
||||||
|
Second, you'll need an Android SDK. If you already have the SDK installed,
|
||||||
|
export the `ANDROID_HOME` environment variable to point at its location.
|
||||||
|
Otherwise, here's how to install it:
|
||||||
|
|
||||||
* Download the "Command line tools" from <https://developer.android.com/studio>.
|
* Download the "Command line tools" from <https://developer.android.com/studio>.
|
||||||
* Create a directory `android-sdk/cmdline-tools`, and unzip the command line
|
* Create a directory `android-sdk/cmdline-tools`, and unzip the command line
|
||||||
|
@ -37,11 +41,6 @@ development tools, which currently means Linux or macOS. This involves doing a
|
||||||
cross-build where you use a "build" Python (for your development machine) to
|
cross-build where you use a "build" Python (for your development machine) to
|
||||||
help produce a "host" Python for Android.
|
help produce a "host" Python for Android.
|
||||||
|
|
||||||
First, make sure you have all the usual tools and libraries needed to build
|
|
||||||
Python for your development machine. The only Android tool you need to install
|
|
||||||
is the command line tools package above: the build script will download the
|
|
||||||
rest.
|
|
||||||
|
|
||||||
The easiest way to do a build is to use the `android.py` script. You can either
|
The easiest way to do a build is to use the `android.py` script. You can either
|
||||||
have it perform the entire build process from start to finish in one step, or
|
have it perform the entire build process from start to finish in one step, or
|
||||||
you can do it in discrete steps that mirror running `configure` and `make` for
|
you can do it in discrete steps that mirror running `configure` and `make` for
|
||||||
|
@ -80,12 +79,15 @@ call. For example, if you want a pydebug build that also caches the results from
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The tests can be run on Linux, macOS, or Windows, although on Windows you'll
|
The test suite can be run on Linux, macOS, or Windows:
|
||||||
have to build the `cross-build/HOST` subdirectory on one of the other platforms
|
|
||||||
and copy it over.
|
|
||||||
|
|
||||||
The test suite can usually be run on a device with 2 GB of RAM, though for some
|
* On Linux, the emulator needs access to the KVM virtualization interface, and
|
||||||
configurations or test orders you may need to increase this. As of Android
|
a DISPLAY environment variable pointing at an X server.
|
||||||
|
* On Windows, you won't be able to do the build on the same machine, so you'll
|
||||||
|
have to copy the `cross-build/HOST` directory from somewhere else.
|
||||||
|
|
||||||
|
The test suite can usually be run on a device with 2 GB of RAM, but this is
|
||||||
|
borderline, so you may need to increase it to 4 GB. As of Android
|
||||||
Studio Koala, 2 GB is the default for all emulators, although the user interface
|
Studio Koala, 2 GB is the default for all emulators, although the user interface
|
||||||
may indicate otherwise. The effective setting is `hw.ramSize` in
|
may indicate otherwise. The effective setting is `hw.ramSize` in
|
||||||
~/.android/avd/*.avd/hardware-qemu.ini, whereas Android Studio displays the
|
~/.android/avd/*.avd/hardware-qemu.ini, whereas Android Studio displays the
|
||||||
|
|
|
@ -259,8 +259,8 @@ def setup_testbed():
|
||||||
f"{temp_dir}/{outer_jar}", "gradle-wrapper.jar"])
|
f"{temp_dir}/{outer_jar}", "gradle-wrapper.jar"])
|
||||||
|
|
||||||
|
|
||||||
# run_testbed will build the app automatically, but it hides the Gradle output
|
# run_testbed will build the app automatically, but it's useful to have this as
|
||||||
# by default, so it's useful to have this as a separate command for the buildbot.
|
# a separate command to allow running the app outside of this script.
|
||||||
def build_testbed(context):
|
def build_testbed(context):
|
||||||
setup_sdk()
|
setup_sdk()
|
||||||
setup_testbed()
|
setup_testbed()
|
||||||
|
@ -376,6 +376,8 @@ async def find_pid(serial):
|
||||||
shown_error = False
|
shown_error = False
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
# `pidof` requires API level 24 or higher. The level 23 emulator
|
||||||
|
# includes it, but it doesn't work (it returns all processes).
|
||||||
pid = (await async_check_output(
|
pid = (await async_check_output(
|
||||||
adb, "-s", serial, "shell", "pidof", "-s", APP_ID
|
adb, "-s", serial, "shell", "pidof", "-s", APP_ID
|
||||||
)).strip()
|
)).strip()
|
||||||
|
@ -407,6 +409,7 @@ async def logcat_task(context, initial_devices):
|
||||||
serial = await wait_for(find_device(context, initial_devices), startup_timeout)
|
serial = await wait_for(find_device(context, initial_devices), startup_timeout)
|
||||||
pid = await wait_for(find_pid(serial), startup_timeout)
|
pid = await wait_for(find_pid(serial), startup_timeout)
|
||||||
|
|
||||||
|
# `--pid` requires API level 24 or higher.
|
||||||
args = [adb, "-s", serial, "logcat", "--pid", pid, "--format", "tag"]
|
args = [adb, "-s", serial, "logcat", "--pid", pid, "--format", "tag"]
|
||||||
hidden_output = []
|
hidden_output = []
|
||||||
async with async_process(
|
async with async_process(
|
||||||
|
@ -421,11 +424,15 @@ async def logcat_task(context, initial_devices):
|
||||||
# such messages, but other components might.
|
# such messages, but other components might.
|
||||||
level, message = None, line
|
level, message = None, line
|
||||||
|
|
||||||
|
# Exclude high-volume messages which are rarely useful.
|
||||||
|
if context.verbose < 2 and "from python test_syslog" in message:
|
||||||
|
continue
|
||||||
|
|
||||||
# Put high-level messages on stderr so they're highlighted in the
|
# Put high-level messages on stderr so they're highlighted in the
|
||||||
# buildbot logs. This will include Python's own stderr.
|
# buildbot logs. This will include Python's own stderr.
|
||||||
stream = (
|
stream = (
|
||||||
sys.stderr
|
sys.stderr
|
||||||
if level in ["E", "F"] # ERROR and FATAL (aka ASSERT)
|
if level in ["W", "E", "F"] # WARNING, ERROR, FATAL (aka ASSERT)
|
||||||
else sys.stdout
|
else sys.stdout
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -573,8 +580,9 @@ def parse_args():
|
||||||
test = subcommands.add_parser(
|
test = subcommands.add_parser(
|
||||||
"test", help="Run the test suite")
|
"test", help="Run the test suite")
|
||||||
test.add_argument(
|
test.add_argument(
|
||||||
"-v", "--verbose", action="store_true",
|
"-v", "--verbose", action="count", default=0,
|
||||||
help="Show Gradle output, and non-Python logcat messages")
|
help="Show Gradle output, and non-Python logcat messages. "
|
||||||
|
"Use twice to include high-volume messages which are rarely useful.")
|
||||||
device_group = test.add_mutually_exclusive_group(required=True)
|
device_group = test.add_mutually_exclusive_group(required=True)
|
||||||
device_group.add_argument(
|
device_group.add_argument(
|
||||||
"--connected", metavar="SERIAL", help="Run on a connected device. "
|
"--connected", metavar="SERIAL", help="Run on a connected device. "
|
||||||
|
@ -591,6 +599,13 @@ def parse_args():
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
install_signal_handler()
|
install_signal_handler()
|
||||||
|
|
||||||
|
# Under the buildbot, stdout is not a TTY, but we must still flush after
|
||||||
|
# every line to make sure our output appears in the correct order relative
|
||||||
|
# to the output of our subprocesses.
|
||||||
|
for stream in [sys.stdout, sys.stderr]:
|
||||||
|
stream.reconfigure(line_buffering=True)
|
||||||
|
|
||||||
context = parse_args()
|
context = parse_args()
|
||||||
dispatch = {"configure-build": configure_build_python,
|
dispatch = {"configure-build": configure_build_python,
|
||||||
"make-build": make_build_python,
|
"make-build": make_build_python,
|
||||||
|
|
Loading…
Reference in New Issue