1、appium安装

1)先下载appium客户端
2)安装appium-python库
命令行安装(需要联网)
	pip install Appium-Python-Client
命令行检测是否已安装appium库
	pip list

1.1 、appium简单初体验

#导模块
	from appium import webdriver
#创建一个字典,包装相应的启动参数
	desired_caps=dict()
#需要连接手机的平台(不限制大小写)
	desired_caps['platformName']='android'
#需要连接的手机的版本号
	desired_caps['platformVersion']='5.1'
#需要连接手机的设备号(Android平台下,可以随便写,但是不能不写)
	desired_caps['deviceName']='19.168.56.101:5555'
#需要启动的程序包名
	desired_caps['appPackage']='com.android.settings'
#需要启动的程序界面名
	desired_caps['appActivity']='.Settings'
#连接appium服务器
	driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)
#退出
	driver.quit()

1.3、在脚本内启动其他app

方法和参数

#脚本内启动其他app
#参数
	#appPackage:要打开的程序包名
	#appActivity:要打开的程序的界面名
driver.start_activity(appPackage,appActivity)

1.4、获取app的包名和界面名

属性名

#获取包名
	driver.current_package
#获取界面名
	driver.current_activity

1.5、关闭app和驱动对象

方法名

#关闭当前操作的app,不会关闭驱动对象
	driver.close_app()
#关闭驱动对象,同时关闭所有关联的app
	driver.quit()

1.6、安装和卸载以及是否安装app

方法

#安装app
#参数:
	#app_path:apk路径
driver.install_pp(app_path)

#卸载app
#参数:
	#app_id:应用程序包名
driver.remove_app(app_id)

#判断app是否以及安装
#参数:
	#app_id:应用程序包名
#返回值:
	#布尔类型,True为安装,False为没有安装
drver.is_app_installed(app_id)

1.7、将应用置于后台

应用场景场景

银行类app会在进入后台一定时间后,如果再回到前台也页面会重新输入密码,如果需要自动化测试这种功能,可以使用这个api进行测试

方法

#app放置到后台一定时间后再回到前台,模拟热启动
#参数:
#   seconds:后台停留多少秒
driver.background_app(seconds)

1.8、uiautomatorviewer使用与注意事项

1)如何使用uiautomatorviewer获取元素的特征

1、保证想要查看的元素在当前的屏幕上
2、打开uiautomatorviewer工具
3、点击左上角左数第二个按钮
4、点击想要获取特征的元素
5、查看工具右下角相关的特征信息

2)使用uiautomatorviewer注意点

1、命令行窗口不要关闭
2、如果uiautomatorviewer闪退
	更换jdk为1.8
3、点击第二个按钮的时候报错
	重启adb
adb kill -server
adb start -server

1.9、如何定位一个元素

方法名

#通过id定位一个元素
#参数:
	#id_value:元素的resource-id的属性
#返回值:
	#定位到的单个元素
driver.find_element_by_id(id_value)

#通过class_name定位一个元素
#参数:
	# class_value:元素的class的属性值
#返回值:
	#定位的单个元素
driver.find_element_by_id(class_value)

#通过xpath定位一个元素
#参数:
	# xpath_value:定位元素的xpath表达式
#返回值
	#定位到的单个元素
