Welcome to Airtest documentation!

Airtest

UI Automation Framework for Games and Apps


Airtest is a cross-platform UI automation framework for games and apps.

If you are new to Airtest, Airtest Project Homepage is a good place to get started.

The following documentation will guide you through main ideas of Airtest, as well as providing a API reference documentation.

Airtest

Cross-Platform UI Automation Framework for Games and Apps


Getting Started

  • Cross-Platform: Airtest automates games and apps on almost all platforms.
  • Write Once, Run Anywhere: Airtest provides cross-platform APIs, including app installation, simulated input, assertion and so forth. Airtest uses image recognition technology to locate UI elements, so that you can automate games and apps without injecting any code.
  • Fully Scalable: Airtest cases can be easily run on large device farms, using commandline or python API. HTML reports with detailed info and screen recording allow you to quickly locate failure points. NetEase builds [Airlab](https://airlab.163.com/) on top of Airtest Project.
  • AirtestIDE: AirtestIDE is an out of the box GUI tool that helps to create and run cases in a user-friendly way. AirtestIDE supports a complete automation workflow: create -> run -> report.

Get Started from Airtest Project Homepage

Supported Platforms
  • Android
  • iOS
  • Windows
  • Unity
  • Cocos2dx
  • Egret
  • WeChat

Read more

Installation

This section describes how to install Airtest python library. Download AirtestIDE from our homepage if you need to use the GUI tool.

System Requirements
  • Operating System:
    • Windows
    • MacOS X
    • Linux
  • Python2.7 & Python3.3+
Installing the python package

Airtest package can be installed directly from Pypi. Use pip to manage installation of all python dependencies and package itself.

pip install -U airtest

You can also install it from Git repository.

git clone https://github.com/AirtestProject/Airtest.git
pip install -e airtest

Use -e here to install airtest in develop mode since this repo is in rapid development. Then you can upgrade the repo with git pull later.

Documentation

You can find the complete Airtest documentation on readthedocs.

Example

Airtest provides simple APIs that are platform independent. This section describes how to create an automated case which does the following:

  1. connects to local android device with adb
  2. installs the apk application
  3. runs application and takes the screenshot
  4. performs several user operations (touch, swipe, keyevent)
  5. uninstalls application
from airtest.core.api import *

# connect an android phone with adb
init_device("Android")
# or use connect_device api
# connect_device("Android:///")

install("path/to/your/apk")
start_app("package_name_of_your_apk")
touch(Template("image_of_a_button.png"))
swipe(Template("slide_start.png"), Template("slide_end.png"))
assert_exists(Template("success.png"))
keyevent("BACK")
home()
uninstall("package_name_of_your_apk")

For more detailed info, please refer to Airtest Python API reference or take a look at API code

Basic Usage

Airtest aims at providing platform independent API, so that you can write automated cases once and run it on multiple devices and platforms.

  1. Using connect_device API you can connect to any android/iOS device or windows application.
  2. Then perform simulated input to automate your game or app.
  3. DO NOT forget to make assertions of the expected result.
Connect Device

Using connect_device API you can connect to any android/iOS device or windows application.

connect_device("platform://host:port/uuid?param=value&param2=value2")
  • platform: Android/iOS/Windows…
  • host: adb host for android, iproxy host for iOS, empty for other platforms
  • port: adb port for android, iproxy port for iOS, empty for other platforms
  • uuid: uuid for target device, e.g. serialno for Android, handle for Windows, uuid for iOS
  • param: device initialization configuration fields. e.g. cap_method/ori_method/…
  • value: device initialization configuration field values.

see also connect_device.

Connect android device
  1. Connect your android phone to your PC with usb
  2. Use adb devices to make sure the state is device
  3. Connect device in Airtest
  4. If you have multiple devices or even remote devices, use more params to specify the device
# connect an android phone with adb
init_device("Android")

# or use connect_device api with default params
connect_device("android:///")

# connect a remote device using custom params
connect_device("android://adbhost:adbport/1234566?cap_method=javacap&touch_method=adb")
Connect iOS device

Follow the instruction of iOS-Tagent to setup the environment.

# connect a local ios device
connect_device("ios:///")
Connect windows application
# connect local windows desktop
connect_device("Windows:///")

# connect local windows application
connect_device("Windows:///?title_re=unity.*")

Airtest uses pywinauto as Windows backend. For more window searching params, please see pywinauto documentation.

Simulate Input

Following APIs are fully supported:

  • touch
  • swipe
  • text
  • keyevent
  • snapshot
  • wait

More APIs are available, some of which may be platform specific, please see API reference for more information.

When using these general APIs, Airtest will automatically call the corresponding operations according to the current platform, such as the following code example:

from airtest.core.api import *  # import the general APIs such as touch/swipe/...

connect_device("Android:///")
touch((100, 100))

connect_device("Windows:///")
touch((100, 100))

Airtest also provides some platform-specific APIs for each platform, which can be queried in the module API of each platform:

>>> from airtest.core.api import *
>>> connect_device("Android:///")
>>> dev = device()  # get current device, which is an Android object
>>> print(type(dev))
<class 'airtest.core.android.android.Android'>
>>> dev.get_top_activity()  # use Android ADB to get the top activity
('com.google.android.apps.nexuslauncher', '.NexusLauncherActivity', '2720')
Make Assertion

Airtest provide some assert functions, including:

  • assert_exists
  • assert_not_exists
  • assert_equal
  • assert_not_equal

When assertion fails, it will raise AssertsionError. And you will see all assertions in the html report.

All assert statements can be found here: airtest.core.assertions

Running .air from CLI

Using AirtestIDE, you can easily create and author automated cases as .air directories. Airtest CLI provides the possibility to execute cases on different host machine and target device platforms without using AirtestIDE itself.

Connections to devices are specified by command line arguments, i.e. the code is platform independent and one automated case can be used for Android, iOS or Windows apps as well.

Following examples demonstrate the basic usage of airtest framework running from CLI. For a deeper understanding, try running provided automated cases: airtest/playground/test_blackjack.air

run automated case
# run automated cases and scenarios on various devices
> airtest run "path to your .air dir" --device Android:///
> airtest run "path to your .air dir" --device Android://adbhost:adbport/serialno
> airtest run "path to your .air dir" --device Windows:///?title_re=Unity.*
> airtest run "path to your .air dir" --device iOS:///
...
# show help
> airtest run -h
usage: airtest run [-h] [--device [DEVICE]] [--log [LOG]]
                   [--recording [RECORDING]]
                   script

positional arguments:
  script                air path

optional arguments:
  -h, --help            show this help message and exit
  --device [DEVICE]     connect dev by uri string, e.g. Android:///
  --log [LOG]           set log dir, default to be script dir
  --recording [RECORDING]
                      record screen when running
  --compress
                      set snapshot quality, 1-99
  --no-image [NO_IMAGE]
                      Do not save screenshots
generate html report
> airtest report "path to your .air dir"
log.html
> airtest report -h
usage: airtest report [-h] [--outfile OUTFILE] [--static_root STATIC_ROOT]
                      [--log_root LOG_ROOT] [--record RECORD [RECORD ...]]
                      [--export EXPORT] [--lang LANG]
                      script

positional arguments:
  script                script filepath

optional arguments:
  -h, --help            show this help message and exit
  --outfile OUTFILE     output html filepath, default to be log.html
  --static_root STATIC_ROOT
                        static files root dir
  --log_root LOG_ROOT   log & screen data root dir, logfile should be
                        log_root/log.txt
  --record RECORD [RECORD ...]
                        custom screen record file path
  --export EXPORT       export a portable report dir containing all resources
  --lang LANG           report language
get case info
# print case info in json if defined, including: author, title, desc
> python -m airtest info "path to your .air dir"
{"author": ..., "title": ..., "desc": ...}

Import from other .air

You can write some common used function in one .air script and import it from other scripts. Airtest provide using API to manage the context change including sys.path and Template search path.

from airtest.core.api import using
using("common.air")

from common import common_function

common_function()

airtest.core.api module

This module contains the Airtest Core APIs.

init_device(platform='Android', uuid=None, **kwargs)[source]

Initialize device if not yet, and set as current device.

Parameters:
  • platform – Android, IOS or Windows
  • uuid – uuid for target device, e.g. serialno for Android, handle for Windows, uuid for iOS
  • kwargs – Optional platform specific keyword args, e.g. cap_method=JAVACAP for Android
Returns:

device instance

Example:
>>> init_device(platform="Android",uuid="SJE5T17B17", cap_method="JAVACAP")
>>> init_device(platform="Windows",uuid="123456")
connect_device(uri)[source]

Initialize device with uri, and set as current device.

Parameters:

uri – an URI where to connect to device, e.g. android://adbhost:adbport/serialno?param=value&param2=value2

Returns:

device instance

Example:
>>> connect_device("Android:///")  # local adb device using default params
>>> # local device with serial number SJE5T17B17 and custom params
>>> connect_device("Android:///SJE5T17B17?cap_method=javacap&touch_method=adb")
>>> # remote device using custom params Android://adbhost:adbport/serialno
>>> connect_device("Android://127.0.0.1:5037/10.254.60.1:5555")
>>> connect_device("Windows:///")  # connect to the desktop
>>> connect_device("Windows:///123456")  # Connect to the window with handle 123456
>>> connect_device("Windows:///123456?foreground=False")  # Connect to the window without setting it foreground
>>> connect_device("iOS:///127.0.0.1:8100")  # iOS device
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100")  # iOS with mjpeg port
device()[source]

Return the current active device.

Returns:

current device instance

Example:
>>> dev = device()
>>> dev.touch((100, 100))
set_current(idx)[source]

Set current active device.

Parameters:

idx – uuid or index of initialized device instance

Raises:

IndexError – raised when device idx is not found

Returns:

None

Platforms:

Android, iOS, Windows

Example:
>>> # switch to the first phone currently connected
>>> set_current(0)
>>> # switch to the phone with serial number serialno1
>>> set_current("serialno1")
auto_setup(basedir=None, devices=None, logdir=None, project_root=None, compress=None)[source]

Auto setup running env and try connect android device if not device connected.

Parameters:
  • basedir – basedir of script, __file__ is also acceptable.
  • devices – connect_device uri in list.
  • logdir – log dir for script report, default is None for no log, set to True for <basedir>/log.
  • project_root – project root dir for using api.
  • compress – The compression rate of the screenshot image, integer in range [1, 99], default is 10
Example:
>>> auto_setup(__file__)
>>> auto_setup(__file__, devices=["Android://127.0.0.1:5037/SJE5T17B17"],
...             logdir=True, project_root=r"D:\test\logs", compress=90)
shell(cmd)[source]

Start remote shell in the target device and execute the command

Parameters:

cmd – command to be run on device, e.g. “ls /data/local/tmp”

Returns:

the output of the shell cmd

Platforms:

Android

Example:
>>> # Execute commands on the current device adb shell ls
>>> print(shell("ls"))
>>> # Execute adb instructions for specific devices
>>> dev = connect_device("Android:///device1")
>>> dev.shell("ls")
>>> # Switch to a device and execute the adb command
>>> set_current(0)
>>> shell("ls")
start_app(package, activity=None)[source]

Start the target application on device

Parameters:
  • package – name of the package to be started, e.g. “com.netease.my”
  • activity – the activity to start, default is None which means the main activity
Returns:

None

Platforms:

Android, iOS

Example:
>>> start_app("com.netease.cloudmusic")
>>> start_app("com.apple.mobilesafari")  # on iOS
stop_app(package)[source]

Stop the target application on device

Parameters:

package – name of the package to stop, see also start_app

Returns:

None

Platforms:

Android, iOS

Example:
>>> stop_app("com.netease.cloudmusic")
clear_app(package)[source]

Clear data of the target application on device

Parameters:

package – name of the package, see also start_app

Returns:

None

Platforms:

Android

Example:
>>> clear_app("com.netease.cloudmusic")
install(filepath, **kwargs)[source]

Install application on device

Parameters:
  • filepath – the path to file to be installed on target device
  • kwargs – platform specific kwargs, please refer to corresponding docs
Returns:

None

Platforms:

Android

Example:
>>> install(r"D:\demo\test.apk")
>>> # adb install -r -t D:\demo\test.apk
>>> install(r"D:\demo\test.apk", install_options=["-r", "-t"])
uninstall(package)[source]

Uninstall application on device

Parameters:

package – name of the package, see also start_app

Returns:

None

Platforms:

Android

Example:
>>> uninstall("com.netease.cloudmusic")
snapshot(filename=None, msg='', quality=None, max_size=None)[source]

Take the screenshot of the target device and save it to the file.

Parameters:
  • filename – name of the file where to save the screenshot. If the relative path is provided, the default location is ST.LOG_DIR
  • msg – short description for screenshot, it will be recorded in the report
  • quality – The image quality, integer in range [1, 99], default is 10
  • max_size – the maximum size of the picture, e.g 1200
Returns:

{“screen”: filename, “resolution”: resolution of the screen} or None

Platforms:

Android, iOS, Windows

Example:
>>> snapshot(msg="index")
>>> # save the screenshot to test.jpg
>>> snapshot(filename="test.png", msg="test")

The quality and size of the screenshot can be set:

>>> # Set the screenshot quality to 30
>>> ST.SNAPSHOT_QUALITY = 30
>>> # Set the screenshot size not to exceed 600*600
>>> # if not set, the default size is the original image size
>>> ST.IMAGE_MAXSIZE = 600
>>> # The quality of the screenshot is 30, and the size does not exceed 600*600
>>> touch((100, 100))
>>> # The quality of the screenshot of this sentence is 90
>>> snapshot(filename="test.png", msg="test", quality=90)
>>> # The quality of the screenshot is 90, and the size does not exceed 1200*1200
>>> snapshot(filename="test2.png", msg="test", quality=90, max_size=1200)
wake()[source]

Wake up and unlock the target device

Returns:

None

Platforms:

Android

Example:
>>> wake()

Note

Might not work on some models

home()[source]

Return to the home screen of the target device.

Returns:

None

Platforms:

Android, iOS

Example:
>>> home()
touch(v, times=1, **kwargs)[source]

Perform the touch action on the device screen

Parameters:
  • v – target to touch, either a Template instance or absolute coordinates (x, y)
  • times – how many touches to be performed
  • kwargs – platform specific kwargs, please refer to corresponding docs
Returns:

finial position to be clicked, e.g. (100, 100)

Platforms:

Android, Windows, iOS

Example:

Click absolute coordinates:

>>> touch((100, 100))

Click the center of the picture(Template object):

>>> touch(Template(r"tpl1606730579419.png", target_pos=5))

Click 2 times:

>>> touch((100, 100), times=2)

Under Android and Windows platforms, you can set the click duration:

>>> touch((100, 100), duration=2)

Right click(Windows):

>>> touch((100, 100), right_click=True)
click(v, times=1, **kwargs)

Perform the touch action on the device screen

Parameters:
  • v – target to touch, either a Template instance or absolute coordinates (x, y)
  • times – how many touches to be performed
  • kwargs – platform specific kwargs, please refer to corresponding docs
Returns:

finial position to be clicked, e.g. (100, 100)

Platforms:

Android, Windows, iOS

Example:

Click absolute coordinates:

>>> touch((100, 100))

Click the center of the picture(Template object):

>>> touch(Template(r"tpl1606730579419.png", target_pos=5))

Click 2 times:

>>> touch((100, 100), times=2)

Under Android and Windows platforms, you can set the click duration:

>>> touch((100, 100), duration=2)

Right click(Windows):

>>> touch((100, 100), right_click=True)
double_click(v)[source]

Perform double click

Parameters:

v – target to touch, either a Template instance or absolute coordinates (x, y)

Returns:

finial position to be clicked

Example:
>>> double_click((100, 100))
>>> double_click(Template(r"tpl1606730579419.png"))
swipe(v1, v2=None, vector=None, **kwargs)[source]

Perform the swipe action on the device screen.

There are two ways of assigning the parameters
  • swipe(v1, v2=Template(...)) # swipe from v1 to v2
  • swipe(v1, vector=(x, y)) # swipe starts at v1 and moves along the vector.
Parameters:
  • v1 – the start point of swipe, either a Template instance or absolute coordinates (x, y)
  • v2 – the end point of swipe, either a Template instance or absolute coordinates (x, y)
  • vector – a vector coordinates of swipe action, either absolute coordinates (x, y) or percentage of screen e.g.(0.5, 0.5)
  • **kwargs

    platform specific kwargs, please refer to corresponding docs

Raises:

Exception – general exception when not enough parameters to perform swap action have been provided

Returns:

Origin position and target position

Platforms:

Android, Windows, iOS

Example:
>>> swipe(Template(r"tpl1606814865574.png"), vector=[-0.0316, -0.3311])
>>> swipe((100, 100), (200, 200))

Custom swiping duration and number of steps(Android and iOS):

>>> # swiping lasts for 1 second, divided into 6 steps
>>> swipe((100, 100), (200, 200), duration=1, steps=6)
pinch(in_or_out='in', center=None, percent=0.5)[source]

Perform the pinch action on the device screen

Parameters:
  • in_or_out – pinch in or pinch out, enum in [“in”, “out”]
  • center – center of pinch action, default as None which is the center of the screen
  • percent – percentage of the screen of pinch action, default is 0.5
Returns:

None

Platforms:

Android

Example:

Pinch in the center of the screen with two fingers:

>>> pinch()

Take (100,100) as the center and slide out with two fingers:

>>> pinch('out', center=(100, 100))
keyevent(keyname, **kwargs)[source]

Perform key event on the device

Parameters:
  • keyname – platform specific key name
  • **kwargs

    platform specific kwargs, please refer to corresponding docs

Returns:

None

Platforms:

Android, Windows, iOS

Example:
  • Android: it is equivalent to executing adb shell input keyevent KEYNAME
>>> keyevent("HOME")
>>> # The constant corresponding to the home key is 3
>>> keyevent("3")  # same as keyevent("HOME")
>>> keyevent("BACK")
>>> keyevent("KEYCODE_DEL")

See also

Module airtest.core.android.adb.ADB.keyevent

Equivalent to calling the android.adb.keyevent()

Android Keyevent

Documentation for more Android.KeyEvent

  • Windows: Use pywinauto.keyboard module for key input:
>>> keyevent("{DEL}")
>>> keyevent("%{F4}")  # close an active window with Alt+F4

See also

Module airtest.core.win.win.Windows.keyevent

pywinauto.keyboard

Documentation for pywinauto.keyboard

  • iOS: Only supports home/volumeUp/volumeDown:
>>> keyevent("HOME")
>>> keyevent("volumeUp")
text(text, enter=True, **kwargs)[source]

Input text on the target device. Text input widget must be active first.

Parameters:
  • text – text to input, unicode is supported
  • enter – input Enter keyevent after text input, default is True
Returns:

None

Platforms:

Android, Windows, iOS

Example:
>>> text("test")
>>> text("test", enter=False)

On Android, sometimes you need to click the search button after typing:

>>> text("test", search=True)

See also

Module airtest.core.android.ime.YosemiteIme.code

If you want to enter other keys on the keyboard, you can use the interface:

>>> text("test")
>>> device().yosemite_ime.code("3")  # 3 = IME_ACTION_SEARCH

Ref: Editor Action Code

sleep(secs=1.0)[source]

Set the sleep interval. It will be recorded in the report

Parameters:

secs – seconds to sleep

Returns:

None

Platforms:

Android, Windows, iOS

Example:
>>> sleep(1)
wait(v, timeout=None, interval=0.5, intervalfunc=None)[source]

Wait to match the Template on the device screen

Parameters:
  • v – target object to wait for, Template instance
  • timeout – time interval to wait for the match, default is None which is ST.FIND_TIMEOUT
  • interval – time interval in seconds to attempt to find a match
  • intervalfunc – called after each unsuccessful attempt to find the corresponding match
Raises:

TargetNotFoundError – raised if target is not found after the time limit expired

Returns:

coordinates of the matched target

Platforms:

Android, Windows, iOS

Example:
>>> wait(Template(r"tpl1606821804906.png"))  # timeout after ST.FIND_TIMEOUT
>>> # find Template every 3 seconds, timeout after 120 seconds
>>> wait(Template(r"tpl1606821804906.png"), timeout=120, interval=3)

You can specify a callback function every time the search target fails:

>>> def notfound():
>>>     print("No target found")
>>> wait(Template(r"tpl1607510661400.png"), intervalfunc=notfound)
exists(v)[source]

Check whether given target exists on device screen

Parameters:

v – target to be checked

Returns:

False if target is not found, otherwise returns the coordinates of the target

Platforms:

Android, Windows, iOS

Example:
>>> if exists(Template(r"tpl1606822430589.png")):
>>>     touch(Template(r"tpl1606822430589.png"))

Since exists() will return the coordinates, we can directly click on this return value to reduce one image search:

>>> pos = exists(Template(r"tpl1606822430589.png"))
>>> if pos:
>>>     touch(pos)
find_all(v)[source]

Find all occurrences of the target on the device screen and return their coordinates

Parameters:

v – target to find

Returns:

list of results, [{‘result’: (x, y), ‘rectangle’: ( (left_top, left_bottom, right_bottom, right_top) ), ‘confidence’: 0.9}, …]

Platforms:

Android, Windows, iOS

Example:
>>> find_all(Template(r"tpl1607511235111.png"))
[{'result': (218, 468), 'rectangle': ((149, 440), (149, 496), (288, 496), (288, 440)),
'confidence': 0.9999996423721313}]

Assertions in airtest

All assert statements can be found here: airtest.core.assertions

airtest.core.android package

This package provide Android Device Class.

For the interface provided for the Android platform, please refer to: airtest.core.android.Android class

Subpackages

airtest.core.android.touch_methods package
Submodules
airtest.core.android.touch_methods.base_touch module
retry_when_connection_error(func)[source]
class BaseTouch(adb, backend=False, size_info=None, input_event=None, *args, **kwargs)[source]

Bases: object

A super class for Minitouch or Maxtouch

install_and_setup()[source]

Install and setup airtest touch

Returns:None
uninstall()[source]

Uninstall airtest touch

Returns:None
install()[source]

Install airtest touch

Returns:None
setup_server()[source]

Setip touch server and adb forward

Returns:server process
safe_send(data)[source]

Send data to client

Parameters:data – data to send
Raises:Exception – when data cannot be sent
Returns:None
setup_client_backend()[source]

Setup backend client thread as daemon

Returns:None
setup_client()[source]

Setup client

Returns:None
teardown()[source]

Stop the server and client

Returns:None
transform_xy(x, y)[source]

Transform coordinates (x, y) according to the device display

Parameters:
  • x – coordinate x
  • y – coordinate y
Returns:

transformed coordinates (x, y)

perform(motion_events, interval=0.01)[source]

Perform a sequence of motion events including: UpEvent, DownEvent, MoveEvent, SleepEvent

Parameters:
  • motion_events – a list of MotionEvent instances
  • interval – minimum interval between events
Returns:

None

touch(tuple_xy, duration=0.01)[source]

Perform touch event

minitouch protocol example:

d 0 10 10 50
c
<wait in your own code>
u 0
c
Parameters:
  • tuple_xy – coordinates (x, y)
  • duration – time interval for touch event, default is 0.01
Returns:

None

swipe_along(coordinates_list, duration=0.8, steps=5)[source]

Perform swipe event across multiple points in sequence.

Parameters:
  • coordinates_list – list of coordinates: [(x1, y1), (x2, y2), (x3, y3)]
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
Returns:

None

swipe(tuple_from_xy, tuple_to_xy, duration=0.8, steps=5)[source]

Perform swipe event.

Parameters:
  • tuple_from_xy – start point
  • tuple_to_xy – end point
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
Returns:

None

two_finger_swipe(tuple_from_xy, tuple_to_xy, duration=0.8, steps=5, offset=(0, 50))[source]

Perform two finger swipe action

minitouch protocol example:

d 0 0 0 50
d 1 1 0 50
c
m 0 20 0 50
m 1 21 0 50
c
m 0 40 0 50
m 1 41 0 50
c
m 0 60 0 50
m 1 61 0 50
c
m 0 80 0 50
m 1 81 0 50
c
m 0 100 0 50
m 1 101 0 50
c
u 0
u 1
c
Parameters:
  • tuple_from_xy – start point
  • tuple_to_xy – end point
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
  • offset – coordinate offset of the second finger, default is (0, 50)
Returns:

None

pinch(center=None, percent=0.5, duration=0.5, steps=5, in_or_out='in')[source]

Perform pinch action

minitouch protocol example:

d 0 0 100 50
d 1 100 0 50
c
m 0 10 90 50
m 1 90 10 50
c
m 0 20 80 50
m 1 80 20 50
c
m 0 20 80 50
m 1 80 20 50
c
m 0 30 70 50
m 1 70 30 50
c
m 0 40 60 50
m 1 60 40 50
c
m 0 50 50 50
m 1 50 50 50
c
u 0
u 1
c
Parameters:
  • center – the center point of the pinch operation
  • percent – pinch distance to half of screen, default is 0.5
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
  • in_or_out – pinch in or pinch out, default is ‘in’
Returns:

None

Raises:

TypeError – An error occurred when center is not a list/tuple or None

operate(args)[source]

Perform down, up and move actions

Parameters:args

action arguments, dictionary containing type and x, y coordinates, e.g.:

{
"type" : "down",
"x" : 10,
"y" : 10
}
Raises:RuntimeError – is invalid arguments are provided
Returns:None
class MotionEvent[source]

Bases: object

Motion Event to be performed by Minitouch/Maxtouch

getcmd(transform=None)[source]
class DownEvent(coordinates, contact=0, pressure=50)[source]

Bases: airtest.core.android.touch_methods.base_touch.MotionEvent

getcmd(transform=None)[source]
class UpEvent(contact=0)[source]

Bases: airtest.core.android.touch_methods.base_touch.MotionEvent

getcmd(transform=None)[source]
class MoveEvent(coordinates, contact=0, pressure=50)[source]

Bases: airtest.core.android.touch_methods.base_touch.MotionEvent

getcmd(transform=None)[source]
class SleepEvent(seconds)[source]

Bases: airtest.core.android.touch_methods.base_touch.MotionEvent

getcmd(transform=None)[source]
airtest.core.android.touch_methods.maxtouch module
class Maxtouch(adb, backend=False, size_info=None, input_event=None)[source]

Bases: airtest.core.android.touch_methods.base_touch.BaseTouch

install()[source]

Install maxtouch

Returns:None
uninstall()[source]

Uninstall maxtouch

Returns:None
setup_server()[source]

Setup maxtouch server and adb forward

Returns:server process
setup_client()[source]

Setup client

Returns:None
transform_xy(x, y)[source]

Normalized coordinates (x, y)

Parameters:
  • x – coordinate x
  • y – coordinate y
Returns:

transformed coordinates (x, y)

teardown()[source]

Stop the server and client

Returns:None
airtest.core.android.touch_methods.minitouch module
class Minitouch(adb, backend=False, size_info=None, input_event=None)[source]

Bases: airtest.core.android.touch_methods.base_touch.BaseTouch

install()[source]

Install minitouch

Returns:None
uninstall()[source]

Uninstall minitouch

Returns:None
setup_server()[source]

Setup minitouch server and adb forward

Returns:server process
setup_client()[source]

Setup client in following steps:

1. connect to server
2. receive the header
    v <version>
    ^ <max-contacts> <max-x> <max-y> <max-pressure>
    $ <pid>
3. prepare to send
Returns:None
transform_xy(x, y)[source]

Transform coordinates (x, y) according to the device display

Parameters:
  • x – coordinate x
  • y – coordinate y
Returns:

transformed coordinates (x, y)

teardown()[source]

Stop the server and client

Returns:None
airtest.core.android.touch_methods.touch_proxy module
class TouchProxy(touch_method)[source]

Bases: object

Perform touch operation according to the specified method

TOUCH_METHODS = {'MAXTOUCH': <class 'airtest.core.android.touch_methods.touch_proxy.MaxtouchImplementation'>, 'MINITOUCH': <class 'airtest.core.android.touch_methods.touch_proxy.MinitouchImplementation'>}
classmethod check_touch(touch_impl)[source]
classmethod auto_setup(adb, default_method=None, ori_transformer=None, size_info=None, input_event=None)[source]
Parameters:
  • adbairtest.core.android.adb.ADB
  • default_method – The default click method, such as “MINITOUCH”
  • ori_transformer – dev._touch_point_by_orientation
  • size_info – the result of dev.get_display_info()
  • input_event – dev.input_event
  • *args
  • **kwargs

Returns: TouchProxy object

Examples

>>> dev = Android()
>>> touch_proxy = TouchProxy.auto_setup(dev.adb, ori_transformer=dev._touch_point_by_orientation)
>>> touch_proxy.touch((100, 100))
register_touch(cls)[source]
class AdbTouchImplementation(base_touch)[source]

Bases: object

METHOD_NAME = 'ADBTOUCH'
touch(pos, duration=0.01)[source]
swipe(p1, p2, duration=0.5, *args, **kwargs)[source]
class MinitouchImplementation(minitouch, ori_transformer)[source]

Bases: airtest.core.android.touch_methods.touch_proxy.AdbTouchImplementation

METHOD_NAME = 'MINITOUCH'
METHOD_CLASS

alias of airtest.core.android.touch_methods.minitouch.Minitouch

touch(pos, duration=0.01)[source]
swipe(p1, p2, duration=0.5, steps=5, fingers=1)[source]
pinch(center=None, percent=0.5, duration=0.5, steps=5, in_or_out='in')[source]
swipe_along(coordinates_list, duration=0.8, steps=5)[source]
two_finger_swipe(tuple_from_xy, tuple_to_xy, duration=0.8, steps=5, offset=(0, 50))[source]
perform(motion_events, interval=0.01)[source]
class MaxtouchImplementation(maxtouch, ori_transformer)[source]

Bases: airtest.core.android.touch_methods.touch_proxy.MinitouchImplementation

METHOD_NAME = 'MAXTOUCH'
METHOD_CLASS

alias of airtest.core.android.touch_methods.maxtouch.Maxtouch

perform(motion_events, interval=0.01)[source]
airtest.core.android.cap_methods package
Submodules
airtest.core.android.cap_methods.adbcap module
class AdbCap(adb, *args, **kwargs)[source]

Bases: airtest.core.android.cap_methods.base_cap.BaseCap

get_frame_from_stream()[source]

Get a frame of the current screen from the mobile screen stream

从手机画面流中,获取一张当前屏幕截图

Returns: frame_data

snapshot(ensure_orientation=True)[source]

Take a screenshot and convert it into a cv2 image object

获取一张屏幕截图,并转化成cv2的图像对象

Returns: numpy.ndarray

airtest.core.android.cap_methods.base_cap module
class BaseCap(adb, *args, **kwargs)[source]

Bases: object

Base class for all screenshot methods 所有屏幕截图方法的基类

get_frame_from_stream()[source]

Get a frame of the current screen from the mobile screen stream

从手机画面流中,获取一张当前屏幕截图

Returns: frame_data

get_frame()[source]
teardown_stream()[source]
snapshot(ensure_orientation=True, *args, **kwargs)[source]

Take a screenshot and convert it into a cv2 image object

获取一张屏幕截图,并转化成cv2的图像对象

Returns: numpy.ndarray

airtest.core.android.cap_methods.javacap module
class Javacap(adb, *args, **kwargs)[source]

Bases: airtest.core.android.yosemite.Yosemite, airtest.core.android.cap_methods.base_cap.BaseCap

This is another screencap class, it is slower in performance than minicap, but it provides the better compatibility

APP_PKG = 'com.netease.nie.yosemite'
SCREENCAP_SERVICE = 'com.netease.nie.yosemite.Capture'
RECVTIMEOUT = None
get_frames()[source]

Get the screen frames

Returns:None
get_frame_from_stream()[source]

Get frame from the stream

Returns:frame
teardown_stream()[source]

End stream

Returns:None
airtest.core.android.cap_methods.minicap module
retry_when_socket_error(func)[source]
class Minicap(adb, projection=None, rotation_watcher=None, display_id=None, ori_function=None)[source]

Bases: airtest.core.android.cap_methods.base_cap.BaseCap

super fast android screenshot method from stf minicap.

reference https://github.com/openstf/minicap

VERSION = 5
RECVTIMEOUT = 3
CMD = 'LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap'
install_or_upgrade()[source]

Install or upgrade minicap

Returns:None
uninstall()[source]

Uninstall minicap

Returns:None
install()[source]

Install minicap

Reference: https://github.com/openstf/minicap/blob/master/run.sh

Returns:None
get_frame(projection=None)[source]
Get the single frame from minicap -s, this method slower than get_frames
1. shell cmd 1. remove log info 1.
Args:
projection: screenshot projection, default is None which means using self.projection
Returns:
jpg data
get_stream(lazy=True)[source]

Get stream, it uses `adb forward`and socket communication. Use minicap ``lazy``mode (provided by gzmaruijie) for long connections - returns one latest frame from the server

Parameters:lazy – True or False

Returns:

get_frame_from_stream()[source]

Get one frame from minicap stream

Returns:frame
snapshot(ensure_orientation=True, projection=None)[source]
Parameters:
  • ensure_orientation – True or False whether to keep the orientation same as display
  • projection – the size of the desired projection, (width, height)

Returns:

update_rotation(rotation)[source]

Update rotation and reset the backend stream generator

Parameters:rotation – rotation input
Returns:None
teardown_stream()[source]

End the stream

Returns:None
airtest.core.android.cap_methods.screen_proxy module
class ScreenProxy(screen_method)[source]

Bases: object

Perform screen operation according to the specified method

SCREEN_METHODS = {'ADBCAP': <class 'airtest.core.android.cap_methods.adbcap.AdbCap'>, 'JAVACAP': <class 'airtest.core.android.cap_methods.javacap.Javacap'>, 'MINICAP': <class 'airtest.core.android.cap_methods.minicap.Minicap'>}
classmethod register_method(name, method_class)[source]
classmethod check_frame(cap_method)[source]

Test whether a frame of image can be obtained correctly

测试能否正确获取一帧图像

Parameters:cap_methodairtest.core.android.cap_methods.base_cap.BaseCap

Returns:

classmethod auto_setup(adb, default_method=None, *args, **kwargs)[source]

In order of priority, try to initialize all registered screenshot methods, select an available method to return

按优先顺序,尝试初始化注册过的所有屏幕截图方法,选择一个可用方法返回

Custom method 自定义方法 > MINICAP > JAVACAP > ADBCAP

Parameters:

Returns: ScreenProxy object

Examples

>>> dev = Android()
>>> screen_proxy = ScreenProxy.auto_setup(dev.adb, rotation_watcher=dev.rotation_watcher)
>>> screen_proxy.get_frame_from_stream()
>>> screen_proxy.teardown_stream()
register_screen()[source]

Submodules

airtest.core.android.adb module
class ADB(serialno=None, adb_path=None, server_addr=None, display_id=None, input_event=None)[source]

Bases: object

adb client object class

status_device = 'device'
status_offline = 'offline'
SHELL_ENCODING = 'utf-8'
static builtin_adb_path()[source]

Return built-in adb executable path

Returns:adb executable path
start_server()[source]

Perform adb start-server command to start the adb server

Returns:None
kill_server()[source]

Perform adb kill-server command to kill the adb server

Returns:None
version()[source]

Perform adb version command and return the command output

Returns:command output
start_cmd(cmds, device=True)[source]

Start a subprocess with adb command(s)

Parameters:
  • cmds – command(s) to be run
  • device – if True, the device serial number must be specified by -s serialno argument
Raises:

RuntimeError – if device is True and serialno is not specified

Returns:

a subprocess

cmd(cmds, device=True, ensure_unicode=True, timeout=None)[source]

Run the adb command(s) in subprocess and return the standard output

Parameters:
  • cmds – command(s) to be run
  • device – if True, the device serial number must be specified by -s serialno argument
  • ensure_unicode – encode/decode unicode of standard outputs (stdout, stderr)
  • timeout – timeout in seconds
Raises:
  • DeviceConnectionError – if any error occurs when connecting the device
  • AdbError – if any other adb error occurs
Returns:

command(s) standard output (stdout)

close_proc_pipe(proc)[source]

close stdin/stdout/stderr of subprocess.Popen.

devices(state=None)[source]

Perform adb devices command and return the list of adb devices

Parameters:state – optional parameter to filter devices in specific state
Returns:list od adb devices
connect(force=False)[source]

Perform adb connect command, remote devices are preferred to connect first

Parameters:force – force connection, default is False
Returns:None
disconnect()[source]

Perform adb disconnect command

Returns:None
get_status()[source]

Perform adb get-state and return the device status

Raises:AdbError – if status cannot be obtained from the device
Returns:None if status is not found, otherwise return the standard output from adb get-state command
wait_for_device(timeout=5)[source]

Perform adb wait-for-device command

Parameters:timeout – time interval in seconds to wait for device
Raises:DeviceConnectionError – if device is not available after timeout
Returns:None
start_shell(cmds)[source]

Handle adb shell command(s)

Parameters:cmds – adb shell command(s)
Returns:None
raw_shell(cmds, ensure_unicode=True)[source]

Handle adb shell command(s) with unicode support

Parameters:
  • cmds – adb shell command(s)
  • ensure_unicode – decode/encode unicode True or False, default is True
Returns:

command(s) output

shell(cmd)[source]

Run the adb shell command on the device

Parameters:cmd – a command to be run
Raises:AdbShellError – if command return value is non-zero or if any other AdbError occurred
Returns:command output
keyevent(keyname)[source]

Perform adb shell input keyevent command on the device

Parameters:keyname – key event name
Returns:None
getprop(key, strip=True)[source]

Perform adb shell getprop on the device

Parameters:
  • key – key value for property
  • strip – True or False to strip the return carriage and line break from returned string
Returns:

propery value

sdk_version
push(local, remote)[source]

Perform adb push command

Note

If there is a space (or special symbol) in the file name, it will be forced to add escape characters, and the new file name will be added with quotation marks and returned as the return value

注意:文件名中如果带有空格(或特殊符号),将会被强制增加转义符,并将新的文件名添加引号,作为返回值返回

Parameters:
  • local – local file to be copied to the device
  • remote – destination on the device where the file will be copied
Returns:

The file path saved in the phone may be enclosed in quotation marks, eg. ‘“testfile.txt”’

Examples

>>> adb = device().adb
>>> adb.push("test.txt", "/data/local/tmp")
>>> new_name = adb.push("test space.txt", "/data/local/tmp")  # test the space in file name
>>> print(new_name)
"/data/local/tmp/test\ space.txt"
>>> adb.shell("rm " + new_name)
pull(remote, local)[source]

Perform adb pull command

Parameters:
  • remote – remote file to be downloaded from the device
  • local – local destination where the file will be downloaded from the device

Note

If <=PY3, the path in Windows cannot be the root directory, and cannot contain symbols such as /g in the path 注意:如果低于PY3,windows中路径不能为根目录,并且不能包含/g等符号在路径里

Returns:None
forward(local, remote, no_rebind=True)[source]

Perform adb forward command

Parameters:
  • local – local tcp port to be forwarded
  • remote – tcp port of the device where the local tcp port will be forwarded
  • no_rebind – True or False
Returns:

None

get_forwards()[source]

Perform `adb forward –list`command

Yields:serial number, local tcp port, remote tcp port
Returns:None
classmethod get_available_forward_local()[source]

Generate a pseudo random number between 11111 and 20000 that will be used as local forward port

Returns:integer between 11111 and 20000

Note

use forward –no-rebind to check if port is available

setup_forward(**kwargs)
remove_forward(local=None)[source]

Perform adb forward –remove command

Parameters:local – local tcp port
Returns:None
install_app(filepath, replace=False, install_options=None)[source]

Perform adb install command

Parameters:
  • filepath – full path to file to be installed on the device
  • replace

    force to replace existing application, default is False

    e.g.[“-t”, # allow test packages
    ”-l”, # forward lock application, “-s”, # install application on sdcard, “-d”, # allow version code downgrade (debuggable packages only) “-g”, # grant all runtime permissions

    ]

Returns:

command output

install_multiple_app(filepath, replace=False, install_options=None)[source]

Perform adb install-multiple command

Parameters:
  • filepath – full path to file to be installed on the device
  • replace – force to replace existing application, default is False
  • install_options

    list of options e.g.[“-t”, # allow test packages

    ”-l”, # forward lock application, “-s”, # install application on sdcard, “-d”, # allow version code downgrade (debuggable packages only) “-g”, # grant all runtime permissions “-p”, # partial application install (install-multiple only)

    ]

Returns:

command output

pm_install(filepath, replace=False, install_options=None)[source]

Perform adb push and adb install commands

Note

This is more reliable and recommended way of installing .apk files

Parameters:
  • filepath – full path to file to be installed on the device
  • replace – force to replace existing application, default is False
  • install_options

    list of options e.g.[“-t”, # allow test packages

    ”-l”, # forward lock application, “-s”, # install application on sdcard, “-d”, # allow version code downgrade (debuggable packages only) “-g”, # grant all runtime permissions

    ]

Returns:

None

uninstall_app(package)[source]

Perform adb uninstall command :param package: package name to be uninstalled from the device

Returns:command output
pm_uninstall(package, keepdata=False)[source]

Perform adb uninstall command and delete all related application data

Parameters:
  • package – package name to be uninstalled from the device
  • keepdata – True or False, keep application data after removing the app from the device
Returns:

command output

snapshot()[source]

Take the screenshot of the device display

Returns:command output (stdout)
touch(tuple_xy)[source]

Perform user input (touchscreen) on given coordinates

Parameters:tuple_xy – coordinates (x, y)
Returns:None
swipe(tuple_x0y0, tuple_x1y1, duration=500)[source]

Perform user input (swipe screen) from start point (x,y) to end point (x,y)

Parameters:
  • tuple_x0y0 – start point coordinates (x, y)
  • tuple_x1y1 – end point coordinates (x, y)
  • duration – time interval for action, default 500
Raises:

AirtestError – if SDK version is not supported

Returns:

None

logcat(grep_str='', extra_args='', read_timeout=10)[source]

Perform adb shell logcat command and search for given patterns

Parameters:
  • grep_str – pattern to filter from the logcat output
  • extra_args – additional logcat arguments
  • read_timeout – time interval to read the logcat, default is 10
Yields:

logcat lines containing filtered patterns

Returns:

None

exists_file(filepath)[source]

Check if the file exits on the device

Parameters:filepath – path to the file
Returns:True or False if file found or not
file_size(filepath)[source]

Get the file size

Parameters:filepath – path to the file
Returns:The file size
Raises:AdbShellError if no such file
line_breaker

Set carriage return and line break property for various platforms and SDK versions

Returns:carriage return and line break string
display_info

Set device display properties (orientation, rotation and max values for x and y coordinates)

Notes: if there is a lock screen detected, the function tries to unlock the device first

Returns:device screen properties
get_display_info()[source]

Get information about device physical display (orientation, rotation and max values for x and y coordinates)

Returns:device screen properties e.g {
’width’: 1440, ‘height’: 2960, ‘density’: 4.0, ‘orientation’: 3, ‘rotation’: 270, ‘max_x’: 4095, ‘max_y’: 4095

}

getMaxXY()[source]

Get device display maximum values for x and y coordinates

Returns:max x and max y coordinates
getRestrictedScreen()[source]

Get value for mRestrictedScreen (without black border / virtual keyboard)`

Returns:screen resolution mRestrictedScreen value as tuple (x, y)
getPhysicalDisplayInfo()[source]

Get value for display dimension and density from mPhysicalDisplayInfo value obtained from dumpsys command.

Returns:physical display info for dimension and density
getDisplayOrientation()[source]

Another way to get the display orientation, this works well for older devices (SDK version 15)

Returns:display orientation information
update_cur_display(display_info)[source]

Some phones support resolution modification, try to get the modified resolution from dumpsys adb shell dumpsys window displays | find “cur=”

本方法虽然可以更好地获取到部分修改过分辨率的手机信息 但是会因为cur=(d+)x(d+)的数值在不同设备上width和height的顺序可能不同,导致横竖屏识别出现问题 airtest不再使用本方法作为通用的屏幕尺寸获取方法,但依然可用于部分设备获取当前被修改过的分辨率

Examples

>>> # 部分三星和华为设备,若分辨率没有指定为最高,可能会导致点击偏移,可以用这个方式强制修改:
>>> # For some Samsung and Huawei devices, if the resolution is not specified as the highest,
>>> # it may cause click offset, which can be modified in this way:
>>> dev = device()
>>> info = dev.display_info
>>> info2 = dev.adb.update_cur_display(info)
>>> dev.display_info.update(info2)
Parameters:display_info – the return of self.getPhysicalDisplayInfo()
Returns:display_info
get_top_activity()[source]

Perform adb shell dumpsys activity top command search for the top activity

Raises:AirtestError – if top activity cannot be obtained
Returns:(package_name, activity_name, pid)
Return type:top activity as a tuple
is_keyboard_shown()[source]

Perform adb shell dumpsys input_method command and search for information if keyboard is shown

Returns:True or False whether the keyboard is shown or not
is_screenon()[source]

Perform adb shell dumpsys window policy command and search for information if screen is turned on or off

Raises:AirtestError – if screen state can’t be detected
Returns:True or False whether the screen is turned on or off
is_locked()[source]

Perform adb shell dumpsys window policy command and search for information if screen is locked or not

Raises:AirtestError – if lock screen can’t be detected
Returns:True or False whether the screen is locked or not
unlock()[source]

Perform adb shell input keyevent MENU and adb shell input keyevent BACK commands to attempt to unlock the screen

Returns:None

Warning

Might not work on all devices

get_package_version(package)[source]

Perform adb shell dumpsys package and search for information about given package version

Parameters:package – package name
Returns:None if no info has been found, otherwise package version
list_app(third_only=False)[source]
Perform adb shell pm list packages to print all packages, optionally only
those whose package name contains the text in FILTER.
Options
-f: see their associated file -d: filter to only show disabled packages -e: filter to only show enabled packages -s: filter to only show system packages -3: filter to only show third party packages -i: see the installer for the packages -u: also include uninstalled packages
Parameters:third_only – print only third party packages
Returns:list of packages
path_app(package)[source]

Perform adb shell pm path command to print the path to the package

Parameters:

package – package name

Raises:
  • AdbShellError – if any adb error occurs
  • AirtestError – if package is not found on the device
Returns:

path to the package

check_app(package)[source]

Perform adb shell dumpsys package command and check if package exists on the device

Parameters:package – package name
Raises:AirtestError – if package is not found
Returns:True if package has been found
start_app(package, activity=None)[source]

Perform adb shell monkey commands to start the application, if activity argument is None, then adb shell am start command is used.

Parameters:
  • package – package name
  • activity – activity name
Returns:

None

start_app_timing(package, activity)[source]

Start the application and activity, and measure time

Parameters:
  • package – package name
  • activity – activity name
Returns:

app launch time

stop_app(package)[source]

Perform adb shell am force-stop command to force stop the application

Parameters:package – package name
Returns:None
clear_app(package)[source]

Perform adb shell pm clear command to clear all application data

Parameters:package – package name
Returns:None
text(content)[source]

Use adb shell input for text input

Parameters:content – text to input
Returns:None

Examples

>>> dev = connect_device("Android:///")
>>> dev.text("Hello World")
>>> dev.text("test123")
get_ip_address()[source]

Perform several set of commands to obtain the IP address.

  • adb shell netcfg | grep wlan0
  • adb shell ifconfig
  • adb getprop dhcp.wlan0.ipaddress
Returns:None if no IP address has been found, otherwise return the IP address
get_gateway_address()[source]
Perform several set of commands to obtain the gateway address.
  • adb getprop dhcp.wlan0.gateway
  • adb shell netcfg | grep wlan0
Returns:None if no gateway address has been found, otherwise return the gateway address
get_memory()[source]
get_storage()[source]
get_cpuinfo()[source]
get_cpufreq()[source]
get_cpuabi()[source]
get_gpu()[source]
get_model()[source]
get_manufacturer()[source]
get_device_info()[source]

Get android device information, including: memory/storage/display/cpu/gpu/model/manufacturer…

Returns:Dict of info
get_display_of_all_screen(info, package=None)[source]

Perform adb shell dumpsys window windows commands to get window display of application.

Parameters:
  • info – device screen properties
  • package – package name, default to the package of top activity
Returns:

None if adb command failed to run, otherwise return device screen properties(portrait mode) eg. (offset_x, offset_y, screen_width, screen_height)

cleanup_adb_forward()[source]
airtest.core.android.android module
class Android(serialno=None, host=None, cap_method='MINICAP', touch_method='MINITOUCH', ime_method='YOSEMITEIME', ori_method='MINICAPORI', display_id=None, input_event=None)[source]

Bases: airtest.core.device.Device

Android Device Class

touch_proxy

Perform touch operation according to self.touch_method

Module: airtest.core.android.touch_methods.touch_proxy.TouchProxy

Returns:TouchProxy

Examples

>>> dev = Android()
>>> dev.touch_proxy.touch((100, 100))  # If the device uses minitouch, it is the same as dev.minitouch.touch
>>> dev.touch_proxy.swipe_along([(0,0), (100, 100)])
touch_method

In order to be compatible with the previous dev.touch_method

为了兼容以前的`dev.touch_method`

Returns:“MINITOUCH” or “MAXTOUCH”

Examples

>>> dev = Android()
>>> print(dev.touch_method)  # "MINITOUCH"
cap_method

In order to be compatible with the previous dev.cap_method

为了兼容以前的`dev.cap_method`

Returns:“MINICAP” or “JAVACAP”

Examples

>>> dev = Android()
>>> print(dev.cap_method)  # "MINICAP"
screen_proxy

Similar to touch_proxy, it returns a proxy that can automatically initialize an available screenshot method, such as Minicap

Afterwards, you only need to call self.screen_proxy.get_frame() to get the screenshot

类似touch_proxy,返回一个代理,能够自动初始化一个可用的屏幕截图方法,例如Minicap

后续只需要调用 ``self.screen_proxy.get_frame()``即可获取到屏幕截图

Returns: ScreenProxy(Minicap())

Examples

>>> dev = Android()
>>> img = dev.screen_proxy.get_frame_from_stream()  # dev.minicap.get_frame_from_stream() is deprecated
get_deprecated_var(old_name, new_name)[source]

Get deprecated class variables

When the airtest version number>=1.1.2, the call device.minicap/device.javacap is removed, and relevant compatibility is made here, and DeprecationWarning is printed

airtest版本号>=1.1.2时,去掉了device.minicap/device.javacap这样的调用,在此做了相关的兼容,并打印DeprecationWarning

Usage: Android.minicap=property(lambda self: self.get_deprecated_var(“minicap”, “screen_proxy”))

Parameters:
  • old_name – “minicap”
  • new_name – “screen_proxy”
Returns:

New implementation of deprecated object, e.g self.minicap -> self.screen_proxy

dev.minicap.get_frame_from_stream() -> dev.screen_proxy.get_frame_from_stream()

Examples

>>> dev = Android()
>>> isinstance(dev.minicap, ScreenProxy)  # True
>>> dev.minicap.get_frame_from_stream()  # --> dev.screen_proxy.get_frame_from_stream()
get_default_device()[source]

Get local default device when no serialno

Returns:local device serialno
uuid

Serial number

Returns:
list_app(third_only=False)[source]

Return list of packages

Parameters:third_only – if True, only third party applications are listed
Returns:array of applications
path_app(package)[source]

Print the full path to the package

Parameters:package – package name
Returns:the full path to the package
check_app(package)[source]

Check if package exists on the device

Parameters:package – package name
Returns:True if package exists on the device
Raises:AirtestError – raised if package is not found
start_app(package, activity=None)[source]

Start the application and activity

Parameters:
  • package – package name
  • activity – activity name
Returns:

None

start_app_timing(package, activity)[source]

Start the application and activity, and measure time

Parameters:
  • package – package name
  • activity – activity name
Returns:

app launch time

stop_app(package)[source]

Stop the application

Parameters:package – package name
Returns:None
clear_app(package)[source]

Clear all application data

Parameters:package – package name
Returns:None
install_app(filepath, replace=False, install_options=None)[source]

Install the application on the device

Parameters:
  • filepath – full path to the apk file to be installed on the device
  • replace – True or False to replace the existing application
  • install_options – list of options, default is []
Returns:

output from installation process

install_multiple_app(filepath, replace=False, install_options=None)[source]

Install multiple the application on the device

Parameters:
  • filepath – full path to the apk file to be installed on the device
  • replace – True or False to replace the existing application
  • install_options – list of options, default is []
Returns:

output from installation process

uninstall_app(package)[source]

Uninstall the application from the device

Parameters:package – package name
Returns:output from the uninstallation process
snapshot(filename=None, ensure_orientation=True, quality=10, max_size=None)[source]

Take the screenshot of the display. The output is send to stdout by default.

Parameters:
  • filename – name of the file where to store the screenshot, default is None which is stdout
  • ensure_orientation – True or False whether to keep the orientation same as display
  • quality – The image quality, integer in range [1, 99]
  • max_size – the maximum size of the picture, e.g 1200
Returns:

screenshot output

shell(*args, **kwargs)[source]

Return adb shell interpreter

Parameters:
  • *args – optional shell commands
  • **kwargs – optional shell commands
Returns:

None

keyevent(keyname, **kwargs)[source]

Perform keyevent on the device

Parameters:
  • keyname – keyevent name
  • **kwargs – optional arguments
Returns:

None

wake()[source]

Perform wake up event

Returns:None
home()[source]

Press HOME button

Returns:None
text(text, enter=True, **kwargs)[source]

Input text on the device

Parameters:
  • text – text to input
  • enter – True or False whether to press Enter key
  • search – True or False whether to press Search key on IME after input
Returns:

None

touch(pos, duration=0.01)[source]

Perform touch event on the device

Parameters:
  • pos – coordinates (x, y)
  • duration – how long to touch the screen
Returns:

None

double_click(pos)[source]
swipe(p1, p2, duration=0.5, steps=5, fingers=1)[source]

Perform swipe event on the device

Parameters:
  • p1 – start point
  • p2 – end point
  • duration – how long to swipe the screen, default 0.5
  • steps – how big is the swipe step, default 5
  • fingers – the number of fingers. 1 or 2.
Returns:

None

pinch(center=None, percent=0.5, duration=0.5, steps=5, in_or_out='in')[source]

Perform pinch event on the device, only for minitouch and maxtouch

Parameters:
  • center – the center point of the pinch operation
  • percent – pinch distance to half of screen, default is 0.5
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
  • in_or_out – pinch in or pinch out, default is ‘in’
Returns:

None

Raises:

TypeError – An error occurred when center is not a list/tuple or None

swipe_along(coordinates_list, duration=0.8, steps=5)[source]

Perform swipe event across multiple points in sequence, only for minitouch and maxtouch

Parameters:
  • coordinates_list – list of coordinates: [(x1, y1), (x2, y2), (x3, y3)]
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
Returns:

None

two_finger_swipe(tuple_from_xy, tuple_to_xy, duration=0.8, steps=5, offset=(0, 50))[source]

Perform two finger swipe action, only for minitouch and maxtouch

Parameters:
  • tuple_from_xy – start point
  • tuple_to_xy – end point
  • duration – time interval for swipe duration, default is 0.8
  • steps – size of swipe step, default is 5
  • offset – coordinate offset of the second finger, default is (0, 50)
Returns:

None

logcat(*args, **kwargs)[source]

Perform `logcat`operations

Parameters:
  • *args – optional arguments
  • **kwargs – optional arguments
Returns:

logcat output

getprop(key, strip=True)[source]

Get properties for given key

Parameters:
  • key – key name
  • strip – True or False whether to strip the output or not
Returns:

property value(s)

get_ip_address()[source]

Perform several set of commands to obtain the IP address

  • adb shell netcfg | grep wlan0
  • adb shell ifconfig
  • adb getprop dhcp.wlan0.ipaddress
Returns:None if no IP address has been found, otherwise return the IP address
get_top_activity()[source]

Get the top activity

Returns:(package, activity, pid)
get_top_activity_name()[source]

Get the top activity name

Returns:package/activity
is_keyboard_shown()[source]

Return True or False whether soft keyboard is shown or not

Notes

Might not work on all devices

Returns:True or False
is_screenon()[source]

Return True or False whether the screen is on or not

Notes

Might not work on all devices

Returns:True or False
is_locked()[source]

Return True or False whether the device is locked or not

Notes

Might not work on some devices

Returns:True or False
unlock()[source]

Unlock the device

Notes

Might not work on all devices

Returns:None
display_info

Return the display info (width, height, orientation and max_x, max_y)

Returns:display information
get_display_info()[source]

Return the display info (width, height, orientation and max_x, max_y)

Returns:display information
get_current_resolution()[source]

Return current resolution after rotation

Returns:width and height of the display
get_render_resolution(refresh=False, package=None)[source]

Return render resolution after rotation

Parameters:
  • refresh – whether to force refresh render resolution
  • package – package name, default to the package of top activity
Returns:

offset_x, offset_y, offset_width and offset_height of the display

start_recording(max_time=1800, bit_rate_level=1, bit_rate=None)[source]

Start recording the device display

Parameters:
  • max_time – maximum screen recording time, default is 1800
  • bit_rate_level – bit_rate=resolution*level, 0 < level <= 5, default is 1
  • bit_rate – the higher the bitrate, the clearer the video
Returns:

None

Examples

Record 30 seconds of video and export to the current directory test.mp4:

>>> from airtest.core.api import connect_device, sleep
>>> dev = connect_device("Android:///")
>>> # Record the screen with the lowest quality
>>> dev.start_recording(bit_rate_level=1)
>>> sleep(30)
>>> dev.stop_recording(output="test.mp4")

Or set max_time=30, the screen recording will stop automatically after 30 seconds:

>>> dev.start_recording(max_time=30, bit_rate_level=5)
>>> dev.stop_recording(output="test_30s.mp4")

The default value of max_time is 1800 seconds, so the maximum screen recording time is half an hour. You can modify its value to obtain a longer screen recording:

>>> dev.start_recording(max_time=3600, bit_rate_level=5)
>>> dev.stop_recording(output="test_hour.mp4")
stop_recording(output='screen.mp4', is_interrupted=False)[source]

Stop recording the device display. Recoding file will be kept in the device.

Parameters:
  • output – default file is screen.mp4
  • is_interrupted – True or False. Stop only, no pulling recorded file from device.
Returns:

None

javacap
maxtouch
minicap
minitouch
adjust_all_screen(package=None)[source]

Adjust the render resolution for all_screen device.

Parameters:package – package name, default to the package of top activity
Returns:None
disconnect()[source]

Disconnect the device

  1. stop minicap/javacap
  2. stop minitouch/maxtouch
  3. stop rotation_watcher
Returns:None
airtest.core.android.constant module
class CAP_METHOD[source]

Bases: object

MINICAP = 'MINICAP'
ADBCAP = 'ADBCAP'
JAVACAP = 'JAVACAP'
class TOUCH_METHOD[source]

Bases: object

MINITOUCH = 'MINITOUCH'
MAXTOUCH = 'MAXTOUCH'
ADBTOUCH = 'ADBTOUCH'
class IME_METHOD[source]

Bases: object

ADBIME = 'ADBIME'
YOSEMITEIME = 'YOSEMITEIME'
class ORI_METHOD[source]

Bases: object

ADB = 'ADBORI'
MINICAP = 'MINICAPORI'
airtest.core.android.ime module
ensure_unicode(value)[source]

Decode UTF-8 values

Parameters:value – value to be decoded
Returns:decoded valued
class CustomIme(adb, apk_path, service_name)[source]

Bases: object

Input Methods Class Object

start()[source]

Enable input method

Returns:None
end()[source]

Disable input method

Returns:None
text(value)[source]
class YosemiteIme(adb)[source]

Bases: airtest.core.android.ime.CustomIme

Yosemite Input Method Class Object

start()[source]

Enable input method

Returns:None
text(value)[source]

Input text with Yosemite input method

Parameters:value – text to be inputted
Returns:output form adb shell command
code(code)[source]

Sending editor action

Parameters:code – editor action code, e.g., 2 = IME_ACTION_GO, 3 = IME_ACTION_SEARCH Editor Action Code Ref: http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html
Returns:output form adb shell command
airtest.core.android.javacap module
airtest.core.android.minicap module
airtest.core.android.recorder module
class Recorder(adb)[source]

Bases: airtest.core.android.yosemite.Yosemite

Screen recorder

start_recording(**kwargs)
stop_recording(output='screen.mp4', is_interrupted=False)[source]

Stop screen recording

Parameters:
  • output – default file is screen.mp4
  • is_interrupted – True or False. Stop only, no pulling recorded file from device.
Raises:

AirtestError – if recording was not started before

Returns:

None

pull_last_recording_file(output='screen.mp4')[source]

Pull the latest recording file from device. Error raises if no recording files on device.

Parameters:output – default file is screen.mp4
airtest.core.android.rotation module
class RotationWatcher(adb, ori_method='MINICAPORI')[source]

Bases: object

RotationWatcher class

get_ready()[source]
install()[source]

Install the RotationWatcher package

Returns:None
uninstall()[source]

Uninstall the RotationWatcher package

Returns:None
setup_server()[source]

Setup rotation wacher server

Returns:server process
teardown()[source]
start()[source]

Start the RotationWatcher daemon thread

Returns:initial orientation
reg_callback(ow_callback)[source]
Parameters:ow_callback

Returns:

class XYTransformer[source]

Bases: object

transform the coordinates (x, y) by orientation (upright <–> original)

static up_2_ori(tuple_xy, tuple_wh, orientation)[source]

Transform the coordinates upright –> original

Parameters:
  • tuple_xy – coordinates (x, y)
  • tuple_wh – screen width and height
  • orientation – orientation
Returns:

transformed coordinates (x, y)

static ori_2_up(tuple_xy, tuple_wh, orientation)[source]

Transform the coordinates original –> upright

Parameters:
  • tuple_xy – coordinates (x, y)
  • tuple_wh – screen width and height
  • orientation – orientation
Returns:

transformed coordinates (x, y)

airtest.core.android.yosemite module
class Yosemite(adb)[source]

Bases: object

Wrapper class of Yosemite.apk, used by javacap/recorder/yosemite_ime.

install_or_upgrade()[source]

Install or update the Yosemite.apk file on the device

Returns:None
get_ready()[source]
uninstall()[source]

Uninstall Yosemite.apk application from the device

Returns:None

airtest.core.ios package

This package provide IOS Device Class.

For the interface provided for the iOS platform, please refer to: airtest.core.ios.IOS class

Submodules

airtest.core.ios.constant module
class CAP_METHOD[source]

Bases: object

MINICAP = 'MINICAP'
WDACAP = 'WDACAP'
MJPEG = 'MJPEG'
class TOUCH_METHOD[source]

Bases: object

WDATOUCH = 'WDATOUCH'
class IME_METHOD[source]

Bases: object

WDAIME = 'WDAIME'
airtest.core.ios.elements_type module
airtest.core.ios.fake_minitouch module
airtest.core.ios.instruct_cmd module
class InstructHelper(uuid=None)[source]

Bases: object

ForwardHelper class or help run other Instruction

static builtin_iproxy_path()[source]
usb_device

Whether the current iOS uses the local USB interface, if so, return the wda.usbmux.Device object 当前iOS是否使用了本地USB接口,如果是,返回wda.usbmux.Device对象 Returns: wda.usbmux.Device or None

tear_down()[source]
setup_proxy(**kwargs)
remove_proxy(local_port)[source]
do_proxy(port, device_port)[source]

Start do proxy of ios device and self device 目前只支持本地USB连接的手机进行端口转发,远程手机暂时不支持 :returns: None

do_proxy_usbmux(lport, rport)[source]

Mapping ports of local USB devices using python multithreading 使用python多线程对本地USB设备的端口进行映射(当前仅使用USB连接一台iOS时才可用)

Parameters:
  • lport – local port
  • rport – remote port

Returns:

airtest.core.ios.ios module
decorator_retry_session(func)[source]

When the operation fails due to session failure, try to re-acquire the session, retry at most 3 times

当因为session失效而操作失败时,尝试重新获取session,最多重试3次

decorator_retry_for_class(cls)[source]

Add decorators to all methods in the class

为class里的所有method添加装饰器 decorator_retry_session

class IOS(addr='http://localhost:8100/', cap_method='MJPEG', mjpeg_port=None)[source]

Bases: airtest.core.device.Device

ios client

  • before this you have to run WebDriverAgent
  • xcodebuild -project path/to/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination "id=$(idevice_id -l)" test
  • iproxy $port 8100 $udid
ip

Returns the IP address of the host connected to the iOS phone It is not the IP address of the iOS phone. If you want to get the IP address of the phone, you can access the interface get_ip_address

For example: when the device is connected via http://localhost:8100, return localhost If it is a remote device http://192.168.xx.xx:8100, it returns the IP address of 192.168.xx.xx

Returns:

uuid
using_ios_tagent

当前基础版本:appium/WebDriverAgent 4.1.4 基于上述版本,2022.3.30之后发布的iOS-Tagent版本,在/status接口中新增了一个Version参数,如果能检查到本参数,说明使用了新版本ios-Tagent 该版本基于Appium版的WDA做了一些改动,可以更快地进行点击和滑动,并优化了部分UI树的获取逻辑 但是所有的坐标都为竖屏坐标,需要airtest自行根据方向做转换 同时,大于4.1.4版本的appium/WebDriverAgent不再需要针对ipad进行特殊的横屏坐标处理了 Returns:

is_pad

Determine whether it is an ipad(or 6P/7P/8P), if it is, in the case of horizontal screen + desktop, the coordinates need to be switched to vertical screen coordinates to click correctly (WDA bug)

判断是否是ipad(或 6P/7P/8P),如果是,在横屏+桌面的情况下,坐标需要切换成竖屏坐标才能正确点击(WDA的bug) Returns:

device_info

get the device info.

Note

Might not work on all devices

Returns:dict for device info, eg. AttrDict({
’timeZone’: ‘GMT+0800’, ‘currentLocale’: ‘zh_CN’, ‘model’: ‘iPhone’, ‘uuid’: ‘90CD6AB7-11C7-4E52-B2D3-61FA31D791EC’, ‘userInterfaceIdiom’: 0, ‘userInterfaceStyle’: ‘light’, ‘name’: ‘iPhone’, ‘isSimulator’: False})
window_size()[source]

return window size namedtuple:

Size(width , height)
orientation

return device oritantation status in LANDSACPE POR

get_orientation()[source]
display_info
touch_factor
get_render_resolution()[source]

Return render resolution after rotation

Returns:offset_x, offset_y, offset_width and offset_height of the display
get_current_resolution()[source]
home()[source]
snapshot(filename=None, quality=10, max_size=None)[source]

take snapshot

Parameters:
  • filename – save screenshot to filename
  • quality – The image quality, integer in range [1, 99]
  • max_size – the maximum size of the picture, e.g 1200

Returns:

get_frame_from_stream()[source]
touch(pos, duration=0.01)[source]
Parameters:
  • pos – coordinates (x, y), can be float(percent) or int
  • duration (optional) – tap_hold duration

Returns: None

Examples

>>> touch((100, 100))
>>> touch((0.5, 0.5), duration=1)
double_click(pos)[source]
swipe(fpos, tpos, duration=0, *args, **kwargs)[source]
Parameters:
  • fpos – start point
  • tpos – end point
  • duration (float) – start coordinate press duration (seconds), default is 0
Returns:

None

Examples

>>> swipe((1050, 1900), (150, 1900))
>>> swipe((0.2, 0.5), (0.8, 0.5))
keyevent(keyname, **kwargs)[source]

Perform keyevent on the device

Parameters:
  • keyname – home/volumeUp/volumeDown
  • **kwargs

Returns:

press(keys)[source]

some keys in [“home”, “volumeUp”, “volumeDown”] can be pressed

text(text, enter=True)[source]

Input text on the device :param text: text to input :param enter: True if you need to enter a newline at the end

Returns:None

Examples

>>> text("test")
>>> text("中文")
install_app(uri, package)[source]

curl -X POST $JSON_HEADER -d “{“desiredCapabilities”:{“bundleId”:”com.apple.mobilesafari”, “app”:”[host_path]/magicapp.app”}}” $DEVICE_URL/session https://github.com/facebook/WebDriverAgent/wiki/Queries

start_app(package, *args)[source]
Parameters:package – the app bundle id, e.g com.apple.mobilesafari
Returns:None

Examples

>>> start_app('com.apple.mobilesafari')
stop_app(package)[source]
Parameters:package – the app bundle id, e.g com.apple.mobilesafari

Returns:

app_state(package)[source]
Parameters:package
Returns:
{
“value”: 4, “sessionId”: “0363BDC5-4335-47ED-A54E-F7CCB65C6A65”

}

value 1(not running) 2(running in background) 3(running in foreground)? 4(running)

Examples

>>> dev = device()
>>> start_app('com.apple.mobilesafari')
>>> print(dev.app_state('com.apple.mobilesafari')["value"])  # --> output is 4
>>> home()
>>> print(dev.app_state('com.apple.mobilesafari')["value"])  # --> output is 3
>>> stop_app('com.apple.mobilesafari')
>>> print(dev.app_state('com.apple.mobilesafari')["value"])  # --> output is 1
app_current()[source]

get the app current

Notes

Might not work on all devices

Returns:
{“pid”: 1281,
”name”: “”, “bundleId”: “com.netease.cloudmusic”}
Return type:current app state dict, eg
get_ip_address()[source]

get ip address from webDriverAgent

Returns:raise if no IP address has been found, otherwise return the IP address
device_status()[source]

show status return by webDriverAgent Return dicts of infos

is_locked()[source]

Return True or False whether the device is locked or not

Notes

Might not work on some devices

Returns:True or False
unlock()[source]

Unlock the device, unlock screen, double press home

Notes

Might not work on all devices

Returns:None
lock()[source]

lock the device, lock screen

Notes

Might not work on all devices

Returns:None
alert_accept()[source]

Alert accept-Actually do click first alert button

Notes

Might not work on all devices

Returns:None
alert_dismiss()[source]

Alert dissmiss-Actually do click second alert button

Notes

Might not work on all devices

Returns:None
alert_wait(time_counter=2)[source]

if alert apper in time_counter second it will return True,else return False (default 20.0) time_counter default is 2 seconds

Notes

Might not work on all devices

Returns:None
alert_buttons()[source]

get alert buttons text. .. rubric:: Notes

Might not work on all devices

Returns:(“设置”, “好”)
Return type:# example return
alert_exists()[source]

get True for alert exists or False.

Notes

Might not work on all devices

Returns:True or False
alert_click(buttons)[source]

when Arg type is list, click the first match, raise ValueError if no match

eg. [“设置”, “信任”, “安装”]

Notes

Might not work on all devices

Returns:None
home_interface()[source]

get True for the device status is on home interface.

Reason:
some devices can Horizontal screen on the home interface

Notes

Might not work on all devices

Returns:True or False
clear_app(package)
disconnect()[source]

discconect mjpeg and rotation_watcher

Returns: None

list_app(**kwargs)
shell(*args, **kwargs)
uninstall_app(package)
airtest.core.ios.minicap module
class MinicapIOS(udid=None, port=12345)[source]

Bases: object

https://github.com/openstf/ios-minicap

CAPTIMEOUT = None
setup()[source]
get_frames()[source]

rotation is alwary right on iOS

list_devices()[source]
airtest.core.ios.rotation module
class RotationWatcher(iosHandle)[source]

Bases: object

RotationWatcher class

get_ready()[source]
teardown()[source]
start()[source]

Start the RotationWatcher daemon thread

Returns:None
reg_callback(ow_callback)[source]
Parameters:ow_callback

Returns:

get_rotation()[source]
class XYTransformer[source]

Bases: object

transform the coordinates (x, y) by orientation (upright <–> original)

static up_2_ori(tuple_xy, tuple_wh, orientation)[source]

Transform the coordinates upright –> original

Parameters:
  • tuple_xy – coordinates (x, y)
  • tuple_wh – current screen width and height
  • orientation – orientation
Returns:

transformed coordinates (x, y)

static ori_2_up(tuple_xy, tuple_wh, orientation)[source]

Transform the coordinates original –> upright

Parameters:
  • tuple_xy – coordinates (x, y)
  • tuple_wh – current screen width and height
  • orientation – orientation
Returns:

transformed coordinates (x, y)

airtest.core.ios.wda_client module

airtest.core.win package

For the interface provided for the Windows platform, please refer to: airtest.core.win.Windows class

This package provide Windows Client Class.

Submodules

airtest.core.win.ctypesinput module

MagicMock is a subclass of Mock with default implementations of most of the magic methods. You can use MagicMock without having to configure the magic methods yourself.

If you use the spec or spec_set arguments then only magic methods that exist in the spec will be created.

Attributes and the return value of a MagicMock will also be MagicMocks.

airtest.core.win.screen module
screenshot(filename, hwnd=None)[source]

Take the screenshot of Windows app

Parameters:
  • filename – file name where to store the screenshot
  • hwnd
Returns:

bitmap screenshot file

airtest.core.win.win module
require_app(func)[source]
class Windows(handle=None, dpifactor=1, **kwargs)[source]

Bases: airtest.core.device.Device

Windows client.

uuid
connect(handle=None, **kwargs)[source]

Connect to window and set it foreground

Parameters:**kwargs – optional arguments
Returns:None
shell(cmd)[source]

Run shell command in subprocess

Parameters:cmd – command to be run
Raises:subprocess.CalledProcessError – when command returns non-zero exit status
Returns:command output as a byte string
snapshot(filename=None, quality=10, max_size=None)[source]

Take a screenshot and save it in ST.LOG_DIR folder

Parameters:
  • filename – name of the file to give to the screenshot, {time}.jpg by default
  • quality – The image quality, integer in range [1, 99]
  • max_size – the maximum size of the picture, e.g 1200
Returns:

display the screenshot

keyevent(keyname, **kwargs)[source]

Perform a key event

References

https://pywinauto.readthedocs.io/en/latest/code/pywinauto.keyboard.html

Parameters:
  • keyname – key event
  • **kwargs – optional arguments
Returns:

None

text(text, **kwargs)[source]

Input text

Parameters:
  • text – text to input
  • **kwargs – optional arguments
Returns:

None

key_press(key)[source]

Simulates a key press event.

Sends a scancode to the computer to report which key has been pressed. Some games use DirectInput devices, and respond only to scancodes, not virtual key codes. You can simulate DirectInput key presses using this method, instead of the keyevent() method, which uses virtual key codes.

Parameters:key – A string indicating which key to be pressed. Available key options are: {‘ESCAPE’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘0’, ‘-’, ‘=’, ‘BACKSPACE’, ‘TAB’, ‘Q’, ‘W’, ‘E’, ‘R’, ‘T’, ‘Y’, ‘U’, ‘I’, ‘O’, ‘P’, ‘[’, ‘]’, ‘ENTER’, ‘LCTRL’, ‘A’, ‘S’, ‘D’, ‘F’, ‘G’, ‘H’, ‘J’, ‘K’, ‘L’, ‘;’, “’”, ‘`’, ‘LSHIFT’, ‘BACKSLASH’, ‘Z’, ‘X’, ‘C’, ‘V’, ‘B’, ‘N’, ‘M’, ‘,’, ‘.’, ‘/’, ‘RSHIFT’, ‘*’, ‘LALT’, ‘SPACE’, ‘CAPS_LOCK’, ‘F1’, ‘F2’, ‘F3’, ‘F4’, ‘F5’, ‘F6’, ‘F7’, ‘F8’, ‘F9’, ‘F10’, ‘NUM_LOCK’, ‘SCROLL_LOCK’, ‘NUMPAD_7’, ‘NUMPAD_8’, ‘NUMPAD_9’, ‘NUMPAD_-’, ‘NUMPAD_4’, ‘NUMPAD_5’, ‘NUMPAD_6’, ‘NUMPAD_+’, ‘NUMPAD_1’, ‘NUMPAD_2’, ‘NUMPAD_3’, ‘NUMPAD_0’, ‘NUMPAD_.’, ‘F11’, ‘F12’, ‘PRINT_SCREEN’, ‘PAUSE’, ‘NUMPAD_ENTER’, ‘RCTRL’, ‘NUMPAD_/’, ‘RALT’, ‘HOME’, ‘UP’, ‘PAGE_UP’, ‘LEFT’, ‘RIGHT’, ‘END’, ‘DOWN’, ‘PAGE_DOWN’, ‘INSERT’, ‘DELETE’, ‘LWINDOWS’, ‘RWINDOWS’, ‘MENU’}.
key_release(key)[source]

