手机应用,最常见的操作之一就是滑动。我们做移动 app 测试的时候,经常需要滑动界面。怎么滑动界面呢? Appium 的 WebDriver 的 swipe 方法,就提供了这个功能,我们来看一下这个方法的说明和参数:
前面4个参数 start_x,start_y,end_x,end_y 分别表示滑动的起始和终点位置的 x/y 坐标,第5个 duration 是滑动所耗费的时间(毫秒)。注意这个时间非常重要。时间短就表示滑动的很快。我们知道移动设备,在屏幕上滑动同样的距离,如果滑动很快和滑动很慢有什么区别?比如我们翻看新闻,滑动同样的距离。如果滑动很会出现屏幕上翻页的效果,而滑动很慢,则会移动固定的位置。
下面是华为应用市场 App 的例子。该 App 有一个广告轮播图,如下图黄色框中的区域。
我们现在要实现手指连续滑动该区域,实现不停翻看图片的动作。该区域对应界面元素它是有 id 的 com.huawei.appmarket:id/backPicture,我们可以通过其 bounds 属性或者移动鼠标光标大概估算出我们要滑动的点的坐标,代码如下:
from appium import webdriver
import time
import traceback
#准备自动化配置信息
desired_caps={
#移动设备平台
'platformName':'Android',
#平台OS版本号,写整数位即可
'plathformVersion':'9',
#设备的名称--值可以随便写
'deviceName':'test0106',
#提供被测app的信息-包名,入口信息:
#adb shell dumpsys activity recents | findstr intent={
'appPackage':'io.manong.developerdaily',
'appActivity':'io.toutiao.android.ui.activity.LaunchActivity',
#确保自动化之后不重置app
'noReset':True,
#设置session的超时时间,单位秒
'newCommandTimeout':6000,
#设置底层测试驱动-1.15默认使用的底层驱动就是UiAutomator2
'automationName':'UiAutomator2',#或者UiAutomator1
# 'skipServerInstallation':True#跳过UI2的安装,如果第一次运行程序,不要添加该配置
}
#初始化driver对象-用于控制手机-启动被测应用
#IP-appium-server所在机器的网络ip,port-监听的端口号,path固定/wd/hub
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
driver.implicitly_wait(20)#稳定元素
try:
ele = driver.find_element_by_id(
'com.huawei.appmarket:id/backPicture')
time.sleep(3)
for i in range(10):
driver.swipe(start_x=560, start_y=340, end_x=130, end_y=340, duration=500)
time.sleep(0.5)
except:
print(traceback.format_exc())
input('**** Press to quit..')
driver.quit()
因为 y 坐标不变,这样就可以实现预期循环滑动10次的效果了。上面的的代码有个问题。如果屏幕分辨率不同,代码就不对了,比如同样的应用,在2K屏的手机上,坐标就不同了。所有一种解决方法是,动态获取元素坐标,而不是查看当前手机的固定坐标。怎么动态获取呢?根据元素的 location 属性,是个 dict,里面有两个key x y 保存了该元素的左上角坐标,但是这个例子里面我需要的右下角的坐标,怎么得到右下角的坐标呢?根据元素的 size 属性,是个 dict,里面有两个key :width,height 保存了该元素的宽、高就可以得到右下角的坐标。
改进代码如下:
ele = driver.find_element_by_id('com.huawei.appmarket:id/banner')
time.sleep(2)
location = ele.location
size1 = ele.size
print(location, size1)
x1 = location['x'] + int(size1['width'] * 0.8)
x2 = location['x'] + int(size1['width'] * 0.2)
y = location['y'] + int(size1['height'] * 0.5)
for i in range(10):
driver.swipe(start_x=x1, start_y=y, end_x=x2, end_y=y, duration=500)
time.sleep(0.5)
这样代码就健壮一些了,整体代码是
from appium import webdriver
import time
import traceback
desired_caps = {}
desired_caps['platformName'] = 'Android' #测试平台
desired_caps['platformVersion'] = '7' #平台版本,不能写错
desired_caps['deviceName'] = 'test' #设备名称,多设备时需区分
# desired_caps['app'] = r'd:\apk\HiSpace.apk' #app 文件 名,指定了要安装的app 在电脑上的路径
desired_caps['appPackage'] = 'com.huawei.appmarket' #app package名,指定了要运行的app
desired_caps['appActivity'] = 'com.huawei.appmarket.MainActivity' #app默认Activity
desired_caps['unicodeKeyboard'] = True # 一定要有该参数,否则unicode 输入的中文无效
desired_caps['noReset'] = True
desired_caps['newCommandTimeout'] = 60
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) #启动Remote RPC
driver.implicitly_wait(10)
try:
ele = driver.find_element_by_id('com.huawei.appmarket:id/banner')
time.sleep(2)
location = ele.location
size1 = ele.size
print(location, size1)
x1 = location['x'] + int(size1['width'] * 0.8)
x2 = location['x'] + int(size1['width'] * 0.2)
y = location['y'] + int(size1['height'] * 0.5)
for i in range(10):
driver.swipe(start_x=x1, start_y=y, end_x=x2, end_y=y, duration=500)
time.sleep(0.5)
except:
print(traceback.format_exc())
input('**** Press to quit..')
driver.quit()
可以拿去运行一下,记得改安卓的版本号。
操作不可见屏幕
比如说我们滑动安卓手机的屏幕,可以通过 driver 的 get_window_size() 获取到获取全屏尺寸, get_window_size() 返回的是手机屏幕的宽度和高度,比如你要滑动这段距离,如图:
这个相当于全屏幕的,这个时候你可以把整个屏幕的分辨率获取,然后算出起始位置和结束位置。
screenSize = driver.get_window_size()
screenW = screenSize['width']
screenH = screenSize['height']
只提供方法,具体代码实现自己操作。