UI Automation Framework for Games and Apps
相关注意事项:
极少部分设备上,可能点击位置会有偏移,目前在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 systemFix:
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 support主要改动:
本次更新以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 completed我们新增了一个改良版本的模板匹配识别算法,能够大幅度增加原有的模板匹配的成功率,更好地适配分辨率变化的场景。
将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
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
在命令行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
增加了对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