测开学习DAY38

黑马程序员网课学习(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. 步骤:

  1. 创建 TouchAction 对象

  2. 通过对象调用要执行的动作

  3. 通过 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()
相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms6 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下6 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。6 天前
2026.2.25监控学习
学习
im_AMBER6 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J6 天前
从“Hello World“ 开始 C++
c语言·c++·学习