UI Automation Framework for Games and Apps
APACHE-2.0 License
Bot releases are visible (Hide)
ADD:
minicap
对于Android 14
版本的支持ADD:
minicap
support for Android 14
version.Published by yimelia 10 months ago
ADD:
touch
, swipe
接口新增相对坐标的支持
get_clipboard
获取剪贴板内容,set_clipboard
设置剪贴板内容, paste
粘贴set_clipboard
设置到剪贴板之后,再使用paste
粘贴即可touch_method
,来强制指定ADBTOUCH
, 或 MINITOUCH
, MAXTOUCH
dev.touch_method = "ADBTOUCH"
FIX:
Invalid parameter not satisfying: allAttributesForKey != nil
)ADD:
touch
, swipe
interfaces add support for relative coordinates
get_clipboard
gets the clipboard content, set_clipboard
sets the clipboard content, paste
pastesset_clipboard
to set it to the clipboard, and then use paste
to paste it.touch_method
to force specifying ADBTOUCH
, or MINITOUCH
, MAXTOUCH
dev.touch_method = "ADBTOUCH"
FIX:
Invalid parameter not satisfying: allAttributesForKey != nil
)Published by yimelia 11 months ago
LocalDeviceError
,部分接口只有本地USB连接的iOS设备才可以用,远程设备将会抛出这个异常。因此若有需要,可以catch住这个异常,并对远程设备做一些额外的兼容和处理。LocalDeviceError
. Some interfaces can only be used by local USB-connected iOS devices, and the remote device will throw this exception. Therefore, if necessary, you can catch this exception and do some additional compatibility and processing for the remote device.Published by yimelia about 1 year ago
ios:///http://10.240.145.171:20092?name=83282c400efc9122e3bcba60c803cf318a6b3822
android://127.0.0.1:5037/10.227.71.86:20029?name=serialno
adb_path
,例如:from airtest.core.android.android import Android, ADB
adb = ADB(adb_path=r"D:\adb\adb.exe")
# 或者可以初始化一个指定了adb_path的Android设备对象
dev = Android(serialno="5TSSMVBYUSEQNRY5", adb_path=r"D:\test\adb41\adb.exe")
paste
,效果等同于执行 text(get_clipboard())
)text = "test_clipboard"
set_clipboard(text)
get_text = get_clipboard()
print(get_text) # -> test_clipboard
paste() # => text(get_clipboard())
bug修复:
修复了一些小问题
如果遇到了手机画面只有一半的情况,重新连接画面即可恢复。
ios:///http://10.240.145.171:20092?name=83282c400efc9122e3bcba60c803cf318a6b3822
android://127.0.0.1:5037/10.227.71.86:20029?name=serialno
adb_path
, for example:from airtest.core.android.android import Android, ADB
adb = ADB(adb_path=r"D:\adb\adb.exe")
# Or specify adb_path when initializing the Android object
dev = Android(serialno="5TSSMVBYUSEQNRY5", adb_path=r"D:\test\adb41\adb.exe")
paste
, the effect is equivalent to executing text(get_clipboard())
)text = "test_clipboard"
set_clipboard(text)
get_text = get_clipboard()
print(get_text) # -> test_clipboard
paste() # => text(get_clipboard())
bug fixes:
Fixed some minor issues
If you encounter a situation where the screen on your phone is only half full, you can restore the screen by reconnecting.
Published by yimelia over 1 year ago
从airtest v1.3.0起,放弃对python2的支持
iOS设备对象IOS
,新增以下接口的支持:
install
install(r"D:\demo\test.ipa") # install iOS ipa
install("http://www.example.com/test.ipa") # install iOS ipa from url
或
#获取当前设备
dev = device()
#通过本地.ipa文件安装APP
dev.install_app(r"D:\demo\test.ipa") # install iOS ipa
#通过下载链接安装APP
dev.install_app("http://www.example.com/test.ipa") # install iOS ipa from url
uninstall
uninstall("com.netease.cloudmusic")
或
dev = device()
dev.uninstall_app("com.netease.godlike")
list_app
list_app("user") 传入要列出的app类型,可以得到app列表
参数可选user/system/all
分别表示列出用户安装的app/系统app/全部app
返回值示例:[('com.apple.mobilesafari', 'Safari', '8.0'), ...]
dev = device()
#列出全部APP
all_app = dev.list_app("all")
print(all_app)
#打印系统APP
print(dev.list_app("system"))
#列出用户安装的APP
user_app = dev.list_app("user")
print(user_app)
get_clipboard
text = get_clipboard()
print(text)
注意:当iOS设备为远程设备、或者安装了不止一个wda时,需要指定具体的wda_bundle_id
才能使用:
text = get_clipboard(wda_bundle_id="com.WebDriverAgentRunner.xctrunner")
set_clipboard
注意:当iOS设备为远程设备、或者安装了不止一个wda时,需要指定具体的wda_bundle_id
才能使用
set_clipboard("content") # local iOS
# When the iOS device is a remote device, or more than one wda is installed on the device, you need to specify the wda_bundle_id
set_clipboard("content", wda_bundle_id="com.WebDriverAgentRunner.xctrunner")
针对本地USB接入的设备,airtest结合tidevice
的能力,封装了一个TIDevice
对象,提供了几个常用接口如下:
devices
:列出USB连接的所有设备的 UDID 列表list_app
: 列出手机上安装的应用列表,支持对类型进行筛选,包括 user/system/alllist_wda
: 列出手机上安装的所有WDA的bundleIDdevice_info
:获取手机信息install_app
:安装ipa包,支持本地路径或URLuninstall_app
:卸载bundle_id对应的包体start_app
:启动 bundle_id 对应的包体stop_app
:停止 bundle_id 对应的包体ps
: 获取当前的进程列表ps_wda
: 获取当前启动中的WDA列表xctest
:启动wda可以参考:https://github.com/AirtestProject/Airtest/blob/master/tests/test_tidevice.py
代码执行效果示例:
>>> from airtest.core.ios.ios import TIDevice
>>> devices = TIDevice.devices()
>>> print(devices)
['10da21b9091f799891557004e4105ebab3416cb9']
>>> udid = devices[0]
>>> print(TIDevice.list_app(udid))
[ ('com.230316modified.WebDriverAgentRunner.xctrunner', 'wda-Runner', '1.0'),]
>>> print(TIDevice.list_app(udid, "system"))
[('com.apple.calculator', 'Calculator', '1.0.0'),]
>>> print(TIDevice.list_wda(udid))
['com.test.WebDriverAgentRunner.xctrunner']
>>> print(TIDevice.device_info(udid))
{'productVersion': '12.4.8', 'productType': 'iPhone7,2', 'modelNumber': 'MG472', 'serialNumber': 'DNPNW6EJG5MN', 'timeZone': 'Asia/Shanghai', 'uniqueDeviceID': '10da21b9091f799891557004e4105ebab3416cb9', 'marketName': 'iPhone 6'}
>>>
>>> TIDevice.start_app(udid, "com.apple.mobilesafari")
>>> TIDevice.stop_app(udid, "com.apple.mobilesafari")
>>> print(TIDevice.ps(udid))
[ {'pid': 215, 'name': 'MobileMail', 'bundle_id': 'com.apple.mobilemail', 'display_name': 'MobileMail'}]
>>> print(TIDevice.ps_wda(udid))
['com.test.WebDriverAgentRunner.xctrunner']
TIDevice.xctest
接口的执行示例如下:
import threading
wda_bundle_id = TIDevice.list_wda(udid)[0]
# 创建一个线程,执行xctest
t = threading.Thread(target=TIDevice.xctest, args=(udid, wda_bundle_id), daemon=True)
t.start()
time.sleep(5)
ps_wda = TIDevice.ps_wda(udid)
print(ps_wda)
time.sleep(5)
# 终止线程
t.join(timeout=3)
using
接口的作用是,支持在脚本中引用另外一个脚本,同时还能够让airtest正确地读取到其他脚本中的图片路径。
假设目录结构如下:
demo/
foo/
bar.air
baz.air
main.py
如果我们希望在main.py中引用 foo/bar.air
和baz.air
,可以将项目根路径设置到ST.PROJECT_ROOT
,或者确保项目根路径是当前工作目录:
# main.py
from airtest.core.api import *
ST.PROJECT_ROOT = r"D:\demo" # This line can be ignored if it is the current working directory
using("foo/bar.air")
using("baz.air")
如果我们希望在 foo/bar.air
中引用 baz.air
,可以这样写:
# foo/bar.air
from airtest.core.api import *
using("../baz.air")
如果当前未连接任何设备,但又调用了某些需要连接设备才可以调用的接口时,抛出异常:NoDeviceError("No devices added.")
set_focus
,与原先的set_foreground
功能相同From airtest v1.3.0, drop support for python2
iOS adds support for the following interfaces:
install
install(r"D:\demo\test.ipa") # install iOS ipa
install("http://www.example.com/test.ipa") # install iOS ipa from url
or
# Get the current device
dev = device()
#Install APP through local .ipa file
dev.install_app(r"D:\demo\test.ipa") # install iOS ipa
#Install the APP through the download link
dev.install_app("http://www.example.com/test.ipa") # install iOS ipa from url
uninstall
uninstall("com.netease.cloudmusic")
or
dev = device()
dev.uninstall_app("com.netease.godlike")
list_app
list_app("user") Pass in the app type to be listed, and you can get the app list
Optional parameter user/system/all
means to list the app installed by the user/system app/all apps respectively
Return value example: [('com.apple.mobilesafari', 'Safari', '8.0'), ...]
dev = device()
#List all APPs
all_app = dev. list_app("all")
print(all_app)
#Print System APP
print(dev. list_app("system"))
#List the apps installed by the user
user_app = dev. list_app("user")
print(user_app)
get_clipboard
text = get_clipboard()
print(text)
Note: When the iOS device is a remote device, or more than one wda is installed, you need to specify a specific wda_bundle_id
to use:
text = get_clipboard(wda_bundle_id="com.WebDriverAgentRunner.xctrunner")
set_clipboard
Note: When the iOS device is a remote device, or more than one wda is installed, you need to specify a specific wda_bundle_id
to use
set_clipboard("content") # local iOS
# When the iOS device is a remote device, or more than one wda is installed on the device, you need to specify the wda_bundle_id
set_clipboard("content", wda_bundle_id="com.WebDriverAgentRunner.xctrunner")
For devices with local USB access, airtest combines the capabilities of tidevice
to encapsulate a TIDevice
object, providing several common interfaces as follows:
devices
: list the UDIDs of all devices connected by USBlist_app
: Lists the list of apps installed on the phone, supports filtering by type, including user/system/alllist_wda
: list the bundleIDs of all WDAs installed on the phonedevice_info
: get phone informationinstall_app
: install ipa package, support local path or URLuninstall_app
: Uninstall the package body corresponding to bundle_idstart_app
: start the package body corresponding to bundle_idstop_app
: Stop the package body corresponding to bundle_idps
: get the current process listps_wda
: Get a list of WDAs currently bootingxctest
: start wdaYou can refer to: https://github.com/AirtestProject/Airtest/blob/master/tests/test_tidevice.py
Example of code execution effect:
>>> from airtest.core.ios.ios import TIDevice
>>> devices = TIDevice.devices()
>>> print(devices)
['10da21b9091f799891557004e4105ebab3416cb9']
>>> udid = devices[0]
>>> print(TIDevice.list_app(udid))
[ ('com.230316modified.WebDriverAgentRunner.xctrunner', 'wda-Runner', '1.0'),]
>>> print(TIDevice.list_app(udid, "system"))
[('com.apple.calculator', 'Calculator', '1.0.0'),]
>>> print(TIDevice.list_wda(udid))
['com.test.WebDriverAgentRunner.xctrunner']
>>> print(TIDevice.device_info(udid))
{'productVersion': '12.4.8', 'productType': 'iPhone7,2', 'modelNumber': 'MG472', 'serialNumber': 'DNPNW6EJG5MN', 'timeZone': 'Asia/Shanghai', 'uniqueDeviceID': '10da21b9091f799891557004e4105ebab3416cb9', 'marketName': 'iPhone 6'}
>>> TIDevice.start_app(udid, "com.apple.mobilesafari")
>>> TIDevice.stop_app(udid, "com.apple.mobilesafari")
>>> print(TIDevice.ps(udid))
[ {'pid': 215, 'name': 'MobileMail', 'bundle_id': 'com.apple.mobilemail', 'display_name': 'MobileMail'}]
>>> print(TIDevice.ps_wda(udid))
['com.test.WebDriverAgentRunner.xctrunner']
The execution example of the TIDevice.xctest
interface is as follows:
import threading
wda_bundle_id = TIDevice.list_wda(udid)[0]
# Create a thread to execute xctest
t = threading.Thread(target=TIDevice.xctest, args=(udid, wda_bundle_id), daemon=True)
t. start()
time. sleep(5)
ps_wda = TIDevice.ps_wda(udid)
print(ps_wda)
time. sleep(5)
# Terminate thread
t.join(timeout=3)
The function of the using
interface is to support another script to be referenced in the script, and at the same time, it can also allow airtest to correctly read the image path in other scripts.
Suppose the directory structure is as follows:
demo/
foo/
bar.air
baz.air
main.py
If we want to reference foo/bar.air
and baz.air
in main.py, we can set the project root path to ST.PROJECT_ROOT
, or make sure the project root path is the current working directory:
# main.py
from airtest.core.api import *
ST.PROJECT_ROOT = r"D:\demo" # This line can be ignored if it is the current working directory
using("foo/bar. air")
using("baz. air")
If we wanted to reference baz.air
in foo/bar.air
, we could write:
# foo/bar.air
from airtest.core.api import *
using("../baz.air")
If no device is currently connected, but some interfaces that need to be connected to the device are called, an exception will be thrown: NoDeviceError("No devices added.")
set_focus
on the windows platform has the same function as the original set_foreground
Published by yimelia over 1 year ago
Android录屏目前提供两种模式,yosemite
和ffmpeg
,区别如下:
yosemite
:原有的默认模式,录屏清晰度和质量较高,但兼容性较差,部分机型可能有问题
orientation
, max_time
, bit_rate
, bit_rate_level
ffmpeg
: 在1.2.9之后加入的新模式,录屏帧率和质量较低,但兼容性更好,能兼容绝大多数设备
orientation
, max_size
, max_time
, fps
, snapshot_sleep
在1.2.10.2中的改动:
cv2
模式已经被舍弃,因为容易引发错误,效果也不如ffmpeg代码示例:
dev = connect_device("android:///")
dev.start_recording(output="test.mp4", mode="ffmpeg", max_size=800) # Android 支持mode指定使用ffmpeg模式
Android screen recording currently provides two modes, yosemite
and ffmpeg
, the differences are as follows:
yosemite
: the original default mode, the recording resolution and quality are higher, but the compatibility is poor, and some models may have problems
max_time
, orientation
, bit_rate
, bit_rate_level
ffmpeg
: a new mode added after 1.2.9, the screen recording frame rate and quality are lower, but the compatibility is better, compatible with most devices
max_time
, fps
, max_size
, snapshot_sleep
Changes in 1.2.10.2:
cv2
mode provided in 1.2.9 has been abandoned, because it is prone to errors and the effect is not as good as ffmpegCode example:
dev = connect_device("android:///")
dev.start_recording(output="test.mp4", mode="ffmpeg", max_size=800) # Android supports mode to specify the use of ffmpeg mode
Published by yimelia over 1 year ago
if __name__ == "__main__"
的写法了if __name__ == "__main__"
Published by yimelia over 1 year ago
目前录屏功能不仅支持Android设备,还支持了windows、iOS设备!
函数 start_recording()
参数修改如下:
其中大部分参数使用默认值即可,最重要的参数有两个:
代码示例:
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:///")
>>> save_path = dev.start_recording(output="test.mp4")
>>> sleep(30)
>>> dev.stop_recording()
>>> print(save_path)
>>> # the screen is portrait
>>> portrait_mp4 = dev.start_recording(output="portrait.mp4", orientation=1) # or orientation="portrait"
>>> sleep(30)
>>> dev.stop_recording()
>>> # the screen is landscape
>>> landscape_mp4 = dev.start_recording(output="landscape.mp4", orientation=2) # or orientation="landscape"
iOS的初始化字符串中,支持传入名为 serialno/udid/uuid
的字段,用于设置这台iOS的设备udid,示例:
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100") # iOS with mjpeg port
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100&&udid=00008020-001270842E88002E") # iOS with mjpeg port and udid
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100&&uuid=00008020-001270842E88002E") # udid/uuid/serialno are all ok
该名称无论使用udid/uuid/serialno中任何一个名字传入都可以生效,可以在连接后,通过以下方式获取到这个值:
dev = connect_device("iOS:///http://localhost:8100/?uuid=00008020-001270842E88002E")
print(dev.uuid)
增加这个参数的主要原因是,在wda中获取不到ios手机的udid,但在某些情况下可能需要用到这个值,因此支持主动传入保存。
目前支持了Android 13
迭代了windows的snapshot,修复了部分游戏截屏图像重复、黑屏等问题,同时修复了在双屏下的截图区域错误问题。
原先的逻辑是:只要整个运行过程中出现traceback,就认为此次任务运行失败
但通常会遇到一种情况是:在运行过程中会出现一些不太重要的脚本异常,我们希望脚本不卡在这里,而是catch住异常后继续往下跑,只要能跑到最后就算脚本成功。
因此将脚本的成功判断改为:当步骤列表的最后一个步骤有traceback,才认为本次脚本运行失败。
做了一些样式调整,修复了一些显示问题
报告html支持上下左右按键切换预览图片。
Currently, the screen recording function not only supports Android devices, but also supports Windows and iOS devices!
The parameters of the function start_recording()
are modified as follows:
Most of the parameters can use the default values, and there are two most important parameters:
Code example:
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:///")
>>> save_path = dev.start_recording(output="test.mp4")
>>> sleep(30)
>>> dev.stop_recording()
>>> print(save_path)
>>> # the screen is portrait
>>> portrait_mp4 = dev.start_recording(output="portrait.mp4", orientation=1) # or orientation="portrait"
>>> sleep(30)
>>> dev.stop_recording()
>>> # the screen is landscape
>>> landscape_mp4 = dev.start_recording(output="landscape.mp4", orientation=2) # or orientation="landscape"
In the initialization string of iOS, it is supported to pass in a field named serialno/udid/uuid
, which is used to set the udid of this iOS device, for example:
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100") # iOS with mjpeg port
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100&&udid=00008020-001270842E88002E") # iOS with mjpeg port and udid
>>> connect_device("iOS:///http://localhost:8100/?mjpeg_port=9100&&uuid=00008020-001270842E88002E") # udid/uuid/serialno are all ok
The name can take effect no matter which name is used in udid/uuid/serialno, and this value can be obtained in the following way after connection:
dev = connect_device("iOS:///http://localhost:8100/?uuid=00008020-001270842E88002E")
print(dev.uuid)
The main reason for adding this parameter is that the udid of the ios phone cannot be obtained in wda, but this value may be needed in some cases, so it is supported to actively pass in and save.
Currently supports Android 13
Iterated the snapshot of windows, fixed some game screenshot image duplication, black screen and other problems, and also fixed the wrong area of the screenshot under dual screen.
The original logic is: as long as a traceback occurs during the entire running process, it is considered that the task failed.
But there is usually a situation where some unimportant script exceptions will appear during the running process. We hope that the script will not get stuck here, but continue to run after catching the exception. As long as it can run to the end, it will be considered as a script. success.
Therefore, the success judgment of the script is changed to: When the last step in the step list has a traceback, the script is considered to have failed.
Made some style adjustments and fixed some display issues
The report html supports up, down, left, and right buttons to switch the preview image.
Published by yimelia about 2 years ago
1.2.7版本主要是新增了设备释放接口、大量断言的语句,新增了对Android 12L的支持,对安装接口的增强,和若干bug的修复。
device.disconnect()
接口原先的Airtest,在脚本长时间运行、或是使用了AirtestIDE反复连接多个不同手机时,可能会 建立大量adb连接未释放 ,一直占用资源。
这也会导致在部分手机上,反复切换横屏和竖屏应用时,会有概率出现 屏幕一半内容变成黑屏 的问题。
因此,1.2.7版本的Airtest新增了device.disconnect()
接口,用于:
dev.disconnect()
,如果还要继续使用这个设备对象,最好重新再创建一次 dev = connect_device("android:///")
在脚本编写中,断言语句是非常重要的组成部分,但airtest旧版只支持 assert_exists
和 assert_equal
两种类型的断言语句。
现在Airtest1.2.7版本,将所有断言语句单独放在 airtest/core/assertions.py
中,增加了更多类型,方便脚本编写工作。
目前Airtest1.2.7支持的断言列表: assertions
assert_exists
assert_not_exists
assert_equal
assert_not_equal
assert_true
assert_false
assert_is
assert_is_not
assert_is_none
assert_is_not_none
assert_in
assert_not_in
assert_is_instance
assert_not_is_instance
assert_greater
assert_greater_equal
assert_less
assert_less_equal
Airtest1.2.7除了让断言语句更加丰富以外,还支持设置断言时截取当前画面的图片,然后显示在Airtest报告中,这样报告的断言内容会更加清晰,也更具有airtest的截图特色:
# 默认情况下,断言截图会开启
assert_exists()
# 如不需要断言时截取当前画面,则可以设置关闭断言的截图
assert_exists(截图, snapshot=False)
已增加 minicap
对android 12L的支持,Poco的支持可以等待poco后续的更新。
pm_install
的增强对 pm_install
接口进行了较大的增强:
adb.install
保持一致),adb.pull()
和 adb.push()
接口,支持了中文路径、包含斜杠的路径(比如 \g
这样的字符也会有问题)、包含特殊符号(空格、括号等)的路径pm_install
安装完毕后,会进行 adb shell rm apk
的操作,超时时间30秒如果希望把自定义的函数显示到airtest的报告中,可以使用@logwrap
,例如:
@logwrap
def func1():
pass
如果希望在报告显示func1
内容的同时,还附带一张当前设备的截图的话,可以增加snapshot=True
参数在func1()
的定义中:
@logwrap
def func1(snapshot=True):
pass
adb.text()
在输入字母+数字时可能会导致乱序的问题,同时支持空格airtest.core.win.Windows
对象时,允许开发者选择性跳过 connect()
方法中的 set_foreground()
功能 #1068Android.get_render_resolution
中增加应用包名参数,get_render_resolution
能够获取到除top activity以外的应用的渲染区域 #1070pip install -U airtest
Version 1.2.7 mainly added device release interface, a large number of assertion statements, added support for Android 12L, enhanced installation interface, and fixed several bugs.
device.disconnect()
interfaceThe original Airtest, when the script runs for a long time, or uses AirtestIDE to repeatedly connect to multiple different mobile phones, may establish a large number of adb connections but not release, which will always occupy resources.
This will also lead to the problem of half of the screen becoming a black screen when switching between landscape and portrait applications repeatedly on some mobile phones.
Therefore, version 1.2.7 of Airtest has added the device.disconnect()
interface for:
dev.disconnect()
, if you want to continue to use this device object, it is best to recreate it again dev = connect_device(" android:///")
In scripting, assertion statement is a very important part, but the old version of airtest only supports assert_exists
and assert_equal
two types of assertion statement.
Now Airtest 1.2.7 version, put all assertion statements in airtest/core/assertions.py
separately, adding more types to facilitate scripting work.
List of assertions currently supported by Airtest1.2.7: assertions
assert_exists
assert_not_exists
assert_equal
assert_not_equal
assert_true
assert_false
assert_is
assert_is_not
assert_is_none
assert_is_not_none
assert_in
assert_not_in
assert_is_instance
assert_not_is_instance
assert_greater
assert_greater_equal
assert_less
assert_less_equal
In addition to enriching the assertion statement, Airtest 1.2.7 also supports capturing a picture of the current screen when setting an assertion, and then displaying it in the Airtest report, so that the assertion content of the report will be clearer and more characteristic of airtest screenshots:
# By default, assertion screenshots are enabled
assert_exists()
# If you do not need to take a screenshot of the current screen when asserting, you can set a screenshot of closing the assertion
assert_exists(screenshot, snapshot=False)
Added minicap
support for android 12L, Poco support can wait for poco's subsequent updates.
pm_install
Major enhancements to the pm_install
interface:
adb.install
),adb.pull()
and adb.push()
interfaces, supports Chinese paths, paths containing slashes (such as \g
and other characters will also problem), paths that contain special symbols (spaces, brackets, etc.)pm_install
is installed, the adb shell rm apk
operation will be performed with a timeout of 30 secondsIf you want to display a custom function in the airtest report, you can use @logwrap
, for example:
@logwrap
def func1():
pass
If you want the report to display the contents of func1
and also attach a screenshot of the current device, you can add the snapshot=True
parameter to the definition of func1()
:
@logwrap
def func1(snapshot=True):
pass
adb.text()
could cause out-of-order when entering letters + numbers, while supporting spacesairtest.core.win.Windows
object, allow developers to selectively skip set_foreground()
function in connect()
method #1068Android.get_render_resolution
,get_render_resolution
to get the rendering area of applications other than top activity #1070pip install -U airtest
Published by yimelia over 2 years ago
相关注意事项:
极少部分设备上,可能点击位置会有偏移,目前在AirtestIDE上无法修正鼠标点击的偏移,但是可以在代码中修复,例如:
我们测试到一台iPhone 7Plus手机,在点击时有坐标偏移的现象,因此通过如下方式在运行代码时可以修正:
>>> device = connect_device("iOS:///")
>>> device.touch((100, 100)) # wrong position
>>> print(device.touch_factor)
0.333333
>>> device.touch_factor = 1 / 3.3 # default is 1/3
>>> device.touch((100, 100))
关于touch_factor
的解释:
touch_factor
这个值用于换算iOS设备的点击坐标:手机真实坐标 = touch_factor * 屏幕坐标
默认计算方式是:self.display_info['window_height'] / self.display_info['height']
但在部分特殊型号手机上可能不准确,例如iOS14.4的7P,默认值为 1/3,但部分7P点击位置不准确,可自行设置为:self.touch_factor = 1 / 3.3
Poco相关的注意事项:
start_app
来打开,但本接口目前必须传入手机中已有的app包名,如果传入的包名不存在,可能会导致报错mstpl
的识别效果adb.file_size
接口获取文件大小失败的问题Related Notes:
On a very small number of devices, the click position may be offset. At present, the offset of the mouse click cannot be corrected on AirtestIDE, but it can be fixed in the code, for example:
We tested an iPhone 7Plus mobile phone, and there is a coordinate offset phenomenon when clicking, so it can be corrected when running the code in the following way:
>>> device = connect_device("iOS:///")
>>> device.touch((100, 100)) # wrong position
>>> print(device.touch_factor)
0.333333
>>> device.touch_factor = 1 / 3.3 # default is 1/3
>>> device.touch((100, 100))
Explanation about touch_factor
:
touch_factor
This value is used to convert the touch coordinates of iOS devices:Phone real coordinates = touch_factor * screen coordinates
The default calculation is:self.display_info['window_height'] / self.display_info['height']
But it may be inaccurate on some special models of mobile phones, such as 7P of iOS14.4, the default value is 1/3, but the click position of some 7P is inaccurate, you can set it yourself: self.touch_factor = 1 / 3.3
Poco related notes:
start_app
to open it, but this interface must be transferred to the mobile phone. For some app package names, if the incoming package name does not exist, an error may be reportedmstpl
adb.file_size
interface fails to obtain the file size under the Android 6.0.1 systemPublished by yimelia almost 3 years ago
Fix:
adb shell input text
输入(不支持中文)wake
接口先尝试使用keyevent224
和82
解锁android屏幕,如果解锁失败,再尝试用yosemite解锁Add:
Fix:
adb shell input text
instead (Chinese is not supported)wake
interface first try to use keyevent224
and 82
to unlock the android screen, if the unlocking fails, try to unlock it with yosemiteAdd:
Android 12
minicap screenshot supportPublished by yimelia about 3 years ago
主要改动:
Published by yimelia about 3 years ago
本次更新以bug修复、图像识别效果提升为主,更新内容如下:
mstpl
算法,提升了判定的严格程度,可以有效降低当目标图片不在当前画面中的误检率tpl
算法被添加回设置里,可以在mstpl失败时作为补充方案adb.pm_install
接口中增加安装完毕后自动删除apk包的功能,避免调用完之后没清理,残留大量apk包的问题This update focuses on bug fixes and improved image recognition effects. The update content is as follows:
mstpl
algorithm to improve the strictness of the judgment, which can effectively reduce the false detection rate when the target picture is not in the current picturetpl
algorithm is added back to the settings, which can be used as a supplementary solution when mstpl failsadb.pm_install
interface to avoid the problem of a large number of apk packages that are not cleaned up after the call is completedPublished by yimelia over 3 years ago
我们新增了一个改良版本的模板匹配识别算法,能够大幅度增加原有的模板匹配的成功率,更好地适配分辨率变化的场景。
将Airtest更新至1.2.0以上版本即可使用,如果您正在使用AirtestIDE,也请同步更新至1.2.10以上版本,最新的版本已经将该算法设置为首选使用的算法。
请参考以下代码示例:
from airtest.core.api import *
touch(Template("search.png", scale_max=800, scale_step=0.005))
在Template图片对象初始化时,与图像识别有关的参数如下:
threshold
:用于设置图像识别的筛选阈值,默认为0.8,因此需要图像识别效果大于0.8时,才会认为此次识别是成功的rgb
:是否要进行彩色识别,默认为False,意思是airtest默认会将图片处理为灰度图片,因此如果需要加入彩色三通道的识别,需要将它设置为Truescale_max
:新算法专用参数,用于调节匹配的最大范围,如果要查找的目标UI很小的话,可以适当增大这个数值,默认值 800, 推荐值 740, 800, 1000 取值范围 [700 , 2000]scale_step
:新算法专用参数,用于控制搜索比例步长,如果要查找的目标UI很小的话,可以适当减小这个数值,默认值0.005,推荐值 0.02, 0.005, 0.001 取值范围 [0.001, 0.1]如果在图像识别时遇到问题或异常报错,请将当前界面截图、与脚本中使用的图片一起提交issue。
在Airtest 1.2.0以上版本中,我们不再希望大家连接手机时,手动指定各连接参数了,包括cap_method
,touch_method
和ori_method
。
因此我们进行了一些改动,在初始化手机时,如果遇到问题,Airtest将会自动尝试进行兼容,并选取备用方案进行连接,直到成功为止。
目前Android12暂时还没有很好地支持,屏幕画面效果很差
新增Android.screen_proxy,类似于之前的touch_proxy,统一使用它作为屏幕截图方法的调用入口
初始化Android()对象时,可以不再强制指定cap_method="MINICAP"
或"JAVACAP"
,screen_proxy
会自动按照顺序进行初始化,直到选取到可以成功初始化的截图方法。
use javacap
,或是在脚本运行时指定cap_method=JAVACAP
,现在可以不指定,也能成功初始化cap_method=MINICAP_STREAM
这个参数,请不要再传MINICAP_STREAM
这个值
dev.minicap
,将会返回dev.screen_proxy
对象,依然可以使用dev.minicap.get_frame_from_stream()
接口dev.cap_method
,将会返回当前使用的截图方法名称(比如"MINICAP"
),同样也可以使用dev.cap_method = "JAVACAP"
来强制指定截图方法在获取图片时,再也不需要进行大量的类型判断然后调用对应的截图方法了
直接使用dev.screen_proxy.get_frame_from_stream()
即可
即以前的这种代码可以废弃了:
if dev.cap_method == CAP_METHOD.MINICAP:
dev.minicap.get_frame_from_stream()
elif dev.cap_method == xxx:
...
如果希望实现自定义的新截图方法:在airtest.core.android.cap_methods.base_cap
中,实现了所有截图方法的基类BaseCap
,可以通过继承它,并实现get_frame_from_stream
这个接口,就能新增一个自定义的截图方法,将它注册到ScreenProxy中就可以使用了
from airtest.core.android.cap_methods.base_cap import BaseCap
class TestCap(BaseCap):
def get_frame_from_stream(self):
return b"frame"
ScreenProxy.register_method("TESTCPY", TestCap)
# 默认优先初始化为自定义的TestCap
cap = ScreenProxy.auto_setup(dev.adb)
原先的android.get_display_info()
默认会返回minicap.get_display_info()
,现在改为默认直接返回adb.get_display_info()
https://github.com/AirtestProject/Airtest/pull/913/commits/43a9c56813641b01a1489bd3174db330183135ba
ori_method=ADBORI
这个参数真正只与屏幕旋转方向做关联,默认情况下使用rotation_watcher.jar
来获取屏幕方向,如果失败了,则可以指定此参数改为每隔2秒使用ADB获取一次当前屏幕旋转方向(一般是一些车机设备/特殊平板等设备)。原先的逻辑里,ADBORI的指定有可能是因为该设备minicap初始化失败,也可能是rotation_watcher拿到的屏幕方向不对,会造成问题难以排查。所有截图方法都包含有snapshot()
这个接口,默认会处理截取的图片,返回一个cv2的图片,去掉了android.snapshot
里的大量类型判断。
projection
参数,用来调整屏幕图的大小,方便IDE中使用该接口拿到手机原始图片进行截图 https://github.com/AirtestProject/Airtest/pull/913/commits/d3fb6a6c2d85947146b5ede3e5fe6c476e7c38a7
与screen_proxy
类似,为touch_proxy
添加了auto_setup
逻辑,在初始化手机时,会先尝试初始化minitouch,如果失败会尝试maxtouch,最后选择adbtouch,这样可以避免一些机型虽然不是android10,但是也需要使用maxtouch的问题 https://github.com/AirtestProject/Airtest/pull/913/commits/e4efe9e8fc0801350b8398776e5457041ced4b38
为上述改动增加了对应的单元测试用例
解决了在连接过程中,由于失败可能导致的socket未关闭或subprocess未关闭输入输出流的问题
auto_kill
参数,在手机断开连接时,能自动杀掉socket,避免内存泄露的问题 https://github.com/AirtestProject/Airtest/commit/b3ff533d2aeaff06d23bd2b1d47d511cd3890a7b
We have added an improved version of the template matching recognition algorithm, which can greatly increase the success rate of the original template matching and better adapt to scenes with changing resolutions.
Update Airtest to version 1.2.0 or higher. If you are using AirtestIDE, please also update to version 1.2.10 or higher. The latest version has set this algorithm as the preferred algorithm.
Please refer to the following code example:
from airtest.core.api import *
touch(Template("search.png", scale_max=800, scale_step=0.005))
When the Template image object is initialized, the parameters related to image recognition are as follows:
threshold
: used to set the screening threshold of image recognition, the default is 0.8, so the recognition effect is required to be greater than 0.8 before the recognition is considered successfulrgb
: Whether to perform color recognition, the default is False, which means that airtest will process the picture as a grayscale picture by default, so if you need to add color three-channel recognition, you need to set it to Truescale_max
: new algorithm special parameter, used to adjust the maximum range of matching, If the target UI to be searched is small, you can increase this value appropriately, the default value is 800, the recommended value is 740, 800 , 1000 Value range [700, 2000]scale_step
: a new algorithm dedicated parameter, used to control the search scale step size, If the target UI to be found is small, you can appropriately reduce this value, the default value is 0.005, the recommended value is 0.02, 0.005 , 0.001 Value range [0.001, 0.1]If you encounter problems or abnormal errors during image recognition, please take a screenshot of the current interface and submit an issue together with the pictures used in the script.
In Airtest 1.2.0 and above, we no longer want everyone to manually specify the connection parameters when connecting to the phone, including cap_method
, touch_method
, and ori_method
.
Therefore, we have made some changes. When initializing the phone, if there is a problem, Airtest will automatically try to be compatible and select a backup plan to connect until it succeeds.
Android.screen_proxy
, which is similar to the previous touch_proxy and uses it as the call entry of the screenshot method.cap_method="MINICAP"
or "JAVACAP"
, screen_proxy
will automatically initialize in order until the screenshot method that can be successfully initialized is selected .
use javacap
on the IDE, or specify cap_method=JAVACAP
when the script is running. Now it is not necessary to specify it, and it can be initialized successfully.cap_method=MINICAP_STREAM
, please do not pass the value of MINICAP_STREAM
again
custom screenshot method
> MINICAP
> JAVACAP
> ADBCAP
. If ADBCAP is called, a warning will be printed to tell the user that the screenshot efficiency is very low at this time.dev.minicap
will return the dev.screen_proxy
object, and the dev.minicap.get_frame_from_stream()
interface can still be useddev.cap_method
will return the name of the currently used screenshot method (such as "MINICAP"
), and you can also use dev.cap_method = "JAVACAP"
to force the specified screenshot methoddev.screen_proxy.get_frame_from_stream()
directlyif dev.cap_method == CAP_METHOD.MINICAP:
dev.minicap.get_frame_from_stream()
elif dev.cap_method == xxx:
...
airtest.core.android.cap_methods.base_cap
, the base class BaseCap
, which implements all screenshot methods, can be inherited and implement the interface get_frame_from_stream
. A custom screenshot method can be added, and it can be used by registering it in ScreenProxy
from airtest.core.android.cap_methods.base_cap import BaseCap
class TestCap(BaseCap):
def get_frame_from_stream(self):
return b"frame"
ScreenProxy.register_method("TESTCPY", TestCap)
# The default priority is initialized to the custom TestCap
cap = ScreenProxy.auto_setup(dev.adb)
nbsp
added an auto_kill
parameter, which can automatically kill the socket when the phone is disconnected to avoid memory leaksSIFT
algorithm patent has been lifted, so the SIFT algorithm has been re-added as the default algorithm, but it is limited by the version number of OpenCV. Not all version numbers can be used directly https://github.com/AirtestProject/Airtest/commit/c8e9bba038b3bb1b5201bb336b5f99a1f5f7c71a
Published by yimelia over 3 years ago
pypi打包版本补充了缺失的ios资源文件
py2不再要求安装facebook-wda
库,避免了安装过程中可能因为第三方库依赖py3而报错(airtest的ios模块,在py2下无法使用)
修复了在极少数情况下可能会获取不到手机渲染分辨率,导致获取的手机尺寸为0的问题
rotationwatcher.jar
缩减包体大小到7kb
恢复了iOS手机端口转发功能,可以使用iOS上面的unity-poco了(linux下如果是ubuntu,可以运行apt-get install libusbmuxd-tools)
增加了一个自动chmod +x的操作,能自动为adb和iproxy文件增加可执行权限
修正了一些wda兼容性的问题
The pypi packaged version supplements the missing ios resource files
py2 no longer requires the installation of the facebook-wda
library, which avoids errors that may be reported during the installation process due to third-party libraries relying on py3 (airtest's ios module cannot be used under py2)
Fixed the issue that in rare cases the rendering resolution of the phone may not be obtained, resulting in the size of the obtained phone being 0
rotationwatcher.jar
reduces the package size to 7kb
The port forwarding function of iOS mobile phones has been restored, and unity-poco on iOS can be used (if it is ubuntu under linux, you can run apt-get install libusbmuxd-tools)
Added an automatic chmod +x operation, which can automatically increase executable permissions for adb and iproxy files
Fixed some wda compatibility issues
iproxy
,在终端中运行:brew install usbmuxd
RotationWatcher.apk
的安装,减少一个安装程序rgb=True
参数时的效果,现在能够更好地识别出不同颜色图片了adb.file_size
不能正确获取到文件大小的bugiproxy
and run in the terminal: brew install usbmuxd
RotationWatcher.apk
is removed, reducing one installation procedurergb=True
parameter, and now it can better recognize pictures with different colorsadb.file_size
could not get the file size correctly重做了airtest/core/ios模块,主要改动如下:
支持Appium的WebDriverAgent工具,因此能够支持更新版本的iOS(>=14)以及新版本的xcode
Appium的WebDriverAgent与我们的iOS-Tagent,只需要选择其中一个部署即可,若原先已经部署了iOS-Tagent,请更新至最新版本
重要: 由于facebook-wda
只支持python3,因此假如想升级到这个版本,更好地使用ios模块以及下方提及的接口的话,必须使用python3
新增了弹窗相关接口:
alert_accept
:适用于拥有2个按钮的iOS弹窗,会点击弹窗右边的按钮,通常是“同意”或者“好”
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
# 点击弹窗右边的按钮
ios.alert_accept()
alert_dismiss
:适用于拥有2个按钮的iOS弹窗,会点击弹窗左边的按钮,例如“不同意”
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
# 点击弹窗左边的按钮
ios.alert_dismiss()
alert_buttons
:以列表形式返回弹窗的按钮文字
# 返回设备弹窗的按钮的文字
ios.alert_buttons()
alert_click
:点击弹窗上的指定按钮
# 点击弹窗上面的指定按钮,可传入列表按顺序查找
ios.alert_click(['设置', '允许', '好'])
alert_exists
:判断弹窗是否存在
ios.alert_exists()
alert_watch_and_click
:监控弹窗出现并点击指定按钮
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
# 默认情况下监控此类弹窗:["使用App时允许", "好", "稍后", "稍后提醒", "确定", "允许", "以后"]
with ios.alert_watch_and_click():
sleep(5)
# 监控指定弹窗出现并点击
with ios.alert_watch_and_click(["Cancel"]):
sleep(5)
# 设置监控的时间间隔为2.0s
with ios.alert_watch_and_click(interval=2.0):
sleep(5)
alert.text
: 返回弹窗上面的描述文字
# 返回弹窗上面的描述文字
print(ios.driver.alert.text)
keyevent
接口增加音量控制事件
支持使用 keyevent
接口对iOS设备的音量进行加减控制:
# 音量增加
keyevent("volumeUp")
# 音量减少
keyevent("volumeDown")
app_state
接口返回包体状态
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
返回当前运行应用
print(ios.app_current())
# output is {"pid": 1281,
"name": "",
"bundleId": "com.netease.cloudmusic"}
加锁相关接口
is_locked
当前是否锁屏
unlock
解锁设备
lock
为设备锁屏
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
# 判断当前iOS设备是否上锁
print(ios.is_locked())
ios.unlock()
ios.lock()
device_info
返回设备信息
print(ios.device_info())
>>> AttrDict({
'timeZone': 'GMT+0800',
'currentLocale': 'zh_CN',
'model': 'iPhone',
'uuid': '90CD6AB7-11C7-4E52-B2D3-61FA31D791EC',
'userInterfaceIdiom': 0,
'userInterfaceStyle': 'light',
'name': 'iPhone',
'isSimulator': False})
home_interface
判断是否在home桌面
print(ios.home_interface())
其他ios相关的bug修复和优化:
1b85fc7
b1c8568
f1f095c
a6e8f68
Reworked the airtest/core/ios module, the main changes are as follows:
Support Appium's WebDriverAgent tool, so it can support updated versions of iOS (>=14) and new versions of xcode
Appium’s WebDriverAgent and our iOS-Tagent, you only need to choose one of them to deploy. Yes, if iOS-Tagent is already deployed, please update to the latest version
Important: Since facebook-wda
only supports python3, if you want to upgrade to this version and better use the ios module and the interfaces mentioned below, you must use python3
Added pop-up related interfaces:
alert_accept
: Applicable to iOS pop-up windows with 2 buttons, you will click the button on the right side of the pop-up window, usually "Agree" or "OK"
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
ios.alert_accept()
alert_dismiss
: Applicable to iOS pop-up windows with 2 buttons, you will click the button on the left side of the pop-up window, such as "disagree"
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
ios.alert_dismiss()
alert_buttons
: return the button text of the pop-up window as a list
ios.alert_buttons()
alert_click
: Click the specified button on the pop-up window
# Click the specified button on the pop-up window, you can enter the list and search in order
ios.alert_click(['Settings','Allow','OK'])
alert_exists
: Determine whether the pop-up window exists
alert_watch_and_click
: The monitoring pop-up window appears and click the specified button
from airtest.core.ios.ios import IOS, wda
ios = IOS("http://localhost:8100/")
# This type of pop-up window is monitored by default: ["Allow when using App", "OK", "Later", "Remind later", "OK", "Allow", "Later"]
with ios.alert_watch_and_click():
sleep(5)
# Monitor the specified pop-up window appears and click
with ios.alert_watch_and_click(["Cancel"]):
sleep(5)
# Set the monitoring interval to 2.0s
with ios.alert_watch_and_click(interval=2.0):
sleep(5)
alert.text
: Return the description text on the pop-up window
print(ios.driver.alert.text)
keyevent
interface adds volume control events
Support using the keyevent
interface to control the volume of iOS devices:
# 音量增加
keyevent("volumeUp")
# 音量减少
keyevent("volumeDown")
The app_state
interface returns the package state
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
Lock related interface
is_locked
whether the screen is currently locked
unlock
to unlock the device
lock
to lock the device screen
from airtest.core.ios.ios import IOS
ios = IOS("http://localhost:8100/")
# Determine whether the current iOS device is locked
print(ios.is_locked())
ios.unlock()
ios.lock()
device_info
returns device information
print(ios.device_info())
>>> AttrDict({
'timeZone': 'GMT+0800',
'currentLocale': 'zh_CN',
'model': 'iPhone',
'uuid': '90CD6AB7-11C7-4E52-B2D3-61FA31D791EC',
'userInterfaceIdiom': 0,
'userInterfaceStyle': 'light',
'name': 'iPhone',
'isSimulator': False})
home_interface
determines whether it is on the home desktop
print(ios.home_interface())
Other iOS related bug fixes and optimizations:
RotationWatcher.apk
is not installed successfully, use adb to obtain ori information, and add the logic of using ADB thread to continuously obtain ori information [1b85fc7
](https://github.com /AirtestProject/Airtest/commit/1b85fc7c26813e0b6c429cadb48adef5362943ed)Yosemite.apk
fails to install (if you have already installed the old version, you can skip the installation), it can also ensure the operation of basic functions [b1c8568
](https://github.com/AirtestProject/Airtest/ commit/b1c8568792bd710674a64c6a45b0566dafde1a60) f1f095c
a6e8f68
Published by yimelia almost 4 years ago
在命令行airtest run xx.air
的时候,新增一个参数 --no-image
,只要在运行时传入这个参数,就能够在任务运行过程中不再保存截图 https://github.com/AirtestProject/Airtest/commit/2ed128c201be94d1fda0f364641296bec7e68a52 , 示例:
airtest run test.air --device Android:/// --log logs/ --no-image
目前settings新增了一个配置ST.SAVE_IMAGE
,默认为True
, 如果改为False
,就不保存截图,直到这个值再次设为True
,示例:
from airtest.core.api import *
# 暂时关闭截图
ST.SAVE_IMAGE = False
touch((100, 100)) # 这条语句将不会保存当前画面图片
# 继续截图
ST.SAVE_IMAGE = True
touch((100, 100))
--no-image
参数时,实际上也是将ST.SAVE_IMAGE
设为False
,因此第二种方式会更加灵活,大家可以在脚本运行过程中自由决定当前是否要保存图片当调用log()
接口来保存对应log到报告中时,也同时将它print到当前终端,方便查看。 https://github.com/AirtestProject/Airtest/commit/b7d98f640fb3ddad339efe2617270488e8ec83c6
去掉了requirements.txt
里opencv-contrib-python
的版本依赖,目前python3.8和python3.9都能安装了。
注意:python3.9如果安装完毕还不能使用airtest,报错ImportError: numpy.core.multiarray failed to import
,可以手工将numpy
版本号降级至1.19.3
就能使用了。
Android的录屏接口,start_recording
修改了参数,增加了一个更简单的bit_rate_level
,可以设置1-5的清晰度级别,默认为1,数字越大会越清晰 https://github.com/AirtestProject/Airtest/pull/834/commits/2220863d9f82e066c9543b3a1f34d7242fdd75c4 , 示例:
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")
更多示例,请参考文档
重新整理了LogToHtml
里面路径相关的参数logfile
和logdir
,现在支持通过修改ST.LOG_DIR
和ST.LOG_FILE
,来自主设置log文件夹和log.txt的文件名。修改完毕后,还可以直接用LogToHtml
生成报告,同时简化了参数的传递 https://github.com/AirtestProject/Airtest/pull/834/commits/a4b43cb824d9d99855d80a0055ba09694889744c , 示例:
from airtest.report.report import LogToHtml
# 假设脚本为当前目录下的run.air, log目录为当前目录下的./log
# 默认将认为log存放在ST.LOG_DIR中,如果ST.LOG_DIR为空,则尝试寻找当前目录下的log文件夹
rpt = LogToHtml("test.air")
rpt.report()
自定义ST.LOG_DIR
和ST.LOG_FILE
的示例:
from airtest.core.helper import set_logdir
new_logfile = "log123.txt"
new_logdir = "./logs_new"
# set logfile = ./logs_new/log123.txt
ST.LOG_FILE = new_logfile
set_logdir(new_logdir)
# ...
rpt = LogToHtml("test.air")
# LogToHtml将会默认选择ST.LOG_FILE作为logfile,ST.LOG_DIR作为log_root,生成对应的log.html内容
rpt.report()
adb.start_app_timing
获取不到app启动时间的问题 https://github.com/AirtestProject/Airtest/commit/002a17077a846010eec69093bfe42abdb094035f
get_top_activity
在获取含有$
符号的包名时会报错的问题(java允许命名时出现$符号) https://github.com/AirtestProject/Airtest/commit/c9e00e878c7aef6f0cc4f5ff2faa9caf82ae5c4f
adb.file_size
更换了获取文件大小的命令,兼容更低版本的android手机,顺便修改了minitouch和maxtouch的安装过程,更简洁一点 https://github.com/AirtestProject/Airtest/commit/75e4665d2dcfc14993a1a8935fba6112dfa2fbb6
generator already executing
报错 https://github.com/AirtestProject/Airtest/commit/3a69dc89ac6f4b797e5175a057121f05b94892f8
RotationWatcher
的时机改为在get_display_info
的时候,避免在特殊情况下,因为它没有及时初始化,导致横竖屏转换时不能正确获取屏幕信息的问题。(假设连手机时是竖屏,开始运行后切换成了横屏,接下来运行纯poco脚本的click语句,就会导致点击位置横竖屏错误。因为poco语句在点击时不涉及截图,导致没有走到rotationwatcher
的初始化逻辑里。) https://github.com/AirtestProject/Airtest/pull/834/commits/1ec622364e3a1ac780629245d4a1b7c8c3314ee9
Android.get_top_activity_name_and_pid
的功能与get_top_activity
重复,因此删除一个。 https://github.com/AirtestProject/Airtest/pull/834/commits/1df9afc0bde7720d408435e99e90f5506aecd6a3
airtest run xx.air
, a new parameter --no-image
is added. As long as this parameter is passed in at runtime, the screenshot can no longer be saved during the task run https:// github.com/AirtestProject/Airtest/commit/2ed128c201be94d1fda0f364641296bec7e68a52, example:airtest run test.air --device Android:/// --log logs/ --no-image
ST.SAVE_IMAGE
in settings, the default is True
, if it is changed to False
, the screenshot will not be saved until the value is set to True
again, example:from airtest.core.api import *
# Temporarily close the screenshot
ST.SAVE_IMAGE = False
touch((100, 100)) # This statement will not save the current screen picture
# Continue to take screenshot
ST.SAVE_IMAGE = True
touch((100, 100))
--no-image
parameter from the command line, it actually sets ST.SAVE_IMAGE
to False
, so the second method will be more flexible. You can freely decide whether the current script is currently running or not. To save the pictureWhen calling the log()
interface to save the corresponding log to the report, it will also be printed to the current terminal for easy viewing. https://github.com/AirtestProject/Airtest/commit/b7d98f640fb3ddad339efe2617270488e8ec83c6
Removed the version dependency of opencv-contrib-python
in requirements.txt
, currently both python3.8 and python3.9 can be installed.
Note: If you cannot use airtest after installing python3.9, you will get an error of ImportError: numpy.core.multiarray failed to import
, you can manually downgrade the numpy
version number to 1.19.3
to use it.
start_recording
has modified the parameters and added a simpler bit_rate_level
, which can set the clarity level from 1-5, the default is 1, the larger the number, the clearer it will be (https://github.com/AirtestProject/Airtest/pull/834/commits/2220863d9f82e066c9543b3a1f34d7242fdd75c4), example: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")
For more examples, please refer to document
logfile
and logdir
in LogToHtml
, and now supports modifying ST.LOG_DIR
and ST.LOG_FILE
, from the main settings log folder and the file name of log.txt. After modification, you can also directly use LogToHtml
to generate a report, and at the same time simplify the transfer of parameters (https://github.com/AirtestProject/Airtest/pull/834/commits/a4b43cb824d9d99855d80a0055ba09694889744c), example:from airtest.report.report import LogToHtml
# Assuming that the script is run.air in the current directory, and the log directory is ./log in the current directory
# By default, log will be considered to be stored in ST.LOG_DIR, if ST.LOG_DIR is empty, try to find the log folder in the current directory
rpt = LogToHtml("test.air")
rpt.report()
Examples of customizing ST.LOG_DIR
and ST.LOG_FILE
:
from airtest.core.helper import set_logdir
new_logfile = "log123.txt"
new_logdir = "./logs_new"
# set logfile = ./logs_new/log123.txt
ST.LOG_FILE = new_logfile
set_logdir(new_logdir)
# ...
rpt = LogToHtml(OWL)
# LogToHtml will select ST.LOG_FILE as logfile and ST.LOG_DIR as log_root by default, and generate the corresponding log.html content
rpt.report()
adb.start_app_timing
could not get app start time in high version android phones https://github.com/AirtestProject/Airtest/commit/002a17077a846010eec69093bfe42abdb094035f
get_top_activity
would report an error when obtaining the package name containing the $
symbol (java allows the $ symbol to appear when naming it) https://github.com/AirtestProject/Airtest/commit/c9e00e878c7aef6f0cc4f5ff2faa9caf82ae5c4f
adb.file_size
has replaced the command to obtain the file size, compatible with lower versions of android phones, and modified the installation process of minitouch and maxtouch by the way to be more concise https://github.com/AirtestProject/Airtest/commit/75e4665d2dcfc14993a1a8935fba6112dfa2fbb6
generator already executing
when taking screenshots from multiple threads at the same time https://github.com/AirtestProject/Airtest/commit/3a69dc89ac6f4b797e5175a057121f05b94892f8
RotationWatcher
is changed to when get_display_info
, to avoid the problem that the screen information cannot be correctly obtained during the horizontal and vertical screen conversion because it is not initialized in time under special circumstances. (Assuming that the phone is connected to the vertical screen and switched to the horizontal screen after starting to run, then running the click statement of the pure poco script will cause the click position to be wrong. Because the poco statement does not involve screenshots when clicking, it does not go Into the initialization logic of rotationwatcher
.) https://github.com/AirtestProject/Airtest/pull/834/commits/1ec622364e3a1ac780629245d4a1b7c8c3314ee9
Android.get_top_activity_name_and_pid
is duplicated with get_top_activity
, so delete one. https://github.com/AirtestProject/Airtest/pull/834/commits/1df9afc0bde7720d408435e99e90f5506aecd6a3
Published by yimelia about 4 years ago
增加了对Android 11
的支持
在脚本中用于记录log的log()
接口进行了大幅度改动,支持4个参数:arg, timestamp=None, desc="", snapshot=False
,(https://github.com/AirtestProject/Airtest/commit/777b5ffe51cfc41c7c05b3bcf289edc38f861774 ,
https://github.com/AirtestProject/Airtest/commit/77a4893be37bb7a3094171af27993fb6b593a0c1 , https://github.com/AirtestProject/Airtest/pull/802/commits/ced1201bbf1a3c244e7a5f5131b684b19b37b18a ),删掉了原先的trace
参数
args
可以是字符串或是traceback对象,现在还支持传入非字符串,并且对py2做了一下兼容。假如传入的是traceback对象,将会自动在报告中标记为报错步骤,否则就是显示正常的log内容timestamp
参数可以自定义当前这条log的时间戳,默认为当前时间(在记录一些长时间的回调中获取到的log时,原本默认使用写入本条log的时间,但是可能需要修改为log产生的时间,比如几分钟前)desc
自定义一个log标题,在报告中有更好的展示效果snapshot
是否需要截取一张当前的屏幕图像并显示到报告中,方便查看。(同时,因为这个参数的加入,现在airtest脚本如果因为执行Poco语句失败报错而终止时,能够额外截取一张当前画面,方便大家排查问题。)data = {"test": 123, "time": 123456}
log(data, timestamp=time.time(), desc="title", snapshot=True)
try:
1/0
except Exception as e:
log(e, snapshot=True)
log("中文")
ST.IMAGE_MAXSIZE
,用于指定截图的最大尺寸,假如设置为1200,则最后保存的截图长宽都都不会超过1200,有利于进一步缩小截图的图片尺寸。 https://github.com/AirtestProject/Airtest/pull/802/commits/ffe7ebc5ad92dcb7139d0f91437658c8518da886
同时,对于单张截图精度和全局截图精度也支持自定义 https://github.com/AirtestProject/Airtest/commit/31e40122e723a36cc23e13716a48d336069a73ea:
snapshot
接口支持传入quality
参数,单独指定本次截图的图像精度ST.SNAPSHOT_QUALITY = xx
设置全局截图精度,在运行脚本时,报告的步骤截图也会采用这个数值进行压缩,默认为10调用示例:
# 默认截图质量为10,这里设置截图质量为30
ST.SNAPSHOT_QUALITY = 30
# 设置截图尺寸不超过600*600,如果不设置,默认为原图尺寸
ST.IMAGE_MAXSIZE = 600
touch(xx) # touch语句保存的截图质量为30, 尺寸不超过600*600
snapshot(filename="test.png", msg="test", quality=90) # 本条语句截图质量为90
snapshot(filename="test2.png", msg="test", quality=90, max_size=1200) # 截图质量为90,尺寸不超过1200*1200
snapshot(msg="test12") # 不设置的情况下,默认采用ST中的全局变量的数值
playground/android_motionevents.py
里面提供了一些Android自定义手势的示例代码,现在直接调用dev.touch_proxy.perform
接口就可以传入写好的MoveEvent列表来进行自定义的滑动了(以前是调用dev.minitouch.perform
,如果是安卓10就会不兼容)。调用示例:
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)
更多示例请参见:https://github.com/AirtestProject/Airtest/blob/master/playground/android_motionevents.py
--recording 录屏文件名.mp4
来指定录屏文件--recording
,默认将会使用recording_手机序列号.mp4
来命名录屏文件--recording test.mp4
,且超过一台手机,就命名为 手机序列号_test.mp4
--recording test.mp4
,且只有一台手机,就命名为 test.mp4
mp4
作为结尾iOS修复了上个版本stopapp
失效的问题 https://github.com/AirtestProject/Airtest/commit/6bf146becc56b2737288941d0771b013d183bc96
回退了屏幕录制代码到1.0.27之前的版本,取消使用yosemite.apk来录屏,避免每次重装过yosemite.apk后必须要手工赋予录屏权限才能录屏的问题
在一些无法使用minicap的手机上,虽然指定了Javacap模式也能截屏,但是在调用get_display_info
的时候依然调用到minicap.get_display_info
,如果没有指定ori_method
为adbori
,会导致脚本无法运行成功。 因此修改为假如获取屏幕信息失败,自动调整为使用adbori
模式来获取当前屏幕信息。 https://github.com/AirtestProject/Airtest/commit/9312f0d52a6dbf28a9b84ed51e338686d68ed875
https://github.com/AirtestProject/Airtest/pull/802/commits/469fa829ca1c593b16e87ba60c8982c4c868cc14
在脚本中一旦对同一台手机运行了不止一次connect_device
接口,并指定了不同的设备连接参数时,G.DEVICE
不会更新到最新参数创建出来的设备对象,导致部分手机可能连接失败。现在改为每次更新设备对象时,也会自动更新一下G.DEVICE
https://github.com/AirtestProject/Airtest/commit/c163a4f46b95c9ad758fa666cf113696bbe7ce6d
修复了在高版本Android手机上,get_ip_address()
接口不能正确获取到手机IP的问题 https://github.com/AirtestProject/Airtest/pull/802/commits/e4d76254f17850b927288fe09a6d0356951a4f2a
(暂未完全修复,请等待下个版本更新)修复了查找图片时,指定RGB属性没生效的问题: https://github.com/AirtestProject/Airtest/pull/802/commits/f2e84a06e90d1e97fc15cec0f2507198c79faf25
去掉了assert_exists
接口使用特殊的ST.THRESHOLD_STRICT
值作为找图阈值的设定。假如之前设置了ST.THRESHOLD_STRICT
将会继续沿用该数值,但是如果没有设置的话,默认与其他图片一样都使用指定的threshold
参数,或是全局的ST.THRESHOLD
,这样能够方便统一设置和管理,也不容易造成误解。https://github.com/AirtestProject/Airtest/pull/802/commits/0045c9bcd074f19e2084f864428eb165d5e10c59
Added support for Android 11
The log()
interface used to log logs in the script has been greatly changed, supporting 4 parameters: arg, timestamp=None, desc="", snapshot=False
, deleted the original parameters.
https://github.com/AirtestProject/Airtest/commit/777b5ffe51cfc41c7c05b3bcf289edc38f861774
https://github.com/AirtestProject/Airtest/commit/77a4893be37bb7a3094171af27993fb6b593a0c1
https://github.com/AirtestProject/Airtest/pull/802/commits/ced1201bbf1a3c244e7a5f5131b684b19b37b18a
Args
can be a string
or a traceback
object, and now supports non-string input, and is compatible with py2
. If the traceback object is passed in, it will be automatically marked as an error step in the report, otherwise the normal log content will be displayedtimestamp
parameter can customize the timestamp of the current log, and the default is the current time (when recording the log obtained in some long-term callbacks, the time written to this log was originally used by default, but it may need to be modified to The time when the log was generated, such as a few minutes ago)desc
customize a log title for better display in the reportsnapshot
Whether it is necessary to take a screenshot of the current screen image and display it in the report for easy viewing. (At the same time, because of the addition of this parameter, if the airtest script terminates due to a failure to execute the Poco statement and an error is reported, it can take an additional screenshot of the current screen to facilitate troubleshooting.)data = {"test": 123, "time": 123456}
log(data, timestamp=time.time(), desc="title", snapshot=True)
try:
1/0
except Exception as e:
log(e, snapshot=True)
log("中文")
ST.IMAGE_MAXSIZE
is added to specify the maximum size of the screenshot. If it is set to 1200, the height and width of the final saved screenshot will not exceed 1200, which is helpful to further reduce the screenshot image size. https://github.com/AirtestProject/Airtest/pull/802/commits/ffe7ebc5ad92dcb7139d0f91437658c8518da886
At the same time, it also supports customization for single screenshot accuracy and global screenshot accuracy https://github.com/AirtestProject/Airtest/commit/31e40122e723a36cc23e13716a48d336069a73ea:
snapshot
interface supports passing in quality
parameter to individually specify the image accuracy of this screenshotST.SNAPSHOT_QUALITY = xx
to set the global screenshot accuracy. When running the script, the step screenshots of the report will also be compressed using this valueExample:
# 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
touch(xx) # The quality of the screenshot saved by the touch statement is 30, and the size does not exceed 600*600
snapshot(filename="test.png", msg="test", quality=90) # The quality of the screenshot of this sentence is 90
snapshot(filename="test2.png", msg="test", quality=90, max_size=1200) # The quality of the screenshot is 90, and the size does not exceed 1200*1200
snapshot(msg="test12") # If not set, the value of the global variable in ST is used by default
playground/android_motionevents.py
provides some sample codes for Android custom gestures, now you can directly call the dev.touch_proxy.perform
interface to pass in the written MoveEvent list for customization Sliding (previously it was called dev.minitouch.perform
, if it is Android 10, it will not be compatible).Call example:
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)
For more examples, please see: https://github.com/AirtestProject/Airtest/blob/master/playground/android_motionevents.py
--recording filename.mp4
to specify the screen file--recording
is passed, serial_number.mp4
will be used by default to name the screen recording file--recording test.mp4
is specified, and there is more than one mobile phone, it will be named as the serialnumber_test.mp4
--recording test.mp4
is specified and there is only one mobile phone, it will be named test.mp4
mp4
iOS fixes the issue of the failure of the previous version of stopapp
https://github.com/AirtestProject/Airtest/commit/6bf146becc56b2737288941d0771b013d183bc96
The screen recording code was rolled back to the version before 1.0.27, and the use of yosemite.apk to record the screen was cancelled to avoid the problem that the screen recording permission must be manually granted every time yosemite.apk is reinstalled.
On some mobile phones that cannot use minicap, although the Javacap mode can also be used to take screenshots, when calling get_display_info
, minicap.get_display_info
is still called. If ʻori_method is not specified as ʻadbori
, it will cause The script could not run successfully. Therefore, it is modified to automatically adjust to use ʻadbori` mode to obtain current screen information if it fails to obtain screen information.
https://github.com/AirtestProject/Airtest/commit/9312f0d52a6dbf28a9b84ed51e338686d68ed875
https://github.com/AirtestProject/Airtest/pull/802/commits/469fa829ca1c593b16e87ba60c8982c4c868cc14
Once the connect_device
interface is run on the same mobile phone more than once in the script, and different device connection parameters are specified, G.DEVICE
will not be updated to the device object created with the latest parameters, which may cause some mobile phones Connection failed. Now it’s changed to automatically update G.DEVICE
every time the device object is updated https://github.com/AirtestProject/Airtest/commit/c163a4f46b95c9ad758fa666cf113696bbe7ce6d
Fixed the issue that the get_ip_address()
interface could not obtain the phone IP correctly on high version Android phones https://github.com/AirtestProject/Airtest/pull/802/commits/e4d76254f17850b927288fe09a6d0356951a4f2a
Fixed the problem that the specified RGB attribute did not take effect when searching for pictures: https://github.com/AirtestProject/Airtest/pull/802/commits/f2e84a06e90d1e97fc15cec0f2507198c79faf25
Removed the assert_exists
interface and uses the special ST.THRESHOLD_STRICT
value as the setting of the image finding threshold. If ST.THRESHOLD_STRICT
is set before, this value will continue to be used, but if it is not set, the specified threshold
parameter or the global ST.THRESHOLD
will be used by default like other pictures, which is convenient for unification Setting and management are not easy to cause misunderstanding. https://github.com/AirtestProject/Airtest/pull/802/commits/0045c9bcd074f19e2084f864428eb165d5e10c59
Published by yimelia over 4 years ago
Android.minitouch
才能运行的接口(主要是pinch
, swipe_along
, two_finger_swipe
),现在统一直接在Android层面进行调用:old:
dev = device()
dev.minitouch.pinch()
dev.minitouch.swipe_along([(100, 300), (300, 300), (100, 500), (300, 600)])
dev.minitouch.two_finger_swipe( (100, 100), (200, 200) )
->
new:
dev = device()
dev.pinch() # 双指捏合或分开
dev.swipe_along([(100, 300), (300, 300), (100, 500), (300, 600)]) # 连续滑过一系列坐标
dev.two_finger_swipe( (100, 100), (200, 200) ) # 两个手指一起滑动
更多调用代码示例与参数示例,可以参考:tests/test_android.py
DownEvent/UpEvent/SleepEvent
,请将import语句修改成如下内容:old:
from airtest.core.android.minitouch import *
->
new:
from airtest.core.android.touch_methods.base_touch import *
修复了部分型号的小米手机(主要是MIUI11版本)在横屏时使用javacap截图,会导致图像被不正确压缩的情况。
Yosemite.apk
,重新连接手机即可重装新版本的Yosemite.apk
修复此问题。修复了MIUI11+android10下,is_screenon
(手机是否亮屏)和is_locked
(手机是否锁屏)接口无法使用的bug
iOS-Tagent
对xcode的支持更新到11.5版本,iOS版本支持到13.5(最新版本的xcode目前暂时还有一些问题需要兼容)Android.minitouch
to run (mainly pinch
, swipe_along
, two_finger_swipe
), it is now called directly at the Android level. like this:old:
dev.minitouch.pinch()
dev.minitouch.swipe_along([(100, 300), (300, 300), (100, 500), (300, 600)])
dev.minitouch.two_finger_swipe( (100, 100), (200, 200) )
->
new:
dev.pinch() # pinch or separate with two fingers
dev.swipe_along([(100, 300), (300, 300), (100, 500), (300, 600)]) # continuously slide through a series of coordinates
dev.two_finger_swipe( (100, 100), (200, 200) ) # Two fingers slide together
For more call code examples, you can refer to tests/test_android.py
DownEvent/UpEvent/SleepEvent
, please modify the import statement to the following:old:
from airtest.core.android.minitouch import *
->
new:
from airtest.core.android.touch_methods.base_touch import *
Yosemite.apk
on your phone and reconnect the phone to reinstall the new version of Yosemite.apk
to fix this problem.is_screenon
(whether the phone is bright) and is_locked
(whether the phone is locked) under MIUI11+android10 cannot be usediOS-Tagent
support for xcode is updated to version 11.5, iOS version is supported to 13.5 (the latest version of xcode currently has some problems that need to be compatible)