Simulates a key release event.

Sends a scancode to the computer to report which key has been released. Some games use DirectInput devices, and respond only to scancodes, not virtual key codes. You can simulate DirectInput key releases using this method. A call to the key_release() method usually follows a call to the key_press() method of the same key.

Parameters:key – A string indicating which key to be released.
touch(pos, **kwargs)[source]

Perform mouse click action

References

https://pywinauto.readthedocs.io/en/latest/code/pywinauto.mouse.html

Parameters:
  • pos – coordinates where to click
  • **kwargs – optional arguments
Returns:

None

double_click(pos)[source]
swipe(p1, p2, duration=0.8, steps=5)[source]

Perform swipe (mouse press and mouse release)

Parameters:
  • p1 – start point
  • p2 – end point
  • duration – time interval to perform the swipe action
  • steps – size of the swipe step
Returns:

None

mouse_move(pos)[source]

Simulates a mousemove event.

Known bug:
Due to a bug in the pywinauto module, users might experience off-by-one errors when it comes to the exact coordinates of the position on screen.
Parameters:pos – A tuple (x, y), where x and y are x and y coordinates of the screen to move the mouse to, respectively.
mouse_down(button='left')[source]

Simulates a mousedown event.

Parameters:button – A string indicating which mouse button to be pressed. Available mouse button options are: {‘left’, ‘middle’, ‘right’}.
mouse_up(button='left')[source]

