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
.
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:
- connects to local android device with
adb
- installs the
apk
application - runs application and takes the screenshot
- performs several user operations (touch, swipe, keyevent)
- 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.
- Using connect_device API you can connect to any android/iOS device or windows application.
- Then perform simulated input to automate your game or app.
- 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¶m2=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¶
- Connect your android phone to your PC with usb
- Use
adb devices
to make sure the state isdevice
- Connect device in Airtest
- 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:
- general APIs: API reference
- Android: airtest.core.android.Android class
- Windows: airtest.core.win.Windows class
- iOS: airtest.core.ios.IOS class
>>> 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.
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¶m2=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("iOS:///127.0.0.1:8100") # iOS device
-
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)
- filename – name of the file where to save the screenshot. If the relative path is provided, the default
location is
-
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)
- v – target to touch, either a
-
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)
- v – target to touch, either a
-
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 v2swipe(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 executingadb 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
: Usepywinauto.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}]
-
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='')[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='')[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")
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¶
-
class
BaseTouch
(adb, backend=False, size_info=None, input_event=None, *args, **kwargs)[source]¶ Bases:
object
A super class for Minitouch or Maxtouch
-
safe_send
(data)[source]¶ Send data to client
Parameters: data – data to send Raises: Exception
– when data cannot be sentReturns: 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
-
-
class
DownEvent
(coordinates, contact=0, pressure=50)[source]¶ Bases:
airtest.core.android.touch_methods.base_touch.MotionEvent
-
class
UpEvent
(contact=0)[source]¶ Bases:
airtest.core.android.touch_methods.base_touch.MotionEvent
-
class
MoveEvent
(coordinates, contact=0, pressure=50)[source]¶ Bases:
airtest.core.android.touch_methods.base_touch.MotionEvent
-
class
SleepEvent
(seconds)[source]¶ Bases:
airtest.core.android.touch_methods.base_touch.MotionEvent
-
class
Maxtouch
(adb, backend=False, size_info=None, input_event=None)[source]¶ Bases:
airtest.core.android.touch_methods.base_touch.BaseTouch
-
class
Minitouch
(adb, backend=False, size_info=None, input_event=None)[source]¶ Bases:
airtest.core.android.touch_methods.base_touch.BaseTouch
-
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
auto_setup
(adb, default_method=None, ori_transformer=None, size_info=None, input_event=None)[source]¶ Parameters: - adb –
airtest.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))
- adb –
-
-
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
-
-
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
-
airtest.core.android.cap_methods package¶
Submodules¶
-
class
AdbCap
(adb, *args, **kwargs)[source]¶
-
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¶
-
-
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
= None¶
-
CMD
= 'LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap'¶
-
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:
-
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:
-
-
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
check_frame
(cap_method)[source]¶ Test whether a frame of image can be obtained correctly
测试能否正确获取一帧图像
Parameters: cap_method – airtest.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: - adb –
airtest.core.android.adb.ADB
- default_method – String such as “MINICAP”, or
airtest.core.android.cap_methods.minicap.Minicap
object
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()
- adb –
-
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'¶
-
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 specifiedReturns: 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 deviceAdbError
– if any other adb error occurs
Returns: command(s) standard output (stdout)
-
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
-
get_status
()[source]¶ Perform adb get-state and return the device status
Raises: AdbError
– if status cannot be obtained from the deviceReturns: 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 timeoutReturns: 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 occurredReturns: 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
Parameters: - local – local file to be copied to the device
- remote – destination on the device where the file will be copied
Returns: None
-
pull
(remote, local)[source]¶ Perform adb pull command :param remote: remote file to be downloaded from the device :param local: local destination where the file will be downloaded from the device
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)[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
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
-
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 supportedReturns: 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 obtainedReturns: (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 detectedReturns: 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 detectedReturns: 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 occursAirtestError
– 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 foundReturns: 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
-
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_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)[source]¶ Perform adb shell dumpsys window windows commands to get window display of application.
Parameters: info – device screen properties Returns: None if adb command failed to run, otherwise return device screen properties(portrait mode) eg. (offset_x, offset_y, screen_width, screen_height)
-
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
-
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
-
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
-
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
-
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
-
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)[source]¶ Return render resolution after rotation
Parameters: refresh – whether to force refresh render resolution 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
¶
-
airtest.core.android.constant module¶
-
class
CAP_METHOD
[source]¶ Bases:
object
-
MINICAP
= 'MINICAP'¶
-
ADBCAP
= 'ADBCAP'¶
-
JAVACAP
= 'JAVACAP'¶
-
airtest.core.android.ime module¶
-
ensure_unicode
(value)[source]¶ Decode UTF-8 values
Parameters: value – value to be decoded Returns: decoded valued
-
class
YosemiteIme
(adb)[source]¶ Bases:
airtest.core.android.ime.CustomIme
Yosemite Input Method Class Object
-
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)¶
-
airtest.core.android.rotation module¶
-
class
XYTransformer
[source]¶ Bases:
object
transform the coordinates (x, y) by orientation (upright <–> original)
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¶
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
-
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
-
setup_proxy
(**kwargs)¶
-
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/')[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
-
uuid
¶
-
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})
-
orientation
¶ return device oritantation status in LANDSACPE POR
-
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
-
snapshot
(filename=None, strType=False, 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: display the screenshot
-
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)
-
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:
-
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
-
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
-
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
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)¶
-
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¶
-
airtest.core.ios.rotation module¶
-
class
XYTransformer
[source]¶ Bases:
object
transform the coordinates (x, y) by orientation (upright <–> original)
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¶
airtest.core.win.win module¶
-
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 statusReturns: 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
-
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: - path – full path to the application
- kwargs – reference: https://pywinauto.readthedocs.io/en/latest/code/pywinauto.application.html#pywinauto.application.Application.start
Returns: None
-
stop_app
(pid)[source]¶ Stop the application
Parameters: pid – process ID of the application to be stopped Returns: None
-
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
-
focus_rect
¶
-
airtest¶
airtest package¶
Subpackages¶
airtest.aircv package¶
-
crop_image
(img, rect)[source]¶ 区域截图,同时返回截取结果 和 截取偏移; Crop image , rect = [x_min, y_min, x_max ,y_max]. (airtest中有用到)
These functions calculate the similarity of two images of the same size.
- Declaration:
- Define all BaseError Classes used in aircv.
-
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.
Detect keypoints with KAZE.
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'¶
-
-
class
AKAZEMatching
(im_search, im_source, threshold=0.8, rgb=True)[source]¶ Bases:
airtest.aircv.keypoint_base.KeypointMatching
AKAZE Matching.
-
METHOD_NAME
= 'AKAZE'¶
-
Detect keypoints with BRIEF/SIFT/SURF. Need opencv-contrib module.
-
class
BRIEFMatching
(im_search, im_source, threshold=0.8, rgb=True)[source]¶ Bases:
airtest.aircv.keypoint_base.KeypointMatching
FastFeature Matching.
-
METHOD_NAME
= 'BRIEF'¶
-
-
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¶
-
-
find_sift
(im_source, im_search, threshold=0.8, rgb=True, good_ratio=0.59)[source]¶ 基于sift进行图像识别,只筛选出最优区域.
airtest.cli package¶
-
get_script_info
(script_path)[source]¶ extract info from script, like basename, __author__, __title__ and __desc__.
Get author title desc.
airtest.core package¶
This package provide Windows Client Class.
-
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 statusReturns: 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
-
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
-
“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 screenshotReturns: 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
¶
-
-
class
MetaDevice
[source]¶ Bases:
type
-
REGISTRY
= {'Android': <class 'airtest.core.android.android.Android'>, 'Device': <class 'airtest.core.device.Device'>}¶
-
error classes
-
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
-
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
= {}¶
-
-
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)
-
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¶
-
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¶
-
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 “”
-
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:
-
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:
- Opens the developer options on the phone, and allows USB debugging
- After using USB to connect the phone, you can see the device using
adb devices
command and refer to Use ADB to see if the phone is successfully connected - On the code and command line, connect the phone with the phone`s serial number, see Use the phone in your code
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 theALLOW 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 islocalhost
or127.0.0.1
adb port
defaults to 5037serialno
is the serial number of the Android phone, such asc2B1c2a7
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
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 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)
clickUpEvent(contact=0)
finger upMoveEvent(coordinates, contact=0, pressure=50)
slide to a coordinateSleepEvent
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.
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 defaultrecording_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 itserialnumber.mp4
- If you specify the filename
--recording test.mp4
and have only one phone, call ittest.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设备连接方法与常见代码示例¶
Android手机连接¶
若使用AirtestIDE进行手机连接,请参考文档
若不打算使用AirtestIDE,可以参考以下步骤:
- 打开手机中的 开发者选项 , 以及 允许USB调试
- 使用USB连上手机后,能够使用
adb devices
命令看到设备,参考使用ADB查看手机是否成功连接 - 在代码和命令行中,使用手机序列号连接手机,参见在代码中使用手机
使用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,默认是本机,也就是localhost
或127.0.0.1
adb port
默认是5037serialno
是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
当我们使用命令行运行脚本时,可以使用--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。
你可以打开手机设置-开发者选项-显示触摸位置
来调试模拟输入的操作,这样做能看到每次点击的位置。
在运行脚本过程中录屏¶
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}")
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 atraceback
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 isTrue
, it will default to the path where the current script is located to find the log contentlogfile
, the file path of log.txtoutput
, 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 pathlog_root
, the path of the log filestatic_root
, the server path where static resources are deployedexport_dir
, the storage path of the export reportscript_name
, the script namelogfile
, the path of the log file log.txtlang
, 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
常见问题与代码示例¶
如何进行脚本初始化¶
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)
如何安装/启动/卸载应用¶
安装应用:install()¶
安装应用到设备上,需传入完整的apk的安装路径,仅支持Android平台,示例:
install(r"D:\demo\tutorial-blackjack-release-signed.apk")
按键事件: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}")
如何输入文本¶
在设备上输入文本,文本框需要处于激活状态(即先点击文本框,再使用 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设备的录屏,请参见在运行脚本过程中录屏