driver.find_element_by_xpath(xpath_value)如(“//*[@content-desc='收起']”)

注意点:

如果很多元素的“特征”相同,使用find_element_by_xxx的方法会找到第一个
也就是说,尽量去找元素特征有唯一性的“特征”,来定位

2.0、定位一组元素【掌握】

和定位一元素相同,但如果想要批量的获取某个相同特征的元素,使用定位一组元素的方式更加方便。

方法名

#通过id定位一组元素
#参数:
#	 id_vlue:元素的resource-id属性值
#返回值:
#	 列表,定位到的所有符合调价你的元素

driver.find_elements_by_calss_name(id_value)

#通过clas_name定位一组元素
#参数:
#	 class_value:元素的class属性值
#返回值:
#	 列表,定位到的所有符合调价的元素

driver.find_elements_by_class_name(class_value)

#通过xpath定位一组元素
#参数:
#	 xpath_value:定位元素的xpath表达式
#返回值:
#	 列表,定位到的所有符合调价你的元素

driver.find_elements_by_xpath(xpath_value)

2.1、定位元素的注意点【了解】

应用场景

了解这些注意点可以意会在出错误的时候,更快速的定位问题原因

示例

使用find_element_by_xx或find_elements_by_xx的方法,分别传入一个没有的“特征”会是什么结果呢?

核心代码

driver.find_element_by_id("xxx")
driver.find_elements_by_id("xx")

小结

1、如果使用find_element-by_xxx方法,如果传入一个没有的特征,会报NoSuchElementException的错	误。
2、如果使用find_elements_by_xxx方法,如果传入一个没有特征,不会报错,会返回一个空列表

2.2、隐式等待

应用场景

针对所有定位元素的超时间设置为同一个值的时候

概念

等待元素加载指定的时长,超出时长抛出NoSuchElementException异常

步骤

1、在获取driver对象后,使用driver调用implicitly_wait方法即可
方法参数解析
#参数:
#	timeout:超时的时长,单位:秒
#引用模块
from selenium.webdriver.support.wait import webDriverWait
implicitly_wait(timeout)

2.3、显式等待

方法参数解析

#参数:
#	 driver:驱动对象
#	 timeout:超时的时长,单位:秒
#	 poll_frequency:检测间隔时间,默认为0.5秒
#返回值:
#	   webDriverWait对象
#引用模块
from selenium.webdriver.support.wait import webDriverWait
webDriverWait(driver,timeout,poll_frequency)

#参数:
#	 method:lambda查找元素表达式
#返回值:
#	 定位到的元素,如果没有定位到会抛出TimeoutException异常
until(method)

2.4.显示等待和隐式等待的选择?

作用域

显示等待为单个元素有效,隐式为全局元素

方法

显示等待方法封装在WebDriverWait类中,而隐式等待则通过driver实例化对象调用

关于sleep的形式?

sleep是固定死一个时间,不管行不行,是不推荐;
元素等待可以让元素出来的第一时间进行操作。sleep可能造成不必要的浪费

2.5、元素操作API

2.5.1、点击元素

应用场景

需要点击某个按钮的时候使用

方法名

#对element按钮进行点击操作
element.click()

2.5.2、输入和清空输入框内容

应用场景

需要对输入框进行输入或清空的时候使用

方法名

#对element输入框进行输入操作
#参数:
#   value:输入的内容
element.send_keys(value)
#清空输入框
element.clear()

注意点

默认输入中文无效,但不会报错,需要在“前置代码”	中增加俩个参数
desired_caps['unicodeKeyboard']=True
desired_caps['resetKeyboard']=True

2.5.3、获取元素的文本内容

应用场景

需要获取按钮、文本框、输入框、等控件内容使用

属性名

#获取element控件的文件内容
#返回值:
#    控件的文本内容
element.text

示例

1、打开设置
2、获取resource-id为“com.android.settings:id/title”的元素,并打印其文字内容

核心内容

titles=driver.find_elements_by_id("com.android.settings:id/title")
for title in titles:
	print(title.text)

2.5.4、获取元素的位置和大小

应用场景

需要获取元素的位置和大小的时候使用

属性名

#获取element的位置
#返回值:
#     字典,x为元素的坐标,y为元素的y坐标
element.location
#获取element的大小
#返回值:
#     字典,width为宽度,height为高度
element》size

2.5.5、获取元素的属性值

应用场景

根据特征定位到元素后使元素的属性名获取对应的属性值

方法名

#对element进行点击操作
#参数:
#    value:要获取的属性名
#返回值:
#     根据属性名得到的属性值
element.get_attribute(value)#value:元素的属性

示例

1、打开设置
2、获取所有resource-id为“com.anroid.settings:id/title”的元素
3、使用get_attribute获取元素的enabled、text、content-desc、resource-id、class的属性值

核心代码

titles=driver.find_element_by_id("com.anroid.settings:id/title")
for title in titles:
	print(title.get_attribute("enabled"))
	print(title.get_attribute("text"))
	print(title.get_attribute("name"))
	print(title.get_attribute("resourceId"))
	print(title.get_attribute("className"))

注意点

想要获取resource-id使用resourceId属性名 API>=18
想要获取class使用className属性名  API>=18
想要获取content-desc使用name属性名  
其他的,都可以参考uiautomator viewer中的 属性名

2.6、滑动和拖拽事件

2.6.1、swipe滑动事件

概念

从一个坐标位置滑动到另一个坐标位置,只能是俩个点之间的滑动。

方法名

#从一个坐标位置滑动到另一个坐标位置,只能是俩个点之间的滑动
#参数:
#	start_x:起点x轴坐标
#	start_y:起点Y轴坐标
#	end_x:终点X轴坐标
#	end_y:终点Y轴坐标
#	duration:滑动这个操作一共持续时间长度,单位:ms
driver.swipe(start_x,start_y,end_x,end_y,duration=None)

特点

参数是坐标点

持续时间短,惯性大

持续时间长,惯性小

2.6.2、scroll滑动事件

概念

从一个元素滑动到另一个元素,直到页面自动停止。

方法名

#从一个元素滑动到另一个元素,直到页面自动停止
#参数:
#	origin_el:	滑动开始的元素
#	destination_el:滑动结束的元素
driver.scroll(origin_el,destination_el)

示例

从“存储”滑动到“更多”

核心代码

save_button=driver.find_element_by_xpath("//*[@text='存储']")
more_button=driver.find_element_by_xpath("//*[@text='更多']")
driver.scroll(save_button,more_button)

小结

不能设置持续时间,惯性很大

2.6.3drag_and_drop拖拽事件

概念

从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置

方法名

#从一个元素滑动到另一个元素,第二个元素原本屏幕上的位置
#参数:
# 	origin_el:滑动开始的元素
#	destination_el:滑动结束的元素
driver.drag_and_drop(origin_el,destination_el)

示例

将“存储”拖拽到“更多”

核心代码

save_button=driver.find_element_by_xpath("//*[@text='存储]'")
more_button=driver.find_element_by_xpath("//*[@text='更多']")
driver.drag_and_drop(save_button,more_button)

小结

不能设置持续时间,没有惯性

2.7、滑动和拖拽事件的选择

滑动和拖拽无非就是考虑是否有惯性,以及传递的参数是元素还是坐标

可以分成以下四种情况

有“惯性”,传入“元素”
	scroll
	
无“惯性”,传入“元素”
	drag_and_drop
	
有“惯性”,传入“坐标”
	swipe,并且设置较短的duration时间
	
无“惯性”,传入“坐标”
	swipe,并且设置较短的duration时间

2.8、高级手势TouchAction

应用场景

TouchAction可以实现一些针对手势的操作,比如滑动、长按、拖动等。我们可以将这些基本手势组合成一个相对复杂的手势。比如,我们解锁手机或者一些应用软件都有手势解锁的这种方式。

使用步骤

1、创建TouchAction对象
2、通过对象调用想执行的手势
3、通过preform执行动作

注意点

所有手势都要通过执行perform()函数才会运行

2.8.1、手指轻敲操作【掌握】

应用场景

模拟手指对某个元素或坐标按下并快速抬起。比如,固定点击(100,100)的位置。

方法名

#模拟手指对元素或坐标的轻敲操作
#参数:
#	 element:元素
#	 x:x坐标
#	 y:y坐标
#	 count:点击次数次数
TouchAction(driver).tap(element=None,x=None,y=None,count=1).perform()

示例

1、打开“设置”
2、轻敲“WLAN”

核心代码

el=driver.find_element_by_xpath("//*[contanins(@text.'WLAN')]")
TouchAction(driver).tap(el).perform()

2.8.2、手势按下和抬起操作【掌握】

应用场景

模拟手指一直按下,模拟手指抬起。可以用来组合成轻敲或长按的操作

方法名

#模拟手指对元素或坐标的按下操作
#参数:
#	el:元素
#	x:x坐标
#	y:y坐标
TouchAction(driver).press(el=None,x=None,y=None).perform()
#模拟手指对元素或坐标的抬起操作
TouchAction(driver).release().perform()

示例1

使用坐标的形式点击WLAN(650,650),2秒后,按下(650,65)的位置

核心代码

TouchAction(driver).press(x=650,y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650,y=650).perform()

示例2

使用坐标的形式点击WLAN(650,650),2秒后,按下(650,65)的位置,并抬起

核心代码

TouchAction(driver).press(x=650,y=650).perform()
time.sleep()
TouchActhon(driver).press(x=650,y=650).release().perform()

2.8.3、等待操作(掌握)

应用场景

模拟手机等待,比如按下后等待5秒之后再抬起

方法名

#模拟手指暂停操作
#参数:
#		ms:暂停的毫秒
TouchAction(driver).wait(ms=0).perform()

示例

使用坐标的形式点击WLAN(650,650),2秒后,按下(650,650)的位置,暂停2秒,并抬起

核心代码

TouchAction(driver).tap(x=650,y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650,y=650).perform().wait(2000).release.perform()

2.8.4、长按操作【掌握】

应用场景

模拟手指对元素或坐标的长按操作。比如,长按某个按钮弹出菜单。

方法名

#模拟手指对元素或坐标的长按操作
#参数:
#	el:元素
#	x:x坐标
#	y:y坐标
#	duration:长按时间,毫秒
TouchAction(driver).long_press(el=None,x=None,y=None,duration=1000).perform()

示例

使用坐标的形式点击WLAN(650,650),2秒后,长按(650,650)的位置持续2秒

核心代码

TouchAciton(driver).tap(x=650,y=650).perform()
time.sleep(2)
TouchAction(driver).long_press(x=400,y=400,duration=2000).release().perform()

额外补充

长按<===>按下.等待.抬手

2.8.5、移动操作【掌握】

应用场景

模拟手指移动操作,比如,手势解锁需要先按下,在移动。

方法名

#模拟手指对元素或坐标的移动操作
#参数:
# 	el:元素
#	x:x坐标
#	y:y坐标
TouchActon(driver).move_to(el=None,y=None).perform()

2.9、获取手机的分辨率【掌握】

应用场景

自动化测试可能会需要根据当前设备的屏幕分辨率来计算一些点击或者滑动的坐标

方法名

#获取手机分辨率
driver.get_window_size()

示例

输出当前设备的屏幕分辨率

核心代码

print(driver.get_window_size())

执行结果

{“height”:800,'width':480}

2.9.1、手机截图【掌握】

应用场景

有些自动化的操作可能没有反应,但并不报错。此时我们就可以将cozy过后的关键情况,截图留存。后期也可以根据图片发现问题。

方法名

#获取手机分辨率
#参数:
#	filename:指定路径下,指定格式的图片
get_screenshot_as_file(filename)

示例

1、打开设置页面
2、截图当前页面保存到当前目录,命名为screen.png

核心代码

driver.get_screenshot_as_file(os.getcwd())+os.sep+'./screen.png'

执行结果

#项目目录下会将设置页面保存成screen.png

2.9.2、获取和设置手机网络

应用场景

视频应用在使用流量查看视频的时候,大部分都会提示用户正在是否继续播放。作为测试人员,我们可能需要自动化的形式来判断是否有对应的提示。即,用流量的时候应该有提示,不用流量的时候应该没有提示。

2.9.2.1、获取手机网络

属性名

#获取手机网络
driver.network_connection

示例

获取当前网络类型,并打印

核心代码

print(driver.network_connection)

结果对照

Possible values:
	value(Alias)	 | Data | Wifi  | Airplane Mode
	-----------------------------------------------
	0(None)			 | 0	| 0		|0
	1(Airplane Mode) | 0	| 0		|1
	2(Wifi only)	 | 0	| 1		|0
	3(Data only)	 | 1	| 0		|0
	6(All network on)| 1	| 1		|0

2.9.2.2、设置手机网络

方法名

#设置手机网络
#参数:
#	connectionType:网络类型
driver.set_network_connection(connectionType)

核心代码

driver.set_nwtwork_connection(1)

执行结果

设备变为飞行模式

注意点

网络的类型,建议使用系统提供的类型
from appium.webdriver.connectiontype import ConnectionType

3.0、发送键到设备【掌握】

应用场景

模拟按“home键”等等操作,比如,很多有按俩次返回键退出应用的功能,如果这个功能需要我们做自动化,那么已定位会用到这个方法

方法名

#发送键到设备
#参数:
#	keycode:发送给设备的关键代码
#	merastate:关于被发送的关键代码的元信息,一般为默认值
driver.press_keycode(keycode,metastate=None)

注意点

按键对应的编码,可以在百度搜索关键字“android keycode”

示例

点击三次音量加,再点击返回,再点击俩次音量减

核心代码

driver.press_keycode(24)
driver.press_keycode(24)
driver.press_keycode(24)
driver.press_keycode(4)
driver.press_keycode(25)
driver.press_keycode(25)

3.1、操作手机通知栏【掌握】

应用场景

测试即时通信类软件的时候,如果A给B发送一条信息,B的通知蓝肯定会显示对应的消息,我们想通过通知栏来判断B是否收到消息,一定要先操作手机的通知栏

方法名

#打开手机通知栏
driver.open_notification()

注意点

appium官方并没有未我们提供关闭通知的api,那么现实生活怎么关闭,就怎么关闭,就怎样操作就行,比如,手指从下往上滑动,或者,按返回键

示例

打开通知栏,俩秒后,关闭通知栏

核心代码

driver.open_notifications()
time.sleep(2)
diver.press_keycode(4)

3.2、启动应用

应用场景

启动应用。你一定很迷惑,不是再初始化配置信息已经指定了应用,脚本运行的时候就需要启动应用,为什么还要有这个方法去启动应用。这个方法是配置close_app()使用的。

示例

driver.close_app()
driver.launch_app()

方法

driver.launch_app()

3.3、应用重置

应用场景

重置应用。相当“恢复出厂默认值”的效果。这个方法不需要入参

方法

driver.reset()

3.4、获取当前Activity

应用场景
得到当前应用的activity。只适用于Android。此方法不需要括号“()”或入参。

方法

driver.current_activity

3.5、缩放屏幕

方法

#在0%到100%内双指缩放屏幕
driver.pinch()

3.6、放大屏幕

方法

#放大屏幕,在100%以上放大屏幕。
driver.zoom()

3.7、拉出文件

方法

#从设备中拉出文件。
driver.push_file()
3.8、推送文件

方法

#推送文件到设备中去
driver.pull_file()