Simulates a mouseup event.

A call to the mouse_up() method usually follows a call to the mouse_down() method of the same mouse button.

Parameters:button – A string indicating which mouse button to be released.
start_app(path, **kwargs)[source]

Start the application

Parameters:
Returns:

None

stop_app(pid)[source]

Stop the application

Parameters:pid – process ID of the application to be stopped
Returns:None
set_foreground()[source]

Bring the window foreground

Returns:None
get_rect()[source]

Get rectangle

Returns:win32structures.RECT
get_title()[source]

Get the window title

Returns:window title
get_pos()[source]

Get the window position coordinates

Returns:coordinates of topleft corner of the window (left, top)
move(pos)[source]

Move window to given coordinates

Parameters:pos – coordinates (x, y) where to move the window
Returns:None
kill()[source]

Kill the application

Returns:None
focus_rect
get_current_resolution()[source]
get_ip_address()[source]

Return default external ip address of the windows os.

Returns:ip address
Return type:str

airtest

airtest package

Subpackages
airtest.aircv package
Submodules
airtest.aircv.aircv module
imread(filename, flatten=False)[source]

根据图片路径,将图片读取为cv2的图片处理格式.

imwrite(filename, img, quality=10, max_size=None)[source]

写出图片到本地路径,压缩

show(img, title='show_img', test_flag=False)[source]

