黑马程序员网课学习(Appium框架)
一、UIAutomatorViewer
1. 应用场景
定位元素的时候必须根据元素的相关特征来进行定位,而 UIAutomatorViewer 就是用来获取元素特征的。
2. 如何获取元素的特征
(1)保证想要查看的元素在当前的屏幕上
(2)打开 uiautomatorviewer 工具
(3)点击左上角左数第二个按钮
(4)点击想要获取特征的元素
(5)查看工具右下角相关的特征信息
3. 使用 uiautomatorviewer 注意点
(1)命令行窗口不要关闭
(2)如果 uiautomatorviewer 闪退
更换jdk为1.8
(3)点击第二个按钮的时候报错
重启adb:adb kill-server ,adb start-server
二、定位元素
1. 如何定位一个元素
(1)find_element_by_id
传入的参数:resource-id 的值
(2)find_element_by_class_name
传入的参数:class 的值
(3)find_element_by_xpath
传入的参数:xpath 表达式
(4)注意点:
如果很多元素的 "特征" 相同,使用 find_element_by_xxx 的方法会找到第一个
也就是说,尽量去找元素特征有唯一性的 "特征" ,来定位。
2. 如何定位一组元素
(1)find_elements_by_id
传入的参数:resource-id 的值
(2)find_elements_by_class_name
传入的参数:class 的值
(3)find_elements_by_xpath
传入的参数:xpath 表达式
(4)概念:
如果通过一组的方式进行定位,获取的返回值不再是一个元素。而是一个列表,列表中装着所有符合这个特征的元素。
3. 定位元素的注意点
如果 find_element_by_xxx 方法,传入了一个没有的条件,会报错,NoSuchElementException
如果 find_elements_by_xxx 方法,传入了一个没有的条件,不会报错,返回一个空列表
python
import time
from appium import webdriver
desired_caps = dict()
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
-------------------- 定位一个元素
# 通过 id 定位放大镜按钮,点击
search_button = driver.find_element_by_id("com.android.settings:id/search")
driver.find_element_by_id("com.android.settings:id/search").click()
# 通过 class 定位输入框,输入hello
driver.find_element_by_class_name("android.widget.EditText").send_keys("hello")
# 通过 xpath 定位返回按钮,点击
driver.find_element_by_xpath("//*[@content-desc='收起']").click()
# -------------------- 定位一组元素
# 通过 id 形式,获取所有id为 "com.android.settings:id/title" 的元素,并且打印文字内容
titles = driver.find_elements_by_id("com.android.settings:id/title")
# print(titles)
# print(len(titles))
# for title in titles:
# print(title.text)
titles[1].click()
# 通过 class_name 的形式,获取所有class 为 "android.widget.TextView" 的元素,并打印其文字内容
textviews = driver.find_elements_by_class_name("android.widget.TextView")
print(len(textviews))
for textview in textviews:
print(textview.text)
# 通过 xpath 的形式,获取所有包含 "设" 的元素,并打印其文字内容
eles = driver.find_elements_by_xpath("//*[contains(@text,'设')]")
print(len(eles))
for i in eles:
print(i.text)
# ------------ 注意点
button = driver.find_element_by_id("xxxxxxx")
button.click()
eles = driver.find_elements_by_id("xxxx")
print(eles)
for i in eles:
print(i)
time.sleep(5)
driver.quit()
三、元素等待
1. 元素等待的概念和应用场景
(1)概念
找元素的时候,通过一个时间的设置,进行等待元素,等待元素出来之后,再来定位,放置报错
(2)应用场景
如果某个元素没有及时出来,那么我们就应该使用元素等待
(3)分类:
隐式等待
显式等待
2. 隐式等待
(1)关键方法:
通过 driver 对象调用 implicitly_wait 方法
设置超时时间
(2)作用:
- 在设置了超时时间之后,后续所有的定位元素的方法都会在这个时间内等待元素的出现。
- 如果出现了,直接进行后续操作。
- 如果没有出现,报错,NoSuchElementException。
3. 显式等待
(1)关键方法:
关键类:WebDriverWait
WebDriverWait 对象中的 until 的方法
(2)作用:
- 在设置了显示等待之后,可以等待一个超时时间,在这个超时时间之内进行查找,默认每0.5秒找一次
- 0.5秒的频率是可以设置的
- 一但找到这个元素,直接进行后续操作
- 如果没有找到,报错,TimeOutException
4. 隐式等待和显式等待的选择
(1)从使用的角度上:
隐式等待更简单
显式等待相对负责
(2)从灵活性的角度上:
显示等待更加灵活,因为可以针对每一个元素进行单独的设置
隐式等待是针对全局的定位元素
(3)关于sleep的问题
sleep不是不能做元素等待,而是不推荐,因为会造成时间上的浪费
(4)从选择的角度:
考虑使用的是单个还是全局
考虑灵活性的问题
python
import time
from appium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
desired_caps = dict()
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# ------- 隐式等待
driver.implicitly_wait(10)
print("---准备找返回进行点击")
driver.find_element_by_xpath("//*[@content-desc='收起']").click()
print("---点完了")
# ------- 显式等待
print("---准备找返回进行点击")
wait = WebDriverWait(driver, 25, 5)
back_button = wait.until(lambda x: x.find_element_by_xpath("//*[@content-desc='收起']"))
back_button.click()
back_button = WebDriverWait(driver, 5, 1).until(lambda x: x.find_element_by_xpath("//*[@content-desc='收起']"))
back_button.click()
WebDriverWait(driver, 5, 1).until(lambda x: x.find_element_by_xpath("//*[@content-desc='收起']")).click()
# 使用显示等待,在20秒的时间内,每3秒钟找一次,id为xxx的元素
WebDriverWait(driver, 20, 3).until(lambda x: x.find_element_by_id("xxx"))
print("---点完了")
time.sleep(5)
driver.quit()
四、元素操作
1. 如何去点击元素
关键方法:click()
2. 如何对输入框进行文字输入
关键方法: send_keys("要输入的文字")
注意点:
默认输入中文是有问题的,需要在连接手机的参数中多加两行代码
python
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
3. 如何对输入框进行文字的清空
关键方法:clear()
4. 如何获取文本内容
关键属性:text
5. 如何获取元素的位置
关键属性:location
是一个字典,字典中有 x 和 y 两个 key
取到的数据类型是 int 的
6. 如何获取元素的大小
关键属性:size
是一个字典,字典中有 width 和 height 两个 key
取到的数据类型是 int 的
7. 如何根据元素的属性名获取属性值
关键的方法:get_attribute("属性名")
注意点:
想要获取 resource-id 使用 resourceId 属性名 API>=18
想要获取 class 使用 className 属性名 API>=18
想要获取 content-desc 使用 name 属性名
其他的,都可以参考 uiautomator viewer 中的 属性名
python
import time
from appium import webdriver
desired_caps = dict()
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
time.sleep(2)
# 点击
driver.find_element_by_id("com.android.settings:id/search").click()
# 输入和清空输入框
# 2. 点击 "放大镜"
driver.find_element_by_id("com.android.settings:id/search").click()
# 3. 输入 "hello"
input_label = driver.find_element_by_id("android:id/search_src_text")
input_label.send_keys("hello")
# 4. 暂停 2 秒
time.sleep(2)
# 5. 清空所有文本内容
input_label.clear()
# 6. 暂停 5 秒
time.sleep(5)
# 7. 输入 "你好"
print("----")
input_label.send_keys("你好")
print("----")
# 获取文本内容
eles = driver.find_elements_by_id("com.android.settings:id/title")
for i in eles:
print(i.text)
# 获取元素的位置和大小
search_button = driver.find_element_by_id("com.android.settings:id/search")
print(search_button.location)
print(search_button.location["x"])
print(search_button.location["y"])
print(search_button.size)
print(search_button.size["width"])
print(search_button.size["height"])
# 获取元素的属性值
eles = driver.find_elements_by_id("com.android.settings:id/title")
for i in eles:
print(i.get_attribute("enabled"))
print(i.get_attribute("clickable"))
print(i.get_attribute("text"))
print(i.get_attribute("resourceId"))
print(i.get_attribute("className"))
eles = driver.find_elements_by_class_name("android.widget.TextView")
for i in eles:
print(i.get_attribute("text"))
print(i.get_attribute("name"))
time.sleep(5)
driver.quit()
五、滑动
1. swipe滑动方式
从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动
(1)方法:
driver.swipe(起始x坐标, 起始y坐标, 结束x坐标, 结束y坐标, 持续时间ms)
(2)特点:
参数是坐标点
持续时间短,惯性大
持续时间长,惯性小
2. scroll滑动方式
从一个元素滑动到另一个元素,直到页面自动停止。
(1)方法:
driver.scroll(起始元素, 结束元素)
(2)特点:
参数是元素
没有持续时间,有惯性
3. drag_and_drop滑动方式
从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置。
(1)方法:
driver.drag_and_drop(起始元素, 结束元素)
(2)特点:
参数是元素
没有持续时间,没有惯性
4. 三种方式的选择
有惯性,传入参数坐标:swipe,设置较短的持续时间
有惯性,传入参数元素:scroll
无惯性,传入参数坐标:swipe,设置较长的持续时间
无惯性,传入参数元素:drag_and_drop
python
import time
from appium import webdriver
desired_caps = dict()
# 手机参数
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# 应用参数
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
# 获取driver
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# swipe ----------------------------
driver.swipe(100, 2000, 100, 1000)
driver.swipe(100, 2000, 100, 100)
driver.swipe(100, 2000, 100, 100, 5000)
# 滑动的距离越长,展示的效果越靠后
# 距离相同时,持续时间越长,惯性越小
# scroll & drag_and_drop ----------------------------
save_button = driver.find_element_by_xpath("//*[@text='存储']")
more_button = driver.find_element_by_xpath("//*[@text='更多']")
driver.scroll(save_button, more_button)
driver.drag_and_drop(save_button, more_button)
time.sleep(20)
# 退出driver
driver.quit()
六、TouchAction
1. 概念和作用
高级手势,可以将小的动作组合成一系列复杂的动作
2. 步骤:
-
创建 TouchAction 对象
-
通过对象调用要执行的动作
-
通过 perform 进行执行
3. 轻敲
(1)关键方法:tap
(2)参数:
可以传入元素:使用 element 参数
可以传入坐标:使用 x 和 y 参数
多次点击:使用 count 参数
4. 按下
(1)关键方法: press
(2)参数:
可以传入元素:使用 el 参数
可与传入坐标:使用 x 和 y 参数
5. 抬起
关键方法:release
6. 等待
(1)关键方法:wait
(2)参数:
等待的时长(毫秒):使用 ms 参数
7. 长按
(1)关键方法:long_press
(2)参数:
可以传入元素:使用 el 参数
可以传入坐标:使用 x 和 y 参数
设置持续时间:使用 duration 参数(毫秒)
额外补充:长按 == 按下.等待.抬手
8. 移动
(1)关键方法:move_to
(2)参数:
可以传入元素:使用 el 参数
可以传入坐标:使用 x 和 y 参数
python
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
desired_caps = dict()
# 手机参数
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# 应用参数
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
# 获取driver
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# ------ 长按操作
TouchAction(driver).tap(x=650, y=650).perform()
time.sleep(2)
TouchAction(driver).long_press(x=650, y=650, duration=2000).perform()
# ------ 等待操作
TouchAction(driver).tap(x=650, y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650, y=650).wait(2000).release().perform()
# ------ 按下和抬起
TouchAction(driver).press(x=650, y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650, y=650).perform()
TouchAction(driver).press(x=650, y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650, y=650).release().perform()
# ------ 轻敲
# 找到要点击的元素
wlan_button = driver.find_element_by_xpath("//*[@text='WLAN']")
# 1. 创建touchaction对象
# 2. 调用想要执行的动作
# 3. 使用perform执行动作
TouchAction(driver).tap(wlan_button).perform()
TouchAction(driver).tap(x=650, y=650).perform()
# 1. 创建touchaction对象
touch_action = TouchAction(driver)
# 2. 调用想要执行的动作
touch_action = touch_action.tap(wlan_button)
# 3. 使用perform执行动作
touch_action.perform()
time.sleep(10)
driver.quit()
python
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
desired_caps = dict()
# 手机参数
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# 应用参数
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.ChooseLockPattern'
# 获取driver
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 如果代码过长,可以使用回车进行换行
# 换行的时候默认会多一个 右斜线 是正常的
# 如果不希望出现这个 右斜线 可以将整句代码用括号括起来,然后再使用回车换行即可
(TouchAction(driver).press(x=244, y=856).move_to(x=721, y=843)
.move_to(x=1203, y=846).move_to(x=1197, y=1346)
.move_to(x=721, y=1336).move_to(x=238, y=1336)
.move_to(x=717, y=1809).release().perform())
time.sleep(10)
driver.quit()
七、手机操作API
1. 如何获取手机分辨率
(1)关键方法:driver.get_window_size()
(2)返回值:字典
里面有两个key。分别是 width 和 height
宽和高的值是 int 类型的
2. 如何截图
(1)关键方法:driver.get_screenshot_as_file
(2)参数:文件的路径
如果直接写了文件名,则会默认保存在项目目录下
3. 如何获取和设置当前手机的网络
(1)获取网络状态
属性:network_connection
(2)设置网络状态
方法:set_network_connection
参数:网络类型
注意点:
网络的类型,建议使用系统提供的类型
`from appium.webdriver.connectiontype import ConnectionType`

