Appium安卓自动化基础

目录

  • Appium连接手机
    • adb无线连接
    • 用Appium脚本连接手机启动APP
  • 元素定位
    • 元素定位方法
    • id定位
    • class定位
    • 相对定位
    • xpath定位
    • list定位
    • UIAutomator元素定位
      • 简介:
      • 定位方式:
      • id定位:
      • text定位
      • class name定位
    • H5页面元素定位
      • 解决思路
      • context
    • H5定位环境搭建
      • H5定位思路
      • 代码实现
        • 进入h5页面
        • 获取H5页面的contexts
        • 切换contexts环境
        • 用pc端的浏览器进入定位
        • 用webdriver的方式进行定位元素
        • 整体代码
    • 时有时无的元素处理
  • 元素等待
    • 强制等待
    • 隐式等待
    • 显示等待
  • 屏幕截图
    • 截图保存在当前目录
    • 截图保存到指定目录
  • 滑动操作
    • swipe方法参数
    • 滑动解析
    • 第一种滑动方式 直接通过坐标点
      • 获取X,Y坐标
    • 第二种通过屏幕尺寸计算得出滑动坐标
        • 处理流程
        • 获取手机尺寸
        • 计算滑动的坐标点
    • 连续滑动
      • TouchAction类
        • 按压操作
        • 长按操作
        • 点击操作
        • 移动操作
        • 暂停
        • 释放
        • 执行
      • 滑动实战操作
    • 多点触控--滑动操作
      • MultiAction类
        • add类方法
        • MultiAction与ActionTouch用法
      • 多点触控实战
        • 滑动原理
        • 代码实现

Appium连接手机

usb连接手机
DOS命令输入adb devices,查询连接设备的名称。例如:设备名称为238ap45

启动appiumDesktop

{

“platformName”: “Android”,

“deviceName”: “devices”,

“platformVersion”: “安卓版本”,

“appPackage”: “包名”,

“appActivity”: “活动页”,

“automationName”:“uiautomator1”

}

AppiumDesktop连接真机成功

adb无线连接

  • 输入adb devices,查询连接设备的名称。例如:设备名称为238ap45

  • 开启端口(端口不能被占用),输入adb tcpip 5555

  • adb shell ip -f inet addr show wlan0: 查看手机内网ip

  • 通过查询到的手机IP与设置的端口号,输入adb connect 192.168.x.xxx:5555

  • 连接上后就可以拔掉USB线了,查看连接状态,输入adb devices

  • 断开无线连接可执行命令:adb disconnect 192.168.21.100:5556

用Appium脚本连接手机启动APP

from appium import webdriver#导入模块
#手机的连接配置信息写入字典中
desired_caps={
  "platformName": "Android",
  "deviceName": "devices",
  "platformVersion": "10",
  "appPackage": "com.sina.weibo",
  "appActivity": "com.sina.weibo.SplashActivity",
  "noReset": "true",
  "automationName": "uiautomator1"
}
#调用webdriver模块中的Remote方法启动APP
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

元素定位

元素定位方法

  • id
  • name
  • class
  • List
  • 相对定位
  • Xpath定位
  • H5页面元素定位
  • Uiautomator定位

id定位

Appium中可以使用find_element_by_id()来进行元素定位

定位的工具可以用sdk自带的uiautomatorviewer 和 Appium Desktop来进行定位

我现在用 Appium Desktop 来进行定位

打开appium Desktop工具 选择 Selected Element 点击要定位的点右侧就会出现id的元素

Appium安卓自动化基础_第1张图片
复制下来在脚本

driver.find_element_by_id('com.shizhuang.duapp:id/iv_search').click()

class定位

by_classname.by

driver.find_element_by_class_name('android.widget.EditText').send_keys('aj')

但有时class属性值有可能有两个以上 重复的 那么就有只能定位第一个元素的情况所以有Id的化一般就不用class

相对定位

​ 先找到目标元素的父元素 然后再利用父元素去定位子元素

#下方代码解释: 定位父元素 将 父元素 放入变量id中然后 用id去定位子元素的class

id = driver.find_element_by_id('com.shizhuang.duapp:id/title_container')
id.find_element_by_class_name('android.widget.FrameLayout').click()

如果父元素下方有多个子元素且class相同那么同样只能定位第一个

xpath定位

/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
nodename 选取此节点的所有子节点。
. 选取当前节点。
选取当前节点的父节点。
@ 选取属性。
通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。
driver.find_element_by_xpath('//*[@class="android.widget.FrameLayout" and     @index="2"]').click() #and 可以实现多条件定位
driver.find_element_by_xpath('//android.widget.EditText[@text="请输入用户名"]').send_keys('zxw1234')