在可缩放窗口里显示图片.

show_origin_size(img, title='image', test_flag=False)[source]

原始尺寸窗口中显示图片.

rotate(img, angle=90, clockwise=True)[source]

函数使图片可顺时针或逆时针旋转90、180、270度. 默认clockwise=True:顺时针旋转

crop_image(img, rect)[source]

区域截图,同时返回截取结果 和 截取偏移; Crop image , rect = [x_min, y_min, x_max ,y_max]. (airtest中有用到)

mark_point(img, point, circle=False, color=100, radius=20)[source]

调试用的: 标记一个点

mask_image(img, mask, color=(255, 255, 255), linewidth=-1)[source]

将screen的mask矩形区域刷成白色gbr(255, 255, 255). 其中mask区域为: [x_min, y_min, x_max, y_max]. color: 顺序分别的blue-green-red通道. linewidth: 为-1时则完全填充填充,为正整数时为线框宽度.

get_resolution(img)[source]
airtest.aircv.cal_confidence module

These functions calculate the similarity of two images of the same size.

cal_ccoeff_confidence(im_source, im_search)[source]

求取两张图片的可信度,使用TM_CCOEFF_NORMED方法.

cal_rgb_confidence(img_src_rgb, img_sch_rgb)[source]

同大小彩图计算相似度.