4. 发送键到设备
(1)关键方法:driver.press_keycode
(2)参数:按键对应的编码
(3)参考的keycode
https://blog.csdn.net/feizhixuan46789/article/details/16801429
5. 操作通知栏
(1)打开
driver.open_notifications
(2)关闭
使用返回键:press_keycode(4)
python
import time
from appium import webdriver
from appium.webdriver.connectiontype import ConnectionType
desired_caps = dict()
# 手机参数
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# 应用参数
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
# 获取driver
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 获取当前设备的分辨率
print(driver.get_window_size())
print(driver.get_window_size()["width"])
print(type(driver.get_window_size()["width"]))
# 截图
driver.get_screenshot_as_file("screen.png")
driver.get_screenshot_as_file("/Users/Yoson/Desktop/screen.png")
# 获取当前网络
print(driver.network_connection)
# 设置当前网络
driver.set_network_connection(1)
# 不推荐
if driver.network_connection == 4: # 4=data only
print(1)
else:
print(0)
# 推荐的
if driver.network_connection == ConnectionType.DATA_ONLY:
print(1)
else:
print(0)
# 发送键到设备
# 需求:三次音量+ 返回 两次音量-
driver.press_keycode(24)
time.sleep(2)
driver.press_keycode(24)
time.sleep(2)
driver.press_keycode(24)
time.sleep(2)
driver.press_keycode(4)
time.sleep(2)
driver.press_keycode(25)
time.sleep(2)
driver.press_keycode(25)
time.sleep(2)
# 打开通知栏
driver.open_notifications()
time.sleep(3)
# 关闭通知栏
driver.press_keycode(4)
time.sleep(10)
driver.quit()