list定位

遇到id和class的属性值都是一样的 这个时候只能定位到第一个 要想获取其他的元素 必须用list定位

思路:

把id或class 集合起来赋值给变量中

用索引取值的方式把值取出来 做相应的操作

注意这里用的是find_elements 最后要加上 s

clas = driver.find_elements_by_class_name('android.widget.TextView')
clas[2].click()

UIAutomator元素定位

简介:

UIAutomator元素定位是 Android 系统原生支持的定位方式,虽然与 xpath 类似,但比它更加好用,且支持元素全部属性定位.定位原理是通过android 自带的android uiautomator的类库去查找元素。 Appium元素定位方法其实也是基于Uiautomator来进行封装的。

使用方法 find_element_by_android_uiautomator() 可以运用UiAutomator元素定位。

定位方式:

  • id定位
  • text定位
  • class name定位

id定位:

id定位是根据元素的resource-id属性来进行定位,使用 UiSelector().resourceId()方法即可。

Appium安卓自动化基础_第2张图片

driver.find_element_by_id('com.shizhuang.duapp:id/rbtn_user').click()#点击我的
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.shizhuang.duapp:id/icon")').click()#待付款

text定位

text定位就是根据元素的text属性值来进行定位,new UiSelector()
Appium安卓自动化基础_第3张图片

driver.find_element_by_android_uiautomator('new UiSelector().text("待付款")').click()

class name定位

与Appium class定位方式一样,也是根据元素的class属性来进行定位。new UiSelector().className

driver.find_element_by_android_uiautomator('new UiSelector().className("android.widget.ImageView")').click()

H5页面元素定位

在混合开发的App中,经常会有内嵌的H5页面。那么这些H5页面元素该如何进行定位操作呢

解决思路

针对这种场景直接使用前面所讲的方法来进行定位是行不通的,因为前面的都是基于Andriod原生控件进行元素定位,而Web网页是单独的B/S架构**,两者的运行环境不同因此需要进行上下文(context)切换,**然后对H5页面元素进行定位操作

context

Context的中文翻译为:语境; 上下文; 背景; 环境,在开发中我们经常说“上下文”,那么这个“上下文”到底是指什么意思呢?

关于应用程序环境的全局信息的接口。 这是一个抽象类,其实现由Android系统提供。 它允许访问特定于应用程序的资源和类,以及对应用程序级操作的调用,如启动活动、广播和接收意图等。

在程序中context我们可以理解为当前对象在程序中所处的一个环境。 比如前面提到的App一个界面是属于Activity类型,也就是Android界面环境,但是当访问内嵌的网页是属于另外一个环境(网页环境),两者处于不同的一个环境。

H5定位环境搭建

  • Chrome pc浏览器
  • 手机版Chrome浏览器(和pc端版本尽量保持一致)
  • Chrome driver下载地址: https://npm.taobao.org/mirrors/chromedriver/
  • WebbDriver放在类似于**…/app\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win
  • App Webview开启debug模式
  • 在电脑端Chrome浏览器地址栏输入chrome://inspect/#devices,进入调试模式

H5定位思路

  • 进入webview页面
  • 获取页面环境的contexts
  • 用获取到的contexts切换webview
  • 在H5页面进行元素定位操作

代码实现

进入h5页面

driver.find_element_by_id('com.wondershare.drfone:id/btnBackup').click()

WebDriverWait(driver,8).until(lambda x:x.find_element_by_id('com.wondershare.drfone:id/btnRecoverData'))#等待元素出现8秒
print('click NextBtn')
driver.find_element_by_id('com.wondershare.drfone:id/btnRecoverData').click()#点击进入h5

获取H5页面的contexts

contexts = driver.contexts #获取页面的contexts
print(contexts)
>>>['NATIVE_APP', 'WEBVIEW_com.wondershare.drfone']

切换contexts环境

#切换获取到的contexts页面
driver.switch_to_default_content('WEBVIEW_com.wondershare.drfone')

用pc端的浏览器进入定位

Chrome浏览器打开 chrome://inspect/#devices 页面 可以获取该H5的URL

用webdriver的方式进行定位元素

#在H5页面中进行操作
driver.find_element_by_id('email').send_keys('[email protected]')
driver.find_element_by_xpath('//button[@class]').click()


#操作结束后 切换回安卓
driver.switch_to.context('NATIVE_APP')
#点击返回
driver.find_element_by_class_name('android.widget.ImageButton').click()

整体代码

driver.find_element_by_id('com.wondershare.drfone:id/btnBackup').click()
WebDriverWait(driver,8).until(lambda x:x.find_element_by_id('com.wondershare.drfone:id/btnRecoverData'))#等待元素出现8秒
driver.find_element_by_id('com.wondershare.drfone:id/btnRecoverData').click()#点击进入h5