airtest.aircv.error module
Declaration:
Define all BaseError Classes used in aircv.
exception BaseError(message='')[source]

Bases: Exception

Base class for exceptions in this module.

exception FileNotExistError(message='')[source]

Bases: airtest.aircv.error.BaseError

Image does not exist.

exception TemplateInputError(message='')[source]

Bases: airtest.aircv.error.BaseError

Resolution input is not right.

exception NoSIFTModuleError(message='')[source]

Bases: airtest.aircv.error.BaseError

Resolution input is not right.

exception NoSiftMatchPointError(message='')[source]

Bases: airtest.aircv.error.BaseError

Exception raised for errors 0 sift points found in the input images.

exception SiftResultCheckError(message='')[source]

Bases: airtest.aircv.error.BaseError

Exception raised for errors 0 sift points found in the input images.

exception HomographyError(message='')[source]

Bases: airtest.aircv.error.BaseError

In homography, find no mask, should kill points which is duplicate.

exception NoModuleError(message='')[source]

Bases: airtest.aircv.error.BaseError

Resolution input is not right.

exception NoMatchPointError(message='')[source]

Bases: airtest.aircv.error.BaseError

Exception raised for errors 0 keypoint found in the input images.

exception MatchResultCheckError(message='')[source]

Bases: airtest.aircv.error.BaseError

Exception raised for errors 0 keypoint found in the input images.

airtest.aircv.keypoint_base module

Detect keypoints with KAZE.

class KeypointMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: object

基于特征点的识别基类: KAZE.

METHOD_NAME = 'KAZE'
FILTER_RATIO = 0.59
ONE_POINT_CONFI = 0.5
mask_kaze()[source]

基于kaze查找多个目标区域的方法.

find_all_results()[source]

基于kaze查找多个目标区域的方法.

find_best_result(*args, **kwargs)
show_match_image()[source]

Show how the keypoints matches.

init_detector()[source]

Init keypoint detector object.

get_keypoints_and_descriptors(image)[source]

获取图像特征点和描述符.

match_keypoints(des_sch, des_src)[source]

Match descriptors (特征值匹配).

airtest.aircv.keypoint_matching module

Detect keypoints with KAZE/AKAZE/BRISK/ORB. No need for opencv-contrib module.

class KAZEMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

KAZE Matching.

class BRISKMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

BRISK Matching.

METHOD_NAME = 'BRISK'
init_detector()[source]

Init keypoint detector object.

class AKAZEMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

AKAZE Matching.

METHOD_NAME = 'AKAZE'
init_detector()[source]

Init keypoint detector object.

class ORBMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

ORB Matching.

METHOD_NAME = 'ORB'
init_detector()[source]

Init keypoint detector object.

airtest.aircv.keypoint_matching_contrib module

Detect keypoints with BRIEF/SIFT/SURF. Need opencv-contrib module.

check_cv_version_is_new()[source]

opencv版本是3.0或4.0以上, API接口与2.0的不同.

class BRIEFMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

FastFeature Matching.

METHOD_NAME = 'BRIEF'
init_detector()[source]

Init keypoint detector object.

get_keypoints_and_descriptors(image)[source]

获取图像特征点和描述符.

match_keypoints(des_sch, des_src)[source]

Match descriptors (特征值匹配).

class SIFTMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

SIFT Matching.

METHOD_NAME = 'SIFT'
FLANN_INDEX_KDTREE = 0
init_detector()[source]

Init keypoint detector object.

get_keypoints_and_descriptors(image)[source]

获取图像特征点和描述符.

match_keypoints(des_sch, des_src)[source]

Match descriptors (特征值匹配).

class SURFMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: airtest.aircv.keypoint_base.KeypointMatching

SURF Matching.

METHOD_NAME = 'SURF'
UPRIGHT = 0
HESSIAN_THRESHOLD = 400
FLANN_INDEX_KDTREE = 0
init_detector()[source]

Init keypoint detector object.

get_keypoints_and_descriptors(image)[source]

获取图像特征点和描述符.

match_keypoints(des_sch, des_src)[source]

Match descriptors (特征值匹配).

airtest.aircv.sift module
find_sift(im_source, im_search, threshold=0.8, rgb=True, good_ratio=0.59)[source]

基于sift进行图像识别,只筛选出最优区域.

mask_sift(im_source, im_search, threshold=0.8, rgb=True, good_ratio=0.59)[source]

基于sift查找多个目标区域的方法.

find_all_sift(im_source, im_search, threshold=0.8, rgb=True, good_ratio=0.59)[source]

基于sift查找多个目标区域的方法.

airtest.aircv.template module

模板匹配.

对用户提供的调节参数:
  1. threshod: 筛选阈值,默认为0.8
  2. rgb: 彩色三通道,进行彩色权识别.
find_template(im_source, im_search, threshold=0.8, rgb=False)[source]

函数功能:找到最优结果.

find_all_template(im_source, im_search, threshold=0.8, rgb=False, max_count=10)[source]

根据输入图片和参数设置,返回所有的图像识别结果.

airtest.aircv.template_matching module

模板匹配.

对用户提供的调节参数:
  1. threshod: 筛选阈值,默认为0.8
  2. rgb: 彩色三通道,进行彩色权识别.
class TemplateMatching(im_search, im_source, threshold=0.8, rgb=True)[source]

Bases: object

模板匹配.

METHOD_NAME = 'Template'
MAX_RESULT_COUNT = 10
find_all_results(*args, **kwargs)
find_best_result(*args, **kwargs)
airtest.aircv.utils module
print_run_time(func)[source]
generate_result(middle_point, pypts, confi)[source]

Format the result: 定义图像识别结果格式.

check_image_valid(im_source, im_search)[source]

Check if the input images valid or not.

检查图像识别的输入.

img_mat_rgb_2_gray(img_mat)[source]

Turn img_mat into gray_scale, so that template match can figure the img data. “print(type(im_search[0][0])”) can check the pixel type.

img_2_string(img)[source]
string_2_img(pngstr)[source]
pil_2_cv2(pil_image)[source]
cv2_2_pil(cv2_image)[source]
compress_image(pil_img, path, quality, max_size=None)[source]

Save the picture and compress

Parameters:
  • pil_img – PIL image
  • path – save path
  • quality – the image quality, integer in range [1, 99]
  • max_size – the maximum size of the picture, e.g 1200
Returns:

airtest.cli package
Submodules
airtest.cli.info module
get_script_info(script_path)[source]

extract info from script, like basename, __author__, __title__ and __desc__.

get_author_title_desc(text)[source]

Get author title desc.

process_desc(desc)[source]
strip_str(string)[source]

Strip string.

airtest.cli.parser module
get_parser()[source]
runner_parser(ap=None)[source]
cli_setup(args=None)[source]

future api for setup env by cli

airtest.cli.runner module
class AirtestCase(methodName='runTest')[source]

Bases: unittest.case.TestCase

PROJECT_ROOT = '.'
SCRIPTEXT = '.air'
TPLEXT = '.png'
classmethod setUpClass()[source]

Hook method for setting up class fixture before running tests in the class.

setUp()[source]

Hook method for setting up the test fixture before exercising it.

tearDown()[source]

Hook method for deconstructing the test fixture after testing it.

runTest()[source]
classmethod exec_other_script(scriptpath)[source]

run other script in test script

setup_by_args(args)[source]
run_script(parsed_args, testcase_cls=<class 'airtest.cli.runner.AirtestCase'>)[source]
airtest.core package
Subpackages
airtest.core.linux package

This package provide Windows Client Class.

Submodules
airtest.core.linux.linux module
class Linux(pid=None, **kwargs)[source]

Bases: airtest.core.device.Device

Linux desktop.

shell(cmd)[source]

Run shell command in subprocess

Parameters:cmd – command to be run
Raises:subprocess.CalledProcessError – when command returns non-zero exit status
Returns:command output as a byte string
snapshot(filename='tmp.png', quality=None)[source]

Take a screenshot and save it to tmp.png filename by default

Parameters:
  • filename – name of file where to store the screenshot
  • quality – ignored
Returns:

display the screenshot

keyevent(keyname, **kwargs)[source]

Perform a key event

References

https://pywinauto.readthedocs.io/en/latest/code/pywinauto.keyboard.html

Parameters:
  • keyname – key event
  • **kwargs – optional arguments
Returns:

None

text(text, **kwargs)[source]

Input text

Parameters:
  • text – text to input
  • **kwargs – optional arguments
Returns:

None

touch(pos, **kwargs)[source]

Perform mouse click action

References

https://pywinauto.readthedocs.io/en/latest/code/pywinauto.mouse.html

Parameters:
  • pos – coordinates where to click
  • **kwargs – optional arguments
Returns:

None

double_click(pos)[source]
swipe(p1, p2, duration=0.8, steps=5)[source]

Perform swipe (mouse press and mouse release) :param p1: start point :param p2: end point :param duration: time interval to perform the swipe action :param steps: size of the swipe step

Returns:None
start_app(path)[source]

Start the application

Parameters:path – full path to the application
Returns:None
stop_app(pid)[source]

Stop the application

Parameters:pid – process ID of the application to be stopped
Returns:None
get_current_resolution()[source]
get_ip_address()[source]

Return default external ip address of the linux os.

Returns:ip address
Return type:str
Submodules
airtest.core.assertions module

Assertions for Airtest

assert_exists(v, msg='')[source]

Assert target exists on device screen

Parameters:
  • v – target to be checked
  • msg – short description of assertion, it will be recorded in the report
Raises:

AssertionError – if assertion fails

Returns:

coordinates of the target

Platforms:

Android, Windows, iOS

Example:
>>> assert_exists(Template(r"tpl1607324047907.png"), "assert exists")
assert_not_exists(v, msg='')[source]

Assert target does not exist on device screen

Parameters:
  • v – target to be checked
  • msg – short description of assertion, it will be recorded in the report
Raises:

AssertionError – if assertion fails

Returns:

None.

Platforms:

Android, Windows, iOS

Example:
>>> assert_not_exists(Template(r"tpl1607324047907.png"), "assert not exists")
assert_equal(first, second, msg='', snapshot=True)[source]

Assert two values are equal

Parameters:
  • first – first value
  • second – second value
  • msg – short description of assertion, it will be recorded in the report
Raises:

AssertionError – if assertion fails

Returns:

None

Platforms:

Android, Windows, iOS

Example:
>>> assert_equal(1, 1, msg="assert 1==1")
assert_not_equal(first, second, msg='', snapshot=True)[source]

Assert two values are not equal

Parameters:
  • first – first value
  • second – second value
  • msg – short description of assertion, it will be recorded in the report
Raises:

AssertionError – if assertion

Returns:

None

Platforms:

Android, Windows, iOS

Example:
>>> assert_not_equal(1, 2, msg="assert 1!=2")
assert_true(expr, msg='', snapshot=True)[source]

Assert expression is True ( bool(expr) is True ) Note that this is equivalent to bool(expr) is True and not to expr is True (use assertIs(expr, True) for the latter).

Example:
>>> assert_true(1==1, msg="assert 1==1")
assert_false(expr, msg='', snapshot=True)[source]

Assert expression is False ( bool(expr) is False )

Example:
>>> assert_false(1==2, msg="assert 1!=2")
assert_is(first, second, msg='', snapshot=True)[source]

Test that first and second are the same object.

Example:
>>> assert_is(1, 1, msg="assert 1 is 1")
assert_is_not(first, second, msg='', snapshot=True)[source]

Test that first and second are not the same object.

Example:
>>> assert_is_not(1, 2, msg="assert 1 is not 2")
assert_is_none(expr, msg='', snapshot=True)[source]

Test that expr is None.

Example:
>>> assert_is_none(None, msg="assert None is None")
assert_is_not_none(expr, msg='', snapshot=True)[source]

Test that expr is not None.

Example:
>>> assert_is_not_none(1, msg="assert 1 is not None")
assert_in(first, second, msg='', snapshot=True)[source]

Test that first is in second.

Example:
>>> assert_in(1, [1, 2], msg="assert 1 in [1, 2]")
assert_not_in(first, second, msg='', snapshot=True)[source]

Test that first is not in second.

Example:
>>> assert_not_in(3, [1, 2], msg="assert 3 not in [1, 2]")
assert_is_instance(obj, cls, msg='', snapshot=True)[source]

Test that obj is an instance of cls (which can be a class or a tuple of classes, as supported by isinstance()).

Example:
>>> assert_is_instance(1, int, msg="assert 1 is int")
assert_not_is_instance(obj, cls, msg='', snapshot=True)[source]

Test that obj is not an instance of cls.

Example:
>>> assert_not_is_instance(1, str, msg="assert 1 is not str")
assert_greater(first, second, msg='', snapshot=True)[source]

Test that first is greater than second. (first > second)

Example:
>>> assert_greater(2, 1, msg="assert 2 > 1")
assert_greater_equal(first, second, msg='', snapshot=True)[source]

Test that first is greater than or equal to second. (first >= second)

Example:
>>> assert_greater_equal(1, 1, msg="assert 1 >= 1")
assert_less(first, second, msg='', snapshot=True)[source]

Test that first is less than second. (first < second)

Example:
>>> assert_less(1, 2, msg="assert 1 < 2")
assert_less_equal(first, second, msg='', snapshot=True)[source]

Test that first is less than or equal to second. (first <= second)

Example:
>>> assert_less_equal(1, 1, msg="assert 1 <= 1")
airtest.core.cv module

“Airtest图像识别专用.

loop_find(query, timeout=20, threshold=None, interval=0.5, intervalfunc=None)[source]

Search for image template in the screen until timeout

Parameters:
  • query – image template to be found in screenshot
  • timeout – time interval how long to look for the image template
  • threshold – default is None
  • interval – sleep interval before next attempt to find the image template
  • intervalfunc – function that is executed after unsuccessful attempt to find the image template
Raises:

TargetNotFoundError – when image template is not found in screenshot

Returns:

TargetNotFoundError if image template not found, otherwise returns the position where the image template has been found in screenshot

try_log_screen(screen=None, quality=None, max_size=None)[source]

Save screenshot to file

Parameters:
  • screen – screenshot to be saved
  • quality – The image quality, default is ST.SNAPSHOT_QUALITY
  • max_size – the maximum size of the picture, e.g 1200
Returns:

filename, “resolution”: aircv.get_resolution(screen)}

Return type:

