测开学习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()
相关推荐
骑鱼过海的猫1232 小时前
【git】git学习记录
git·学习·elasticsearch
weixin_409383122 小时前
简单四方向a*寻路学习记录3 将角色世界坐标传给地图数组 计算上下左右四个格子到目的地的f 选择最小的f方向
学习·a星
学编程的闹钟2 小时前
浅谈VMProtectV2.13.8的IAT修复
学习
盐焗西兰花2 小时前
鸿蒙学习实战之路-多端交互最佳实践
学习·交互·harmonyos
AI绘画哇哒哒2 小时前
AI 智能体长期记忆系统架构设计与落地实践
人工智能·学习·算法·ai·程序员·产品经理·转行
JH灰色3 小时前
【大模型】学习路线
学习
林林宋4 小时前
nvidia&cuda&gpu 关系学习
学习
学编程的闹钟4 小时前
102【php开发准备】
学习
半夏知半秋4 小时前
Elasticsearch 分词器
大数据·学习·elasticsearch·搜索引擎·全文检索