contexts = driver.contexts #获取页面的contexts
print(contexts)
#切换获取到的contexts页面
driver.switch_to.context('WEBVIEW_com.wondershare.drfone')
#在H5页面中进行操作
driver.find_element_by_id('email').send_keys('[email protected]')
driver.find_element_by_xpath('//button[@class]').click()


#操作结束后 切换回安卓contexts
driver.switch_to.context('NATIVE_APP')
#点击返回
driver.find_element_by_class_name('android.widget.ImageButton').click()

时有时无的元素处理

有些页面不一定每次都有 比如版本升级后对于新功能的介绍

这些页面元素 就需要处理一下 否则可能下次执行就会因为找不到元素报错

异常处理的方式解决

id = driver.find_element_by_id('com.shizhuang.duapp:id/iv_search')
try:
   id
except EnvironmentError as e:
  print("没有定位到元素")
else:
  id.click()

元素等待

有时候有的元素加载时间可能过长 所以要等待这个元素出现再进行下面的操作

强制等待

设置固定的等待时间,使用sleep()方法即可实现

from time import sleep
#强制等待5秒
sleep(5)

隐式等待

隐式等待是针对全部元素设置的等待时间

driver.implicitly_wait(20)

显示等待

显式等待是针对某个元素来设置的等待时间

webdriverwait:源码分析
from selenium.webdriver.support.ui import WebDriverWait
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver : WebDriver
timeout : 最长超时时间,默认以秒为单位
poll_frequency : 休眠时间的间隔时间,默认为0.5秒
ignored_exceptions : 超时后的异常信息,默认情况下抛NoSuchElementException异常。
from selenium.webdriver.support.ui import WebDriverWait
#等待3秒 
WebDriverWait(driver,3).until(lambda x:x.find_element_by_id("com.shizhuang.duapp:id/iv_search"))

屏幕截图

截图保存在当前目录

save_screenshot() 该方法直接保存当前屏幕截图到当前脚本所在文件位置。

driver.save_screenshot('login.png')

截图保存到指定目录

get_screenshot_as_file(self, filename) 将截图保留到指定文件路径

filename: 保存的路径和文件名

driver.get_screenshot_as_file('./img/login.png')

滑动操作

在Appium中模拟用户滑动操作需要使用swipe方法

swipe方法参数

def swipe(self, start_x, start_y, end_x, end_y, duration=None):
    """
    从一个点滑动到另一个点,持续时间可选。
参数:
	start_x (int):开始的x坐标
	start_y (int):开始的y坐标
	end_x (int):要停止的x坐标
	end_y (int):停止的y坐标
	duration:持续时间
    """

滑动解析

滑动主要分为:

  • 水平滑动
  • 垂直滑动
  • 任意方向滑动

滑动轨迹图如下:

Appium安卓自动化基础_第4张图片

第一种滑动方式 直接通过坐标点

获取X,Y坐标

使用AppiumDesktop获取坐标点 连接手机打开App后, 选择Swipe By Coordinates在左侧就能获得相应坐标 点的值 或者在手机开发者中开启指针位置

然后在调用 swipe方法

driver.swipe(422,1150,526,469)#前两个是起点坐标 后面是终点坐标  滑动时间默认为空可以不写 如果需要指定时间 直接写上就好 单位是毫秒

第二种通过屏幕尺寸计算得出滑动坐标

处理流程

  • 获取手机屏幕尺寸
  • 通过获得的宽高 计算出起始和终点坐标

获取手机尺寸

def get_size():
    """
    :return: 获取手机屏幕尺寸
    """
    x=driver.get_window_size()['width']
    y=driver.get_window_size()['height']
    return x,y
l = get_size()
print(l)
print("宽:{}".format(int(l[0])))
print("高度:{}".format(int(l[1])))
>>>(1080, 2030)
>>>:1080
>>>高度:2030

计算滑动的坐标点

从下向上滑动

def get_size():
    """
    :return: 获取手机屏幕尺寸
    """
    x=driver.get_window_size()['width']
    y=driver.get_window_size()['height']
    return x,y
l = get_size()
print(l)
print("宽:{}".format(int(l[0])))
print("高度:{}".format(int(l[1])))

def swipeLeft():
    l = get_size()
    x1 = int(l[0]*0.5)#宽度在中间滑动乘0.5
    y1 = int(l[1] * 0.9) # 高度在底部开始向上滑动 乘0.9
    x2 = int(l[0]*0.5)#终点的宽度也在中间
    y2 = int(l[1]* 0.1)#滑动到接近顶部的位置
    driver.swipe(x1,y1,x2,y2)