{“screen”

class Template(filename, threshold=None, target_pos=5, record_pos=None, resolution=(), rgb=False, scale_max=800, scale_step=0.005)[source]

Bases: object

picture as touch/swipe/wait/exists target and extra info for cv match filename: pic filename target_pos: ret which pos in the pic record_pos: pos in screen when recording resolution: screen resolution when recording rgb: 识别结果是否使用rgb三通道进行校验. scale_max: 多尺度模板匹配最大范围. scale_step: 多尺度模板匹配搜索步长.

filepath
match_in(screen)[source]
match_all_in(screen)[source]
class Predictor[source]

Bases: object

this class predicts the press_point and the area to search im_search.

DEVIATION = 100
static count_record_pos(pos, resolution)[source]

计算坐标对应的中点偏移值相对于分辨率的百分比.

classmethod get_predict_point(record_pos, screen_resolution)[source]

预测缩放后的点击位置点.

classmethod get_predict_area(record_pos, image_wh, image_resolution=(), screen_resolution=())[source]

Get predicted area in screen.

airtest.core.device module
class MetaDevice[source]

Bases: type

REGISTRY = {'Android': <class 'airtest.core.android.android.Android'>, 'Device': <class 'airtest.core.device.Device'>}
class Device[source]

Bases: object

base class for test device

uuid
shell(*args, **kwargs)[source]
snapshot(*args, **kwargs)[source]
touch(target, **kwargs)[source]
double_click(target)[source]
swipe(t1, t2, **kwargs)[source]
keyevent(key, **kwargs)[source]
text(text, enter=True)[source]
start_app(package, **kwargs)[source]
stop_app(package)[source]
clear_app(package)[source]
list_app(**kwargs)[source]
install_app(uri, **kwargs)[source]
uninstall_app(package)[source]
get_current_resolution()[source]
get_render_resolution()[source]
get_ip_address()[source]
disconnect()[source]
airtest.core.error module

error classes

exception BaseError(value)[source]

Bases: Exception

exception AirtestError(value)[source]

Bases: airtest.core.error.BaseError

This is Airtest BaseError

exception InvalidMatchingMethodError(value)[source]

Bases: airtest.core.error.BaseError

This is InvalidMatchingMethodError BaseError When an invalid matching method is used in settings.

exception TargetNotFoundError(value)[source]

Bases: airtest.core.error.AirtestError

This is TargetNotFoundError BaseError When something is not found

exception ScriptParamError(value)[source]

Bases: airtest.core.error.AirtestError

This is ScriptParamError BaseError When something goes wrong

exception AdbError(stdout, stderr)[source]

Bases: Exception

This is AdbError BaseError When ADB have something wrong

exception AdbShellError(stdout, stderr)[source]

Bases: airtest.core.error.AdbError

adb shell error

exception DeviceConnectionError(value)[source]

Bases: airtest.core.error.BaseError

device connection error

DEVICE_CONNECTION_ERROR = "error:\\s*((device \\'\\S+\\' not found)|(cannot connect to daemon at [\\w\\:\\s\\.]+ Connection timed out))"
exception ICmdError(stdout, stderr)[source]

Bases: Exception

This is ICmdError BaseError When ICmd have something wrong

exception ScreenError(value)[source]

Bases: airtest.core.error.BaseError

When the screen capture method(Minicap/Javacap/ScreenProxy) has something wrong

exception MinicapError(value)[source]

Bases: airtest.core.error.ScreenError

This is MinicapError BaseError When Minicap have something wrong

exception MinitouchError(value)[source]

Bases: airtest.core.error.BaseError

This is MinitouchError BaseError When Minicap have something wrong

exception PerformanceError(value)[source]

Bases: airtest.core.error.BaseError

airtest.core.helper module
class G[source]

Bases: object

Represent the globals variables

BASEDIR = []
LOGGER = <airtest.utils.logwraper.AirtestLogger object>
LOGGING = <Logger airtest.core.api (DEBUG)>
SCREEN = None
DEVICE = None
DEVICE_LIST = []
RECENT_CAPTURE = None
RECENT_CAPTURE_PATH = None
CUSTOM_DEVICES = {}
classmethod add_device(dev)[source]

Add device instance in G and set as current device.

Examples

G.add_device(Android())

Parameters:dev – device to init
Returns:None
classmethod register_custom_device(device_cls)[source]
set_logdir(dirpath)[source]

set log dir for logfile and screenshots.

Parameters:dirpath – directory to save logfile and screenshots

Returns:

log(arg, timestamp=None, desc='', snapshot=False)[source]

Insert user log, will be displayed in Html report.

Parameters:
  • arg – log message or Exception object
  • timestamp – the timestamp of the log, default is time.time()
  • desc – description of log, default is arg.class.__name__
  • snapshot – whether to take a screenshot, default is False
Returns:

None

Examples

>>> log("hello world", snapshot=True)
>>> log({"key": "value"}, timestamp=time.time(), desc="log dict")
>>> try:
        1/0
    except Exception as e:
        log(e)
logwrap(f)[source]
device_platform(device=None)[source]
using(path)[source]
import_device_cls(platform)[source]

lazy import device class

delay_after_operation()[source]
airtest.core.settings module
class Settings[source]

Bases: object

DEBUG = False
LOG_DIR = None
LOG_FILE = 'log.txt'
static RESIZE_METHOD(w, h, sch_resolution, src_resolution, design_resolution=(960, 640))

图像缩放规则: COCOS中的MIN策略.

CVSTRATEGY = ['mstpl', 'tpl', 'surf', 'brisk']
KEYPOINT_MATCHING_PREDICTION = True
THRESHOLD = 0.7
THRESHOLD_STRICT = None
OPDELAY = 0.1
FIND_TIMEOUT = 20
FIND_TIMEOUT_TMP = 3
PROJECT_ROOT = ''
SNAPSHOT_QUALITY = 10
IMAGE_MAXSIZE = None
SAVE_IMAGE = True
airtest.report package
Submodules
airtest.report.report module
nl2br(eval_ctx, value)[source]
timefmt(timestamp)[source]

Formatting of timestamp in Jinja2 templates :param timestamp: timestamp of steps :return: “%Y-%m-%d %H:%M:%S”

class LogToHtml(script_root, log_root='', static_root='', export_dir=None, script_name='', logfile=None, lang='en', plugins=None)[source]

Bases: object

Convert log to html display

scale = 0.5
static init_plugin_modules(plugins)[source]
classmethod get_thumbnail(path)[source]

compress screenshot

classmethod get_small_name(filename)[source]
static div_rect(r)[source]

count rect for js use

is_pos(v)[source]
copy_tree(src, dst, ignore=None)[source]
get_relative_log(output_file)[source]

Try to get the relative path of log.txt :param output_file: output file: log.html :return: ./log.txt or “”

get_console(output_file)[source]
readFile(filename, code='utf-8')[source]
report_data(output_file=None, record_list=None)[source]

Generate data for the report page

Parameters:
  • output_file – The file name or full path of the output file, default HTML_FILE
  • record_list – List of screen recording files
Returns:

report(template_name='log_template.html', output_file='log.html', record_list=None)[source]

Generate the report page, you can add custom data and overload it if needed

Parameters:
  • template_name – default is HTML_TPL
  • output_file – The file name or full path of the output file, default HTML_FILE
  • record_list – List of screen recording files
Returns:

simple_report(filepath, logpath=True, logfile=None, output='log.html')[source]
get_parger(ap)[source]
main(args)[source]

Device Connection

Supported Platforms 各平台支持情况

Overview
Platforms Airtest Poco
Android
Emulator model list
iOS ios-Tagent ios-tagent
Windows Not yet
Cocos2dx-js & Cocos2dx-lua integration doc
Unity3D integration doc
Egret integration doc
WeChat Applet & Webview tutorial 中文版本
Netease engines tutorial
Other engines implementation doc
Android

Currently we are compatible with most Android phones (2.3 <= Android <= 11) on the market, and a few special Android tablets and devices.

  • If you encounter problems during the connection, please refer to the device settings of this document according to the different mobile phone manufacturers: Some manufacturer’s device special problems
  • For MIUI 11 or above of Xiaomi mobile phone, please use cap_method=JAVACAP mode to connect to the phone

目前我们兼容市面上绝大多数的Android手机(2.3 <= Android <= 11),和少数特殊Android平板和设备。

  • 如果在连接中遇到问题,请根据手机厂商的不同,查看此文档的设备设置:部分厂商设备特殊问题
  • 小米手机的MIUI 11 以上版本,请使用cap_method=JAVACAP模式连接手机
Android Emulator 模拟器

The following emulators have been verified, Android Emulator Connection Guidelines

下列模拟器都经过验证,Android模拟器连接指引

附录:我们对常见模拟器版本的适配情况测试(2020.06,随着版本更新可能失效)

iOS

According to iOS-Tagent document, the current support situation:

iOS-Tagent文档为准,目前的支持情况:

xcode iOS
<= 11.5 <=13.5

Android device connection methods and FAQs

中文版

Android phone connection

If use AirtestIDE to mobile phone connection, please refer to the documents

If you’re not going to use AirtestIDE, have a look at this statement:

Use ADB to see if the phone is successfully connected

adb is the official Android command line tool for Google, which allows us to communicate with devices.(if you are interested, please refer to: adb.)

We have stored adb executables for each platform under airtest\airtest\core\Android\static\adb directory, you can use it without downloading.

Take Windows as an example, you can first use the terminal to enter the directory where adb.exe is located (in airtest\airtest\core\Android\static\adb\Windows, shift+right click to open the command line terminal), and then execute the command line of adb devices :

E:\airtest\airtest\core\android\static\adb\windows>adb devices

List of devices attached
c2b1c2a7        device
eba17551        device
127.0.0.1:10033 device

In MAC, you can visit airtest/core/android/static/adb/mac directory and run the ./adb devices, if the adb no executable permissions, can run chmod + x adb add executable permissions for it.

  • In the above example, you can see that the 3 Android devices currently connected, whose state is device, are normally online
  • If the device status is UNAUTHORIZED, click OK in the ALLOW USB Debugging menu that pops up over the phone
  • If you can’t see the device name, you may need to install the phone’s official driver on your PC
If your phone has a connection problem

Due to different mobile phone manufacturers and the corresponding model, may encounter all sorts of problems in the process of connecting, please refer to the link common problems Android

Use the phone in your code

After confirming that the phone can be successfully connected, we can see the device serial number of the phone in the command line of adb devices :

> adb devices 

List of devices attached
c2b1c2a7        device

The c2B1c2A7 above is the device serial number of the mobile phone. We define a mobile phone with the following format string:

Android://<adbhost>:<adbport>/<serialno>

Among them:

  • adbhost is the IP of the host where adb Server is located. By default, this is localhostor 127.0.0.1
  • adb port defaults to 5037
  • serialno is the serial number of the Android phone, such as c2B1c2a7 just now

Here are some examples:

# Will default to the first phone in the current connection if you fill in nothing 
Android:///
# A phone with c2B1C2a7 connected to the default port of the native 
Android://127.0.0.1:5037/c2b1c2a7
# Connect a remote device through ADB connect with the native ADB. Note that 10.254.60.1:5555 is actually Serialno 
Android://127.0.0.1:5037/10.254.60.1:5555
Connect the phone according to the Android:/// string

When we run a script from the command line, we can use --device Android:/// to specify the Android device on which the script will run, for example:

>airtest run untitled.air --device Android:/// phone serial number --log log/

In addition, we can use the connect_device interface when we want to connect the phone in our code:

from airtest.core.api import *
connect_device("Android:///Phone Serial Number")

These two methods only need to choose one of them, basically can meet our needs to connect devices.

Some special parameters

Some special devices may appear black screen when connected, such as some emulators, we can add an extra parameter cap_method=JAVACAP to force the screen capture mode to be JAVACAP :

# Connect the emulator and check the `Use Javacap` mode 
Android://127.0.0.1:5037/127.0.0.1:7555?cap_method=JAVACAP

In addition, we have two other parameters, ori_method=ADBORI, which specifies the rotation mode of the device screen, and touch_method=ADBTOUCH, which specifies the click mode of the screen as ADB instruction.

For the most part, we don’t need to specify these parameters, and we only need to add additional parameters if some special Android devices (such as some special models of tablets) can`t connect with the default parameters:

# Check all the options to connect the device and use && to connect multiple parameter strings 
Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP&&ori_method=ADBORI&&touch_method=ADBTOUCH

Note: if any of the characters ^<>|&appear on the command line, they may need to be escaped to take effect.

Therefore, if you need to write && in the connection string, you need to rewrite it as ^&^& in Windows, add a ^ symbol for escape, and add \ for escape under MAC:

# -- device Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP&&ori_method=ADBORI is not available under Windows 
--device Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP^&^&ori_method=ADBORI # Windows command line add ^ escape effect
--device Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP\&\&ori_method=ADBORI # MAC command line add \ escape
Android interface calls

All interfaces defined in airtest.core.api can be used on the Android platform and can be called directly in the script:

from airtest.core.api import *
touch((100, 200))
# Start an application 
start_app("org.cocos2d.blackjack")
# Pass in a key response 
keyevent("BACK")

Can refer to airtest.core.api for the API list.

Android device interface

In addition to the cross-platform interface provided in airtest.core.api, Android device objects have many built-in interfaces that can be called,We can airtest core. Android. Android module in this document refer to the android device object has a method, and then call something like this:

dev = device() # gets the Android object to the current device
print(dev.get_display_info()) # to view the display information for the current device
print(dev.list_app()) # prints out the list of currently installed apps
The ADB instruction call

Using the Android device interface, we can call adb directives like this:

# Execute the instruction ADB shell LS on the current device 
print(shell("ls"))

# Execute the ADB instruction for a specific device 
dev = connect_device("Android:///device1")
dev.shell("ls")

# Switch to a device and execute adb instruction 
set_current(0)
shell("ls")
Frequently asked Questions about Android
Android emulator connection

The simulator is connected in a similar way to the real machine. The following steps are required:

  • Open developer options on the emulator and check to allow USB debugging. Some emulators may need to find Settings - about the phone multiple times before opening the developer options
  • Use ADB to connect the corresponding port number, for example, enter adb connect 127.0.0.1:62001, where 7555 is the port number corresponding to the simulator, and each brand simulator is different
  • you can use the code Android://127.0.0.1:5037/127.0.0.1:62001?cap_method=JAVACAP connects to the corresponding emulator

Key points to note:

  • Most emulators cannot connect with default parameters and must specify cap_method=JAVACAP
  • each brand simulator port can be refer to Android emulator
Slide continuously

We provide some sliding interfaces to facilitate more complex operations:

dev = device()  # gets the current device
dev.pinch()  # Two fingers pinch or separate
dev.swipe_along([(100, 300), (300, 300), (100, 500), (300, 600)]) # continuously slides over a series of coordinates
dev.two_finger_swipe((100, 100), (200, 200))  # both fingers slip together

Among them, swipe_along can continuously streak through a series of coordinate points, which is the most commonly used interface.

Custom slide

In airtest.core.android.touch_methods.base_touch, defines four action events:

  • DownEvent(Coordinates, contact=0, pressure=50) click
  • UpEvent(contact=0) finger up
  • MoveEvent(coordinates, contact=0, pressure=50) slide to a coordinate
  • SleepEvent wait (seconds)

In the above four actions, the contact parameter defaults to 0, representing the first finger. If 1 is passed in, the action of the second finger can be defined, so that the complex operation of the double-finger can be achieved.

pressure=50 defines the pressure when pressed and defaults to 50.

The touch interface, for example, is actually made up of [DownEvent, SleepEvent, UpEvent] actions, which in theory can be combined to allow you to customize very complex click-and-slide operations.

For example, here`s an example of a two-fingered tap on a screen:

from airtest.core.android.touch_methods.base_touch import *
# tap with two fingers
multitouch_event = [
     DownEvent((100, 100), 0),
     DownEvent((200, 200), 1),  # second finger
     SleepEvent(1),
     UpEvent(0), UpEvent(1)]

device().touch_proxy.perform(multitouch_event)

In the example code above, press the first finger at the coordinates of (100, 100), press the second finger at (200, 200), and wait for a second before lifting each finger.

Also, MoveEvent can be added to achieve more diversified operations, such as an ordinary swipe :

Swipe_event = [DownEvent((500, 500)), SleepEvent(0.1)]

for i in range(5):
     swipe_event.append(MoveEvent((500 + 100*i, 500 + 100*i)))
     Swipe_event. Append (SleepEvent (0.2))

swipe_event.append(UpEvent())

dev.touch_proxy.perform(swipe_event)

Based on this improvement, more complex operations can be achieved, such as long press 2 seconds - slide to a position:

from airtest.core.android.touch_methods.base_touch import *
dev = device()

# Long press delete application 
longtouch_event = [
     DownEvent([908, 892]),  # coordinates of the application to be deleted
     SleepEvent(2),
     MoveEvent([165,285]),  # delete the application's garbage can coordinates
     UpEvent(0)]

dev.touch_proxy.perform(longtouch_event)

More examples, please refer to the airtest/playground/android_motionevents.py.

Debug tips

You can switch on settings-developer options-show input position on your phone to debug simulated inputs.

Record the screen while running the script

Android phones support recording the screen while running the script. Add the --recording parameter to the command line of running the script:

airtest run "D:\test\Airtest_example.air"  --device android:/// --log logs/ --recording

After running, you can find the mp4 file recorded in the specified log directory.

  • If only the --recording parameter has been passed, by default recording_serialnumber.mp4 will be used to name the recording screen file
  • If the file name --recording test.mp4 is specified and there is more than one phone, name it serialnumber.mp4
  • If you specify the filename --recording test.mp4 and have only one phone, call it test.mp4
  • Note that the file name passed in must end with mp4
  • The default screen recording file is up to 1800 seconds. If you need to record for a longer time, you need to manually call the screen recording interface in the code

If you call the screen recording interface in the code, you can control the clarity and duration of the screen recording. For the document, see Android.start_recording.

For example, to record a 30-second video with the lowest definition and export it to test.mp4 in the current directory:

from airtest.core.api import connect_device, sleep
dev = connect_device("Android:///")
# Record the screen with the lowest quality
dev.start_recording(bit_rate_level=1)
sleep(30)
dev.stop_recording(output="test.mp4")

bit_rate_level is used to control the resolution of screen recording. The value range is 1-5. bit_rate_level=5 has the highest resolution, but it will take up more hard disk space.

Or set the parameter max_time=30, the screen recording will automatically stop after 30 seconds:

dev = device()
dev.start_recording(max_time=30, bit_rate_level=5)
dev.stop_recording(output="test_30s.mp4")

The default value of max_time is 1800 seconds, so the maximum screen recording time is half an hour, you can modify its value to get a longer screen recording:

dev = device()
dev.start_recording(max_time=3600, bit_rate_level=5)
dev.stop_recording(output="test_hour.mp4")
Refer to the tutorial and documentation for more

Android设备连接方法与常见代码示例

English version

Android手机连接

若使用AirtestIDE进行手机连接,请参考文档

若不打算使用AirtestIDE,可以参考以下步骤:

使用ADB查看手机是否成功连接

adb是谷歌官方推出的Android命令行工具,可以让我们跟设备进行通信。(感兴趣的话,请参考:官方地址。)

我们已经在airtest\airtest\core\android\static\adb目录下,存放了各平台的adb可执行文件,大家无需下载也可以使用。

以windows为例,可以先使用终端进入到adb.exe所在的目录下(在airtest\airtest\core\android\static\adb\windows目录下shift+右键打开命令行终端),然后执行adb devices命令行:

E:\airtest\airtest\core\android\static\adb\windows>adb devices

List of devices attached
c2b1c2a7        device
eba17551        device
127.0.0.1:10033 device

在mac中,可以访问airtest/core/android/static/adb/mac目录下,运行 ./adb devices,若提示adb没有可执行权限,可以运行chmod +x adb为它添加可执行权限。

  • 在上面这个例子中,可以看到当前连接的3台Android设备,状态为device就是正常在线
  • 如果设备状态为unauthorized,请在手机上弹出的允许USB调试菜单中点击同意
  • 如果看不到设备名称,可能需要在PC上安装手机对应的官方驱动
手机连接遇到问题

由于手机对应的厂商和型号各不相同,可能在连接过程中会遇到各种各样的问题,请参考Android连接常见问题

在代码中使用手机

确认手机能够成功连接后,我们能够在adb devices命令行的结果中看到手机的设备序列号:

> adb devices

List of devices attached
c2b1c2a7        device

上面的c2b1c2a7就是手机的设备序列号,我们用以下格式的字符串来定义一台手机:

Android://<adbhost>:<adbport>/<serialno>

其中:

  • adbhost是adb server所在主机的ip,默认是本机,也就是localhost127.0.0.1
  • adb port默认是5037
  • serialno是android手机的序列号,例如刚才的c2b1c2a7

以下是一些示例:

# 什么都不填写,会默认取当前连接中的第一台手机
Android:///
# 连接本机默认端口连的一台设备号为c2b1c2a7的手机
Android://127.0.0.1:5037/c2b1c2a7
# 用本机的adb连接一台adb connect过的远程设备,注意10.254.60.1:5555其实是serialno
Android://127.0.0.1:5037/10.254.60.1:5555
根据Android:///字符串连接手机

当我们使用命令行运行脚本时,可以使用--device Android:///来为它指定脚本运行的Android设备,例如:

>airtest run untitled.air --device Android:///手机序列号 --log log/

除此之外,当我们想在代码里连接手机时,可以使用connect_device接口:

from airtest.core.api import *
connect_device("Android:///手机序列号")

这两种方式只需要选择其中一种,基本上都能满足我们连接设备的需求。

一些特殊参数

部分特殊设备在连接时可能会出现黑屏的情况,例如一些模拟器,我们可以额外添加cap_method=JAVACAP的参数来强制指定屏幕截图方式为JAVACAP:

# 连接了模拟器,勾选了`Use javacap`模式
Android://127.0.0.1:5037/127.0.0.1:7555?cap_method=JAVACAP

除此之外,我们还有另外两个参数,分别是用于指定设备画面旋转模式的ori_method=ADBORI,以及指定点击画面方式为ADB指令点击的touch_method=ADBTOUCH

大部分情况下,我们无需指定这些参数,只有在一些特殊的Android设备(例如部分特殊型号的平板)上,使用默认参数无法连接时,才需要加入额外的参数:

# 所有的选项都勾选上之后连接的设备,用&&来连接多个参数字符串
Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP&&ori_method=ADBORI&&touch_method=ADBTOUCH

注意:命令行中如果有出现 ^ < > | & 这些字符,可能都需要转义才能生效。

因此如果连接字符串中需要写 && 时,在windows下需要改写成 ^&^& ,添加一个 ^ 符号进行转义,在mac下则需要添加\进行转义:

# --device Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP&&ori_method=ADBORI 在windows下不可用
--device Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP^&^&ori_method=ADBORI  # windows命令行添加^转义后效果
--device Android://127.0.0.1:5037/79d03fa?cap_method=JAVACAP\&\&ori_method=ADBORI  # mac命令行添加\转义
Android接口调用

所有在airtest.core.api中定义的接口,都可以在Android平台上使用,直接在脚本中调用即可:

from airtest.core.api import *
touch((100, 200))
# 启动某个应用
start_app("org.cocos2d.blackjack")
# 传入某个按键响应
keyevent("BACK")

可以查阅airtest.core.api文档获得API列表。

Android设备接口

除了在airtest.core.api中提供的跨平台接口之外,Android设备对象还有很多内置的接口可以调用,我们可以在airtest.core.android.android module这个文档中查阅到Android设备对象拥有的方法,然后像这样调用:

dev = device()  # 获取到当前设备的Android对象
print(dev.get_display_info())  # 查看当前设备的显示信息
print(dev.list_app())  # 打印出当前安装的app列表
ADB指令调用

利用Android设备接口,我们可以这样调用adb指令:

# 对当前设备执行指令 adb shell ls
print(shell("ls"))

# 对特定设备执行adb指令
dev = connect_device("Android:///device1")
dev.shell("ls")

# 切换到某台设备,执行adb指令
set_current(0)
shell("ls")
Android常见问题与代码示例
Android模拟器连接

模拟器与真机的连接方式类似,需要进行以下步骤:

  • 打开模拟器上的开发者选项,并勾选允许USB调试。部分模拟器可能需要找到 设置-关于手机 点击多次后才能打开开发者选项
  • 使用adb连上对应的端口号,例如输入adb connect 127.0.0.1:62001,其中7555是模拟器对应的端口号,每个品牌模拟器不相同
  • 可以使用代码Android://127.0.0.1:5037/127.0.0.1:62001?cap_method=JAVACAP连上对应的模拟器

注意要点:

  • 大部分模拟器无法使用默认参数连接,必须要指定cap_method=JAVACAP
  • 各品牌模拟器的端口可以查阅Android模拟器连接
连续滑动

我们提供了一些滑动方面的接口,方便大家进行更复杂的操作:

dev = device()  # 获取当前设备
dev.pinch()  # 双指捏合或分开
dev.swipe_along([(100, 300), (300, 300), (100, 500), (300, 600)])  # 连续滑过一系列坐标
dev.two_finger_swipe( (100, 100), (200, 200) )  # 两个手指一起滑动

其中,swipe_along可以连续不断地划过一系列坐标点,是最常用的一个接口。

自定义滑动

airtest.core.android.touch_methods.base_touch中,定义了4个动作事件:

  • DownEvent(coordinates, contact=0, pressure=50) 手指按下
  • UpEvent(contact=0) 手指抬起
  • MoveEvent(coordinates, contact=0, pressure=50) 滑动到某个坐标
  • SleepEvent(seconds) 等待

上述4个动作中,contact参数默认为0,代表了第一根手指,如果传入1,就可以定义第二根手指的动作,这样就能实现双指的复杂操作了。

pressure=50定义了按下时的压力,默认为50。

例如touch接口,实际上是由[DownEvent, SleepEvent, UpEvent]三个动作组成的,理论上组合这些动作,能够自定义非常复杂的点击滑动操作。

例如这是一个双指轻点屏幕的例子:

from airtest.core.android.touch_methods.base_touch import *
# tap with two fingers
multitouch_event = [
    DownEvent((100, 100), 0),
    DownEvent((200, 200), 1),  # second finger
    SleepEvent(1),
    UpEvent(0), UpEvent(1)]

device().touch_proxy.perform(multitouch_event)

在上面的示例代码中,先在(100, 100)的坐标按下第一个手指,在(200, 200)按下第二个手指,等待一秒后再分别抬起两个手指。

还可以加入MoveEvent来实现更丰富的操作,例如一个普通的swipe是这样实现的:

swipe_event = [DownEvent((500, 500)), SleepEvent(0.1)]

for i in range(5):
    swipe_event.append(MoveEvent((500 + 100*i, 500 + 100*i)))
    swipe_event.append(SleepEvent(0.2))

swipe_event.append(UpEvent())

dev.touch_proxy.perform(swipe_event)

在此基础上进行改进,可以实现更多复杂操作,例如长按2秒-滑动到某个位置:

from airtest.core.android.touch_methods.base_touch import *
dev = device()

# 长按删除应用
longtouch_event = [
    DownEvent([908, 892]),  # 待删除应用的坐标
    SleepEvent(2),
    MoveEvent([165,285]),  # 删除应用的垃圾桶坐标
    UpEvent(0)]

dev.touch_proxy.perform(longtouch_event)

更多示例,请参考airtest/playground/android_motionevents.py

Debug tips

你可以打开手机设置-开发者选项-显示触摸位置来调试模拟输入的操作,这样做能看到每次点击的位置。

在运行脚本过程中录屏

Android手机支持在运行脚本过程中对屏幕进行录制,在运行脚本的命令行中加入--recording参数即可:

airtest run "D:\test\Airtest_example.air"  --device android:/// --log logs/ --recording

运行完毕后,可以在指定的log目录中找到录制完毕的mp4文件。

  • 如果只传了--recording参数,默认将会使用recording_手机序列号.mp4来命名录屏文件
  • 如果指定了文件名--recording test.mp4,且超过一台手机,就命名为 手机序列号_test.mp4
  • 如果指定了文件名--recording test.mp4,且只有一台手机,就命名为 test.mp4
  • 注意传入的文件名必须以mp4作为结尾
  • 默认录屏文件最长为1800秒,如果需要录制更长时间,需要手动在代码中调用录屏接口

如果在代码中调用录屏接口,能够控制录屏时的清晰度和时长,文档参见Android.start_recording

例如,以最低清晰度录制一段30秒的视频,并导出到当前目录下的test.mp4

from airtest.core.api import connect_device, sleep
dev = connect_device("Android:///")
# Record the screen with the lowest quality
dev.start_recording(bit_rate_level=1)
sleep(30)
dev.stop_recording(output="test.mp4")

bit_rate_level用于控制录屏的清晰度,取值范围是1-5,bit_rate_level=5清晰度最高,但是占用的硬盘空间也会更大。

或者设置参数max_time=30,30秒后将自动停止录屏:

dev = device()
dev.start_recording(max_time=30, bit_rate_level=5)
dev.stop_recording(output="test_30s.mp4")

max_time默认值为1800秒,所以录屏最大时长是半小时,可以修改它的值以获得更长时间的录屏:

dev = device()
dev.start_recording(max_time=3600, bit_rate_level=5)
dev.stop_recording(output="test_hour.mp4")

Code Example

Common problems and code examples

中文版

How to initialize the script
air script: auto_setup()

Automatically configure the interface of the running environment, you can configure the path where the current script is located, the device used, the storage path of the log content, the project root directory, and the screenshot compression accuracy:

auto_setup(basedir=None, devices=None, logdir=None, project_root=None, compress=None)

Interface example:

auto_setup(__file__)

auto_setup(__file__, devices=["android://127.0.0.1:5037/emulator-5554?cap_method=JAVACAP&&ori_method=MINICAPORI&&touch_method=MINITOUCH"],
           logdir=True, project_root=r"D:\test", compress=90)
How to connect/use the device
Please note: For more device related information, please refer to Document
Connect the device: connect_device(URI)

The interface to connect to the device requires the URI string used to initialize the device. Example:

# Connect Android device
connect_device("Android://127.0.0.1:5037/SJE5T17B17")

# Connect iOS device
connect_device("iOS:///127.0.0.1:8100")

# Connect Windows window
connect_device("Windows:///123456")

# Connect the simulator
connect_device("Android://127.0.0.1:5037/127.0.0.1:62001?cap_method=JAVACAP&&ori_method=ADBORI")
Connect the device: init_device()

To initialize the interface of the device, you need to pass in the device platform, the uuid and optional parameters of the device, where uuid is the serial number of Android, the window handle of Windows, or the uuid of iOS:

init_device(platform='Android', uuid=None, **kwargs)

Example of interface usage:

# Connect Android device
init_device(platform="Android",uuid="SJE5T17B17",cap_method="JAVACAP")

# Connect Windows window
init_device(platform="Windows",uuid="123456")
Get the current device: device()

Return the device instance currently in use, the usage example is as follows:

dev = device()
dev.swipe_along([[959, 418],[1157, 564],[1044, 824],[751, 638],[945, 415]])
Set the current device: set_current()

Set the current device used, which can be used to switch between multiple devices. Examples are as follows:

# The first type: Incoming numbers 0, 1, 2, etc., switch the currently operating mobile phone to the first and second mobile phone connected to Airtest
set_current(0)
set_current(1)

# Second: Switch the current mobile phone to the serial number serialno1, serialno2
set_current("serialno1")
set_current("serialno2")
How to perform coordinate click/coordinate sliding
Coordinate click

When you click on the device, you can pass in parameters such as the click location and the number of clicks. The optional parameters under different platforms are slightly different. Examples are as follows:

# Pass in absolute coordinates as the click position
touch([100,100])

# Pass in the template picture instance, click the center of the screenshot
touch(Template(r"tpl1606730579419.png", target_pos=5, record_pos=(-0.119, -0.042), resolution=(1080, 1920)))

# Click 2 times
touch([100,100],times=2)

# Under Android and Windows platforms, you can set the click duration
touch([100,100],duration=2)
Coordinate sliding

For sliding operations on the device, there are two ways to pass parameters, one is to pass in the starting point and end of the sliding, and the other is to pass in the starting point and sliding direction vector. Examples are as follows:

# Pass in absolute coordinates as the start and end of the sliding
swipe([378, 1460],[408, 892])

# Incoming image as a starting point, slide along a certain direction
swipe(Template(r"tpl1606814865574.png", record_pos=(-0.322, 0.412), resolution=(1080, 1920)), vector=[-0.0316, -0.3311])

# Commonly, you can also set the duration of sliding
swipe([378, 1460],[408, 892],duration=1)
How to install/start/uninstall apps
Start the application: start_app()

To start the target application on the device, you need to pass in the package name of the application, which supports Android and iOS platforms. Examples:

start_app("com.netease.cloudmusic")
Terminate application operation: stop_app()

To terminate the operation of the target application on the device, the package name of the application needs to be passed in. It supports Android and iOS platforms. Examples:

stop_app("com.netease.cloudmusic")
Clear application data: clear_app()

To clean up the target application data on the device, the package name of the application needs to be passed in. Only supports the Android platform, example:

clear_app("com.netease.cloudmusic")
Install the application: install()

To install the application on the device, you need to pass in the complete apk installation path, only supports the Android platform, example:

install(r"D:\demo\tutorial-blackjack-release-signed.apk")
Uninstall the application: uninstall()

To uninstall the application on the device, you need to pass in the package name of the uninstalled application. Only supports the Android platform, example:

uninstall("com.netease.cloudmusic")
Key event: keyevent
Android keyevent

It is equivalent to executing adb shell input keyevent KEYNAME, an example is as follows:

keyevent("HOME")
# The constant corresponding to the home key is 3
keyevent("3") # same as keyevent("HOME")
keyevent("BACK")
keyevent("KEYCODE_DEL")
Windows keyevent

Unlike Android, the Windows platform uses the pywinauto.keyboard module module for key input. Example:

keyevent("{DEL}")

# Use Alt+F4 to close the Windows window
keyevent("%{F4}")
iOS keyevent

Currently only supports HOME key:

keyevent("HOME")
How to enter text

To enter text on the device, the text box needs to be activated (that is, click the text box first, and then use the text() interface to enter). Examples are as follows:

touch (Template instance of text box)
text("input text")

# By default, text is with carriage return, you can pass False if you don’t need it
text("123",enter=False)

# Under the Android platform, you can also click the search button on the soft keyboard after typing
text("123",enter=False,search=True)
How to delete text

Delete a single character through the keyevent interface:

keyevent("KEYCODE_DEL")
keyevent("67") # 67 is the delete key, please note that the input is a string

Simulate clearing the input box operation:

for i in range(10):
    keyevent("67")

Delete poco (leave the input box blank):

poco("xxx").set_text("").

Log
How to log into the report

The log() interface is convenient to insert some user-defined log information, which will be displayed in the Airtest report. In Airtest version 1.1.6, the log interface supports 4 parameters:

  • args, which can be a string, a non-string or a traceback object;
  • timestamp, used to customize the timestamp of the current log;
  • desc, used to customize the title of the log;
  • snapshot, indicating whether it is necessary to take a screenshot of the current screen image and display it in the report:

Examples are as follows:

# Incoming string
log("123",desc="this is title 01")

# Pass in non-string
data = {"test": 123, "time": 123456}
log(data,desc="this is title 02")

# Incoming traceback
try:
    1/0
except Exception as e:
    log(e, desc="This is title 03")
    
# Record timestamp and take a screenshot of the current screen
log("123", timestamp=time.time(), desc="This is title 04", snapshot=True)
How to set the log save path

Airtest provides some global settings, in which LOGFILE is used to customize the name of the txt file that records the log content; LOGDIR is used to customize the save path of the log content, examples are as follows:

from airtest.core.settings import Settings as ST
from airtest.core.helper import set_logdir

ST.LOG_FILE = "log123.txt"
set_logdir(r'D:\test\1234.air\logs')

auto_setup(__file__)
How to filter unnecessary log information

Add settings for log information level at the beginning of the script code:

__author__ = "Airtest"

import logging
logger = logging.getLogger("airtest")
logger.setLevel(logging.ERROR)

After changing the level of output log information to [ERROR], only a small amount of initialization information is output during the entire script running process, which makes it easier to view error messages.

Report
Report generation: simple_report()

Simple interface for generating reports:

simple_report(filepath, logpath=True, logfile='log.txt', output='log.html')

The 4 parameters that can be passed in represent:

  • filepath, the path of the script file, you can directly pass in the variable `file``
  • logpath, the path where the log content is located, if it is True, it will default to the path where the current script is located to find the log content
  • logfile, the file path of log.txt
  • output, the path to the report, must end with .html

Examples are as follows:

from airtest.report.report import simple_report
auto_setup(__file__, logdir=True)

# N use case scripts are omitted here

simple_report(__file__,logpath=True,logfile=r"D:\test\1234.air\log\log.txt",output=r"D:\test\1234.air\log\log1234.html")
Report generation: LogToHtml()

Base class of report:

class LogToHtml(script_root, log_root=``, static_root='', export_dir=None, script_name='', logfile='log.txt', lang='en', plugins=None)

The logtohtml class can pass in many parameters:

  • script_root, script path
  • log_root, the path of the log file
  • static_root, the server path where static resources are deployed
  • export_dir, the storage path of the export report
  • script_name, the script name
  • logfile, the path of the log file log.txt
  • lang, the language of the report (Chinese: zh; English: en)
  • plugins, plug-ins, will be used if poco or airtest-selenium is used

When using logtohtml to generate a test report, we generally first instantiate a logtohtml object, and then use this object to call the class method report() to generate the report. An example is as follows:

from airtest.report.report import LogToHtml

# N use case scripts are omitted here

h1 = LogToHtml(script_root=r'D:\test\1234.air', log_root=r"D:\test\1234.air\log", export_dir=r"D:\test\1234.air" ,logfile= r'D:\test\1234.air\log\log.txt', lang='en', plugins=["poco.utils.airtest.report"])
h1.report()
Screenshot
How to take a screenshot with script

Take a screenshot of the target device and save it to a file. You can pass in the file name of the screenshot, a short description of the screenshot, the compression accuracy of the screenshot, and the maximum size of the screenshot. Examples are as follows:

snapshot(filename="123.jpg",msg="Homepage screenshot",quality=90,max_size=800)
How to take a partial screenshot

Partial screenshots or screenshots by coordinates are a frequently asked question. Airtest provides the crop_image(img, rect) method to help us achieve partial screenshots:

# -*- encoding=utf8 -*-
__author__ = "AirtestProject"

from airtest.core.api import *
# crop_image() method is in airtest.aircv and needs to be introduced
from airtest.aircv import *

auto_setup(__file__)
screen = G.DEVICE.snapshot()

# Partial screenshot
screen = aircv.crop_image(screen,(0,160,1067,551))
# Save partial screenshots to the log folder
try_log_screen(screen)
How to do partial image recognition

Steps to find a partial picture:

  • Take a partial screenshot
  • Define the target screenshot object to find
  • Use the match_in method to find the specified screenshot object in the partial screenshot
from airtest.core.api import *
from airtest.aircv import *
auto_setup(__file__)

screen = G.DEVICE.snapshot()
# Partial screenshot
local_screen = aircv.crop_image(screen,(0,949,1067,1500))

# Set our target screenshot as a Template object
tempalte = Template(r"png_code/settings.png")
# Find the specified image object in the partial screenshot
pos = tempalte.match_in(local_screen)

# Return the coordinates of the image object found (the coordinates are relative to the coordinates of the local screenshot)
print(pos)

# To return the coordinates of the target in the entire screen, both x and y need to be added with the minimum x and y set during the partial screenshot
print(pos[0]+0,pos[1]+949)
How to set the report screenshot accuracy

SNAPSHOT_QUALITY is used to set the global screenshot compression accuracy, the default value is 10, and the value range is [1,100]. Examples are as follows:

from airtest.core.settings import Settings as ST

# Set the global screenshot accuracy to 90
ST.SNAPSHOT_QUALITY = 90

Define the compression accuracy of a single screenshot, example:

# Set the compression accuracy of a single screenshot to 90, and the remaining unset will be based on the global compression accuracy
snapshot(quality=90)
How to set the maximum size of report screenshots

In Airtest1.1.6, a new setting for specifying the maximum size of screenshots is added: ST.IMAGE_MAXSIZE. If it is set to 1200, the length and width of the last saved screenshot will not exceed 1200. Example:

from airtest.core.settings import Settings as ST

# Set the global screenshot size not to exceed 600*600, if not set, the default is the original image size
ST.IMAGE_MAXSIZE = 600

# In the case of not setting separately, the value of the global variable in ST is used by default, that is, 600*600
snapshot(msg="test12")
# Set the maximum size of a single screenshot not to exceed 1200*1200
snapshot(filename="test2.png", msg="test02", quality=90, max_size=1200)
How to specify the path and name for saving screenshots

Take a screenshot of the screen of the current device and save the screenshot in a custom path. This can be achieved in the following ways:

screen = G.DEVICE.snapshot()
pil_img = cv2_2_pil(screen)
pil_img.save(r"D:/test/首页.png", quality=99, optimize=True)
How to make assertions
Assert the existence: assert_exists()

There is an assertion target on the device screen, you need to pass in 1 assertion target (screenshot) and the assertion step information displayed on the report, example:

assert_exists(Template(r"tpl1607324047907.png", record_pos=(-0.382, 0.359), resolution=(1080, 1920)), "Find the Tmall entrance on the homepage")
Assert that does not exist: assert_not_exists()

There is no assertion target on the device screen. Like assert_exists(), you need to pass in an assertion target (screenshot) and the assertion step information displayed on the report, for example:

assert_not_exists(Template(r"tpl1607325103087.png", record_pos=(-0.005, 0.356), resolution=(1080, 1920)), "The icon of Tmall Global does not exist on the current page")
Assert equal: assert_equal()

To assert that two values are equal, you need to pass in the values of the two assertions, and a short description of the assertion that will be recorded in the report:

assert_equal("actual value", "predicted value", "please fill in a short description of the assertion")

It is often used to make an assertion together with the script that poco gets the attribute. Examples are as follows:

assert_equal(poco("com.taobao.taobao:id/dx_root").get_text(), "Tmall new product", "The text attribute value of the control is Tmall new product")

assert_equal(str(poco(text="Tmall new product").attr("enabled")), "True", "The enabled attribute value of the control is True")
Assert that is not equal: assert_not_equal()

Assert that two values are not equal, like assert_equal(), you need to pass in the values of 2 assertions, and a short description of the assertion that will be recorded in the report:

assert_not_equal("actual value", "predicted value", "please fill in a short description of the assertion")

assert_not_equal("1", "2", "Assert that 1 and 2 are not equal")
How to switch between absolute and relative coordinates

Use code to switch between absolute coordinates and relative coordinates:

# Get device screen resolution (vertical screen)
height = G.DEVICE.display_info['height']
width = G.DEVICE.display_info['width']

# Known absolute coordinates [311,1065], converted to relative coordinates
x1 = 311/width
y1 = 1065/height
poco.click([x1,y1])

# Known relative coordinates [0.3,0.55], convert to absolute coordinates
x2 = 0.3*width
y2 = 0.55*height
touch([x2,y2])

# If it is a horizontal screen device, the resolution is as follows
height = G.DEVICE.display_info['width']
width = G.DEVICE.display_info['height']

Determine whether the current screen is horizontal or vertical, and get the resolution of the current screen:

if G.DEVICE.display_info['orientation'] in [1,3]:
    height = G.DEVICE.display_info['width']
    width = G.DEVICE.display_info['height']
else:
    height = G.DEVICE.display_info['height']
    width = G.DEVICE.display_info['width']
How to call other .air scripts

If you want to call a public function encapsulated in another .air script in a .air script, you can do this:

from airtest.core.api import using
# Relative path or absolute path, make sure the code can be found
using("common.air")

from common import common_function
common_function()

If the paths of the sub-scripts that need to be referenced are all placed in a certain directory, you can set a default project root directory PROJECT_ROOT, so that when using the using interface, you can find other sub-scripts in the current root directory without filling in The full path makes it easier to call each other between scripts.

For example, if we create a script named test1.air, the actual path is /User/test/project/test1.air:

from airtest.core.api import *

def test():
    touch("tmp.png")

Another main.air script in the same directory can refer to the test in it like this:

from airtest.core.api import *

ST.PROJECT_ROOT = "/User/test/project"
using("test1.air")
from test1 import test
How to record screen during script running

Currently only supports screen recording on Android devices, please refer to Record the screen while running the script

常见问题与代码示例

English version

如何进行脚本初始化
air脚本:auto_setup()

自动配置运行环境的接口,可以配置当前脚本所在路径、使用的设备、log内容的保存路径、项目根目录和截图压缩精度:

auto_setup(basedir=None, devices=None, logdir=None, project_root=None, compress=None)

接口示例:

auto_setup(__file__)

auto_setup(__file__, devices=["android://127.0.0.1:5037/emulator-5554?cap_method=JAVACAP&&ori_method=MINICAPORI&&touch_method=MINITOUCH"], logdir=True, project_root=r"D\test", compress=90)
如何连接/使用设备
请注意: 更多设备相关的信息,请参考文档
连接设备:connect_device(URI)

连接设备的接口,需要传入用于初始化设备的URI字符串,示例:

# 连接安卓设备
connect_device("Android://127.0.0.1:5037/SJE5T17B17")

# 连接iOS设备
connect_device("iOS:///127.0.0.1:8100")

# 连接Windows窗口
connect_device("Windows:///123456")

# 连接模拟器
connect_device("Android://127.0.0.1:5037/127.0.0.1:62001?cap_method=JAVACAP&&ori_method=ADBORI")
连接设备:init_device()

初始化设备的接口,需要传入设备平台、设备的uuid和可选参数等,其中uuid为,Android的序列号,Windows的窗口句柄,或iOS的uuid:

init_device(platform='Android', uuid=None, **kwargs)

接口使用示例:

# 连接安卓设备
init_device(platform="Android",uuid="SJE5T17B17",cap_method="JAVACAP")

# 连接Windows窗口
init_device(platform="Windows",uuid="123456")
获取当前设备:device()

返回当前正在使用中的设备实例,用法示例如下:

dev = device()
dev.swipe_along([[959, 418],[1157, 564],[1044, 824],[751, 638],[945, 415]])
设置当前设备:set_current()

设置当前的使用设备,可以用于在多设备之间切换使用,示例如下:

# 第一种:传入数字0、1、2等,切换当前操作的手机到Airtest连接的第1台、第2台手机
set_current(0)
set_current(1)

# 第二种:切换当前操作的手机到序列号为serialno1、serialno2的手机
set_current("serialno1")
set_current("serialno2")
如何进行坐标点击/坐标滑动
坐标点击

在设备上进行点击操作,可以传入点击位置、点击次数等参数,不同平台下的可选参数稍有不同,示例如下:

# 传入绝对坐标作为点击位置
touch([100,100])

# 传入Template图片实例,点击截图中心位置
touch(Template(r"tpl1606730579419.png", target_pos=5, record_pos=(-0.119, -0.042), resolution=(1080, 1920)))

# 点击2次
touch([100,100],times=2)

# Android和Windows平台下,可以设置点击时长
touch([100,100],duration=2)
坐标滑动

在设备上进行滑动操作,有2种传参方式,一种是传入滑动的起点和终点,一种是传入滑动的起点和滑动方向vector,示例如下:

# 传入绝对坐标作为滑动的起点和终点
swipe([378, 1460],[408, 892])

# 传入图像作为起点,沿着某个方向滑动
swipe(Template(r"tpl1606814865574.png", record_pos=(-0.322, 0.412), resolution=(1080, 1920)), vector=[-0.0316, -0.3311])

# 常见的还可以设置滑动的持续时长
swipe([378, 1460],[408, 892],duration=1)
如何安装/启动/卸载应用
启动应用:start_app()

在设备上启动目标应用,需传入应用的包名,支持Android和iOS平台,示例:

start_app("com.netease.cloudmusic")
终止应用运行:stop_app()

在设备上终止目标应用的运行,需传入应用的包名,支持Android和iOS平台,示例:

stop_app("com.netease.cloudmusic")
清除应用数据:clear_app()

清理设备上的目标应用数据,需传入应用的包名,仅支持Android平台 ,示例:

clear_app("com.netease.cloudmusic")
安装应用:install()

安装应用到设备上,需传入完整的apk的安装路径,仅支持Android平台,示例:

install(r"D:\demo\tutorial-blackjack-release-signed.apk")
卸载应用:uninstall()

卸载设备上的应用,需传入被卸载应用的包名,仅支持Android平台,示例:

uninstall("com.netease.cloudmusic")
按键事件:keyevent
Android的keyevent

等同于执行 adb shell input keyevent KEYNAME ,示例如下:

keyevent("HOME")
# The constant corresponding to the home key is 3
keyevent("3")  # same as keyevent("HOME")
keyevent("BACK")
keyevent("KEYCODE_DEL")
Windows的keyevent

与安卓不同,Windows平台使用 pywinauto.keyboard module 模块来进行按键输入,示例:

keyevent("{DEL}")

# 使用Alt+F4关闭Windows窗口
keyevent("%{F4}")
iOS的keyevent

目前仅支持HOME键:

keyevent("HOME")
如何输入文本

在设备上输入文本,文本框需要处于激活状态(即先点击文本框,再使用 text() 接口进行输入)。示例如下:

touch(文本框的Template实例)
text("输入的文本")

# 默认情况下,text是带回车的,不需要可以传入False
text("123",enter=False)

# 安卓平台下,还支持输入后点击软键盘的搜索按钮
text("123",enter=False,search=True)
如何删除文本

通过 keyevent 接口删除单个字符:

keyevent("KEYCODE_DEL")
keyevent("67")  # 67即为删除键,请注意传入的是字符串

模拟清空输入框操作:

for i in range(10):
    keyevent("67")

poco的删除(输入框置空):

poco("xxx").set_text("")

log相关
如何记录log到报告中

log() 接口方便插入用户自定义的一些log信息,将会被显示在Airtest报告中。在1.1.6版本的Airtest中,log接口支持传入4个参数:

  • args ,可以是字符串、非字符串或者 traceback 对象
  • timestamp ,用于自定义当前log的时间戳
  • desc ,用于自定义log的标题
  • snapshot ,表示是否需要截取一张当前的屏幕图像并显示到报告中

示例如下:

# 传入字符串
log("123",desc="这是标题01")

# 传入非字符串
data = {"test": 123, "time": 123456}
log(data,desc="这是标题02")

# 传入traceback
try:
    1/0
except Exception as e:
    log(e, desc="这是标题03")
    
# 记录timestamp,并且对当前画面截图
log("123", timestamp=time.time(), desc="这是标题04", snapshot=True)
如何设置log的保存路径

Airtest提供了一些全局的设置,其中 LOGFILE 用于自定义记录log内容的txt文档的名称;LOGDIR 用于自定义log内容的保存路径,示例如下:

from airtest.core.settings import Settings as ST
from airtest.core.helper import set_logdir

ST.LOG_FILE = "log123.txt"
set_logdir(r'D:\test\1234.air\logs')

auto_setup(__file__)
如何过滤不必要的log信息

在脚本代码开头加上 对日志信息等级的设定

__author__ = "Airtest"

import logging
logger = logging.getLogger("airtest")
logger.setLevel(logging.ERROR)

把输出日志信息的级别改成 [ERROR] 以后,整个脚本运行过程中只有少量初始化信息输出,更方便查看报错信息。

报告
报告生成:simple_report()

生成报告的简单接口:

simple_report(filepath, logpath=True, logfile='log.txt', output='log.html')

其中可传入的4个参数分别表示:

  • filepath,脚本文件的路径,可以直接传入变量 __file__
  • logpath ,log内容所在路径,如为 True ,则默认去当前脚本所在路径找log内容
  • logfile ,log.txt的文件路径
  • output ,报告的到处路径,必须以 .html 结尾

示例如下:

from airtest.report.report import simple_report
auto_setup(__file__, logdir=True)

# 此处省略N条用例脚本

simple_report(__file__,logpath=True,logfile=r"D:\test\1234.air\log\log.txt",output=r"D:\test\1234.air\log\log1234.html")
报告生成:LogToHtml()

报告的基类:

class LogToHtml(script_root, log_root='', static_root='', export_dir=None, script_name='', logfile='log.txt', lang='en', plugins=None)

logtohtml 类可以传入的参数非常多:

  • script_root ,脚本路径
  • log_root ,log文件的路径
  • static_root ,部署静态资源的服务器路径
  • export_dir ,导出报告的存放路径
  • script_name ,脚本名称
  • logfile ,log文件log.txt的路径
  • lang ,报告的语言(中文:zh;英文:en)
  • plugins ,插件,使用了poco或者airtest-selenium会用到

使用 logtohtml 生成测试报告时,我们一般先实例化一个 logtohtml 对象,然后用这个对象调用类方法 report() 生成报告,示例如下:

from airtest.report.report import LogToHtml

# 此处省略N条用例脚本

h1 = LogToHtml(script_root=r'D:\test\1234.air', log_root=r"D:\test\1234.air\log", export_dir=r"D:\test\1234.air" ,logfile=r'D:\test\1234.air\log\log.txt', lang='en', plugins=["poco.utils.airtest.report"])
h1.report()
截图相关
如何用脚本截图

对目标设备进行一次截图,并且保存到文件中,可以传入截图文件名、截图的简短描述、截图压缩精度和截图最大尺寸,示例如下:

snapshot(filename="123.jpg",msg="首页截图",quality=90,max_size=800)
如何进行局部截图

局部截图或者说按坐标截图是大家经常会问到的问题,Airtest提供了 crop_image(img, rect) 方法可以帮助我们实现局部截图:

# -*- encoding=utf8 -*-
__author__ = "AirtestProject"

from airtest.core.api import *
# crop_image()方法在airtest.aircv中,需要引入
from airtest.aircv import *

auto_setup(__file__)
screen = G.DEVICE.snapshot()

# 局部截图
screen = aircv.crop_image(screen,(0,160,1067,551))
# 保存局部截图到log文件夹中
try_log_screen(screen)
如何做局部识图

局部找图的步骤:

  • 进行局部截图
  • 定义要查找的目标截图对象
  • 利用 match_in 方法,在局部截图中查找指定的截图对象
from airtest.core.api import *
from airtest.aircv import *
auto_setup(__file__)

screen = G.DEVICE.snapshot() 
# 局部截图
local_screen = aircv.crop_image(screen,(0,949,1067,1500))

# 将我们的目标截图设置为一个Template对象
tempalte = Template(r"png_code/设置.png")
# 在局部截图里面查找指定的图片对象
pos = tempalte.match_in(local_screen)

# 返回找到的图片对象的坐标(该坐标是相对于局部截图的坐标)
print(pos)

# 若要返回目标在整个屏幕中的坐标,则x,y都需要加上局部截图时设置的最小x、y
print(pos[0]+0,pos[1]+949)
如何设置报告的截图精度

SNAPSHOT_QUALITY 用于设置全局的截图压缩精度,默认值为10,取值范围[1,100]。示例如下:

from airtest.core.settings import Settings as ST

# 设置全局的截图精度为90
ST.SNAPSHOT_QUALITY = 90

定义单张截图的压缩精度,示例:

# 设置单张截图的压缩精度为90,其余未设置的将按照全局压缩精度来
snapshot(quality=90)
如何设置报告截图的最大尺寸

在Airtest1.1.6中,新增了一个用于指定截图最大尺寸的设置:ST.IMAGE_MAXSIZE 。假如设置为1200,则最后保存的截图长宽都不会超过1200,示例:

from airtest.core.settings import Settings as ST

# 设置全局截图尺寸不超过600*600,如果不设置,默认为原图尺寸
ST.IMAGE_MAXSIZE = 600

# 不单独设置的情况下,默认采用ST中的全局变量的数值,即600*600
snapshot(msg="test12")
# 设置单张截图的最大尺寸不超过1200*1200
snapshot(filename="test2.png", msg="test02", quality=90, max_size=1200) 
如何指定截图保存的路径和名称

对当前设备的屏幕进行截图,并将截图保存在自定义路径下,可以用下述方式实现:

screen = G.DEVICE.snapshot()  
pil_img = cv2_2_pil(screen)
pil_img.save(r"D:/test/首页.png", quality=99, optimize=True)
如何做断言
断言存在:assert_exists()

设备屏幕上存在断言目标,需要传入1个断言目标(截图)和在报告上显示的断言步骤信息,示例:

assert_exists(Template(r"tpl1607324047907.png", record_pos=(-0.382, 0.359), resolution=(1080, 1920)), "找到首页的天猫入口")  
断言不存在:assert_not_exists()

设备屏幕上不存在断言目标,与 assert_exists() 一样,需要传入1个断言目标(截图)和在报告上显示的断言步骤信息,示例:

assert_not_exists(Template(r"tpl1607325103087.png", record_pos=(-0.005, 0.356), resolution=(1080, 1920)), "当前页不存在天猫国际的icon")  
断言相等:assert_equal()

断言两个值相等,需要传入2个断言的值,还有将被记录在报告中的断言的简短描述:

assert_equal("实际值", "预测值", "请填写断言的简短描述")

常与poco获取属性的脚本一起做断言,示例如下:

assert_equal(poco("com.taobao.taobao:id/dx_root").get_text(), "天猫新品", "控件的text属性值为天猫新品")

assert_equal(str(poco(text="天猫新品").attr("enabled")), "True", "控件的enabled属性值为True")
断言不相等:assert_not_equal()

断言两个值不相等,与 assert_equal() 一样,需要传入2个断言的值,还有将被记录在报告中的断言的简短描述:

assert_not_equal("实际值", "预测值", "请填写断言的简短描述")

assert_not_equal("1", "2", "断言1和2不相等")
如何切换绝对坐标和相对坐标

用代码实现绝对坐标和相对坐标之间的切换:

# 获取设备屏幕分辨率(竖屏)
height = G.DEVICE.display_info['height']
width = G.DEVICE.display_info['width']

# 已知绝对坐标[311,1065],转换成相对坐标
x1 = 311/width
y1 = 1065/height
poco.click([x1,y1])

# 已知相对坐标[0.3,0.55],转换成绝对坐标
x2 = 0.3*width
y2 = 0.55*height
touch([x2,y2])

# 如果是横屏设备的话,则分辨率如下
height = G.DEVICE.display_info['width']
width = G.DEVICE.display_info['height']

判断当前屏幕为横屏还是竖屏,并获取当前屏幕的分辨率:

if G.DEVICE.display_info['orientation'] in [1,3]:
    height = G.DEVICE.display_info['width']
    width = G.DEVICE.display_info['height']
else:
    height = G.DEVICE.display_info['height']
    width = G.DEVICE.display_info['width']
如何调用别的.air脚本

如果想要在一个.air 脚本中,调用另外一个 .air 脚本里封装的公用函数,可以这样做:

from airtest.core.api import using
# 相对路径或绝对路径,确保代码能够找得到即可
using("common.air")

from common import common_function
common_function()

如果需要引用的子脚本路径统一都放在某个目录下,可以通过设定一个默认项目根目录 PROJECT_ROOT ,让使用 using 接口时能够在当前根目录下寻找别的子脚本,无需填写完整路径,让脚本之间相互调用使用更加方便。

例如,我们建立一个名为 test1.air 的脚本,实际路径为 /User/test/project/test1.air :

from airtest.core.api import *

def test():
    touch("tmp.png")

在同一目录下另外一个 main.air 脚本可以这样引用到它里面的 test :

from airtest.core.api import *

ST.PROJECT_ROOT = "/User/test/project"
using("test1.air")
from test1 import test
如何在脚本运行过程中录制屏幕

目前仅支持Android设备的录屏,请参见在运行脚本过程中录屏