swipeLeft()

连续滑动

滑动操作一般是两点之间的滑动,而实际使用过程中用户可能要进行一些多点连续滑动操作。如九宫格滑动操作,连续拖动图片移动等场景

TouchAction类

Touch Action包含一些列操作,比如按压、长按、点击、移动、暂停。由着些不同操作可以组成一套动作。使用TochAction需要先导入对应的模块

from appium.webdriver.common.touch_action import TouchAction

按压操作

方法:press() 开始按压一个元素或坐标点(x,y)。通过手指按压手机屏幕的某个位置。 press也可以接收屏幕的坐标(x,y)。

press(self, el=None, x=None, y=None)
 
TouchAction(driver).press(x=0,y=308)

长按操作

方法:longPress() 开始按压一个元素或坐标点(x,y)。 相比press()方法,longPress()多了一个入参,既然长按,得有按的时间吧。duration以毫秒为单位。1000表示按一秒钟。其用法与press()方法相同。

long_press(self, el=None, x=None, y=None, duration=1000)

点击操作

方法:tap() 对一个元素或控件执行点击操作。用法参考press()。

tap(self, element=None, x=None, y=None, count=1)

移动操作

方法:move_to() 将指针从上一个点移动到指定的元素或点。注意:移动到目位置有时是算绝对坐标点,有时是基于前面一个坐标点的偏移量,(比如 x=50 就是横轴向右移动50个单位 x=-50就是向左移动50个单位)

move_to(self, el=None, x=None, y=None)

暂停

方法:Wait()暂停脚本的执行,单位为毫秒

wait(self, ms=0)

释放

方法release() 结束的行动取消屏幕上的指针。

release(self)

执行

perform() 执行的操作发送到服务器的命令操作。

perform(self)

滑动实战操作

在九宫格上画一个数字7的操作

press按压第一个点 然后move_to方法滑动到目标坐标点 最后release().perform()释放指针执行操作

from appium import webdriver
from run_app import driver
from selenium.webdriver.support.ui import WebDriverWait
import time as t
from appium.webdriver.common.touch_action import TouchAction


TouchAction(driver).press(x=307,y=719).wait(2000)\
    .move_to(x=536,y=720).wait(2000)\
    .move_to(x=552,y=1230).release().perform()

多点触控–滑动操作

在使用地图App中,我们经常需要对界面进行缩放操作来更加便利的查看位置。那么在Appium中怎样去模拟这类操作呢?

MultiAction类

MultiAction 是多点触控的类,可以模拟用户多点操作。主要包含 add()perform() 两个方法, MultiAction可以结合前面所学的 ActionTouch可以模拟出用户的多个手指滑动的操作效果;

from appium.webdriver.common.multi_action import MultiAction
from appium.webdriver.common.touch_action import TouchAction

add类方法

def add(self, *touch_actions):
    """
    将TouchAction对象添加到MultiAction中,稍后执行。
参数:
	touch_actions (' TouchAction '):一个或多个TouchAction对象,描述一个手指要执行的操作链
    """

MultiAction与ActionTouch用法

a1 = TouchAction(driver)
a1.press(el1).move_to(el2).release()
 
a2 = TouchAction(driver)
a2.press(el2).move_to(el1).release()
 
MultiAction(driver).add(a1, a2)

多点触控实战

百度地图APP演示

滑动原理

Appium安卓自动化基础_第5张图片

代码实现

缩小地图操作

from run_app import driver
from selenium.webdriver.support.ui import WebDriverWait
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.common.multi_action import MultiAction


WebDriverWait(driver,6).until(lambda x:x.find_element_by_id("com.baidu.BaiduMap:id/duhelper_flysaucer"))
x = driver.get_window_size()['width']
y = driver.get_window_size()['height']

def pinch():
    """缩小地图"""
    """定义两个手指动作"""
    action1=TouchAction(driver)
    action2=TouchAction(driver)
    zoom_action=MultiAction(driver)

    """
    action1:第一个手指滑动的操作
    action2:第二个手指滑动的操作
    zoom_action.add:将这两个手指操作添加到zoom_action.add方法里 然后perform执行
    """
    action1.press(x=x*0.2,y=y*0.2).wait(1000).move_to(x=x*0.4,y=y*0.4).wait(1000).release()
    action2.press(x=x*0.8,y=y*0.8).wait(1000).move_to(x=x*0.6,y=y*0.6).wait(1000).release()
    zoom_action.add(action1, action2)
    zoom_action.perform()

if __name__ == '__main__':
    for i in range(3):
        pinch()

你可能感兴趣的:(自动化测试,编程语言)