webdriver库里的常用 API

2023-12-20 06:46:15

1、webdriver 库里的常用 API

一、appium-python-client 中 webdriver 库里的常用 API
  • 获取当前应用的包名和启动名

    driver.current_package   # 获取当前应用包名
    driver.current_activity  # 获取当前界面启动名
    
  • 关闭当前 APP

    driver.close_app() # 这是一个方法,不是属性,关闭前置代码中打开的 APP
    
  • 启动其它的 APP

    driver.start_activity( "包名","启动名" )  # 可以在当前 APP 内再次打开另外一个 APP
    
  • 退出( 关闭 ) 当前 APP

    driver.quit()  # 可以关闭当前次的会话,失去与手机之间的连接
    
  • 安装卸载 APP

    driver.install_app( "包所在路径" )  # 安装对应的 APK 包
    driver.remove_app( "包名" )  # 卸载之前确保该应用已经安装在手机上
    
  • 判断是否安装了某个 APP

    driver.is_app_installed( "包名" ) # 传入一个包名,返回布尔值,判断当前应用是否被安装
    
  • 在后台运行 APP

    driver.background_app( 时间 ) # 接收一个时间参数,单位是毫秒,让应用置于后台运行一定的时间
    
  • 查询手机的时间

    driver.device_time # 这是一个查询当前设备时间的属性
    
  • 获取当前设备的屏幕分辨率

    driver.get_window_size()  # 返回一个字典,包含了设备的宽度和高度
    
  • 发送键到设备

    driver.keyevent( 码值 ) # 可以发送一个数值代表具体的手机操作,例如 4 就代表点击返回键
    
  • 进行手机截图

    driver.get_screenshot_as_file( "./1.png" )  # 将当前手机所在界面进行截图,传入的是希望的最终文件路径
    
  • 获取当前屏幕内元素结构

    driver.page_source  # 这是一个属性,可以返回当前手机界面中对应元素的 xml 文档格式信息
    
  • 操作手机通知栏【了解】

    driver.open_notifications()
    
  • 获取手机当前网络【了解】

    print(driver.network_connection) # 这是一个属性,返回一个数字,表示当前设备连接的网络
    
  • 设置手机网络【了解】

    driver.set_network_connection(1) # 接收的是一个数字类型,表示不同的网络类型状态
    
二、上传文件到手机

我们之前在 adb 操作中可以通过 adb push 或者 adb pull 命令轻松的实现文件在PC与手机设备之间的传输操作,但是有了在 appium 的 webdriver 库中不能直接对文件整体进行操作,它允许操作是文件里具体的数据内容。同时手机对于数据的编码有自已的要求,所以如果我们想要将PC机上的一个文件最终上传到手机里,需要做的事情是先拿到该文件中的数据源,然后进行一系统的编码、解码操作,最终将满足手机支持的数据格式以字符的形式写入到手机对应的存储位置

# -*- coding=utf-8 -*-

import base64

# 导入python需要的 webdriver 库
from appium import webdriver

# 定义一个空字典来存放具体的配置参数
desired_caps = dict()

# 书写具体的参数
desired_caps["platformName"] = "android"  # 当前的系统平台名称
desired_caps["platformVersion"] = "5.1.1"  # 当前连接设备的 android 版本
desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名

# 获取对应的连接
driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )

# 读取2.txt里的内容
with open( "2.txt","r",encoding="utf8" ) as f1:
    original_data = f1.read()

# 将从文件中读取出来的原始数据进行编码,编码成 utf8 [ 因为手机支持是经过 base64规则加密之后的utf8 ]
utf8_data = original_data.encode("utf8")

# 将上述编码成 utf8 规则的字符进行 base64 加密处理
base64_utf8_data = base64.b64encode( utf8_data )

# 将数据处理成 base64 加密后的utf8 编码之后还需要处理成 str 的格式才能写入手机
str_data = str( base64_utf8_data,"utf8" )

# 将具体的内容写入到手机具体的目录当中
driver.push_file( "./sdcard/000.txt",str_data )
三、拉取手机文件到本地

拉取文件与上传文件思路完全一致,不一样的就是具体的代码书写,一个是从PC到手机,一个是从手机到 PC

# -*- coding=utf-8 -*-

import base64

# 导入python需要的 webdriver 库
from appium import webdriver

# 定义一个空字典来存放具体的配置参数
desired_caps = dict()

# 书写具体的参数
desired_caps["platformName"] = "android"  # 当前的系统平台名称
desired_caps["platformVersion"] = "5.1.1"  # 当前连接设备的 android 版本
desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名

# 获取对应的连接
driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )

# 先从手机的相应的目录下拿到对应的文件数据
phone_data = driver.pull_file( "./sdcard/0000.txt" )

# 我们从手机里拿到的是经过 base64 规则之后的 utf8 编码字符,所以我们首先需要进行 base64 的解密操作
utf8_data = base64.b64decode( phone_data )

# 此时我们手机有的是 utf8 对应的编码形式,我们如果想要写到PC机里,就需要对该数据进行字符化。
str_utf8 = str( utf8_data,"utf8" )

# 将数据写入到对应的目录里
with open( "./a.txt","w+",encoding="utf8" ) as f:
    f.write( str_utf8 )

2、安卓之UIAutomator使用

一、UIAutomator 基本介绍
  • 定义:uiautomator 是 安卓 sdk 中自带的一个用于调试的工具。
  • 作用:通过 uiautomator 我们可以定位原生 APP 中界面里出现的元素,获取到该元素的具体信息。从而方便我们使用 python 脚本来对其进行定位操作
二、UIAutomator 基本使用
  1. 启动 uiautomator 工具 【因为后期经常使用,所以建议生成快捷方式】

  1. 通过该工具可以执行:打开之前已保存的截国、截取当前屏幕、带框框架截取当前屏幕、保存当前屏幕信息截图

    • open 操作: 因为在测试一款 APP 的时候我们可能会频繁的去定位不同界面里的不同元素,这个时候每次都去执行截屏操作会浪费时间且容易出错,所以我们会在定位获取信息之前将有可能操作到的界面整体信息都保存在本地,然后下次使用的时候只需要 open 打开我们本地的源文件就可以了。
    • 截取当前屏幕+带框架截取当前屏幕:二者在使用上没有太大的区别,当我们使用第一种截取操作无法成功的时候可以尝试第二种
    • 保存操作:保存操作主要是为了服务于 open ,我们可以在截取到某个界面之后,将它对应的界面和界面的中的元素信息保存一份到本地,方便下次使用。
  2. 注意:

    • 如果在我们截屏的时候出现了错误,那么最有可能的就是 uiautomator 的 adb 服务与 我们之前的 appium adb 服务产生了冲突,所以在此时我们可以选择将 appium 服务器停止,先将需要的屏幕信息进行保存,然后再开启 appium 服务。

    • 在一些分辨率比较好的电脑设备上执行打开操作的时候,有可能会无法显示正常的下拉框,所以此时我们可以将当前的设备分辨率调低然后进行操作。

三、UIAutomator 使用体验

示例代码

# -*- coding=utf-8 -*-

# 导入python需要的 webdriver 库
from appium import webdriver

# 定义一个空字典来存放具体的配置参数
desired_caps = dict()

# 书写具体的参数
desired_caps["platformName"] = "android"  # 当前的系统平台名称
desired_caps["platformVersion"] = "5.1.1"  # 当前连接设备的 android 版本
desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名

# 获取对应的连接
driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )


driver.find_element_by_xpath( "//*[contains(@text,'WLAN')]" ).click()

3、元素定位操作

一、 获取元素前言

我们当前最终想要做的事情就是通过 python 去编写测试脚本,从而让我们之前手工的测试操作可以演变成运行对应的 py 文件。所以在这个过程中我们肯定会做的事情就是找到某个元素 ,然后对这个元素进行具体的操作。这以这个找元素就是我们的获取 | 定位元素,在 appium-python-client 当中定义了多种定义元素的方法函数,我们只需要调用就可以!

在 appium-python-client 的webdriver 库中,按着类型来说常见的查找元素方式就是 按着类名查找、按id名查找、按xpath 路径进行查找,为了方便记忆。此处给分成二类三种规则,分别是一次只找一个,一次找多个。不论是哪一种规则,都可以按 类名、id 名、xpath 路径进行查找

二、获取单个元素
  • 按类名查找单个
driver.find_element_by_class_name( "类名" )  # 传入一个类名会返回一个元素
  • 按id名查找单个
driver.find_element_by_id( "id名" ) # 传入一个id名会返回对应的一个元素
  • 按xpath 规则查找单个
driver.find_element_by_xpath( "xpath 规则" )  # 传入一个路径规则 会返回对应的一个元素
三、获取多个元素
  • 按类名查找多个

    driver.find_elements_by_class_name( "类名" )  # 传入一个类名会返回具有该类名的多个元素
    
  • 按id名查找多个

    driver.find_elements_by_id( "id名" ) # 传入一个id名会返回具有该id名的多个元素
    
  • 按xpath 查找多个

    driver.find_elements_by_xpath( "xpath 规则" )  # 传入一个路径规则 会返回满足该规则的所有元素
    
四、获取元素细节
  • 通过上面的二类 六个函数我们可以发现在 webdriver 库中,选择到元素个数与采用的规则无法,如果使用的是?单个元素单个元素类型的方法,返回的结果一定是单个。如果使用的是?多个元素多个元素?类型的方法返回的一定是列表。

  • 如果在使用?单个元素单个元素类型的方法时传入了一个不存在的属性值( id class xpath ),这个时候会抛出语法异常

  • 如果在使用多个元素多个元素类型的方法时传入了一个不存在的属性值( id class xpath ),这个时候不会有任何错误的语法提示。

  • 如果在使用多个元素多个元素类型的方法时传入了一个只存在一次的属性值,那么这个时候返回的是一个元素,但是该元素依然被放在了一个列表当中,且该列表里只有一个元素,我们需要使用下标进行访问。

    单个元素. 类似于 find_element_by_id() 这类每次只查找一个的元素的方法 ??
    多个元素. 类似于 find_elements_by_id() 这类每次可以获取到多个元素的方法 ??

4、元素事件和属性

常见的元素事件和属性操作

当我们使用 python 脚本获取到一个元素之后就可以对它执行具体的操作,这里我们列举了几个经常使用到的事件操作以及常见的属性获取操作

  • 点击操作

    driver.find_element_by_XXX("定位元素的属性").click() # 找到某个元素后对它执行点击
    
  • 输入字符操作

    driver.find_element_by_XXXX( "定位元素的属性" ).send_keys( "写入的内容" ) # 在选中的输入控制中输入具体的内容【中文需要处理】
    
  • 清空输入内容操作

    driver.find_element_by_XXX( "定位元素的属性" ).clear() # 将选中的输入控制内容清空
    
  • 获取不同属性值操作

    # -*- coding=utf-8 -*-
    
    # 导入python需要的 webdriver 库
    from appium import webdriver
    
    # 定义一个空字典来存放具体的配置参数
    desired_caps = dict()
    
    # 书写具体的参数
    desired_caps["platformName"] = "android"  # 当前的系统平台名称
    desired_caps["platformVersion"] = "5.1.1"  # 当前连接设备的 android 版本
    desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
    desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
    desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名
    
    # 获取对应的连接
    driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )
    # 使用的思路就是先获取到某个具体的元素,然后用这个元素对象去调用 get_attribute() 方法
    # 在该方法中传入想要获取的属性值名称,常用的四个值有:
    # resourceID  获取当前元素的 id 值
    # className   获取当前元素的 类名 值
    # text        获取当前的 text 属性值
    # name     获取当前元素的 content-des或text 属性值
    serarch_btn = driver.find_element_by_id( "com.android.settings:id/search" )
    print( serarch_btn.get_attribute( "name" ) )
    

    属性操作截图示例

    属性和事件操作注意事项

    • click() 我们一般会认为是一个PC端的鼠标操作事件,在后续的 APP 操作中我们可能更多的是使用 tap
    • obj.get_attribute() 操作可以帮助我们获取元素身上的某些具体属性值,但是有些属性它是获取不到的
    • send_keys() 在发送中文的时候我们需要在 desired capability 中添加具体的配置参数
    send_keys() 方法处理中文

    desired_caps["resetKeyboard"] = True # 重置设备的输入键盘
    desired_caps["unicodeKeyboard"] = True # 采用unicode码输入

    # -*- coding=utf-8 -*-
    
    # 导入python需要的 webdriver 库
    from appium import webdriver
    
    # 定义一个空字典来存放具体的配置参数
    desired_caps = dict()
    
    # 书写具体的参数
    desired_caps["platformName"] = "android"  # 当前的系统平台名称
    desired_caps["platformVersion"] = "5.1.1"  # 当前连接设备的 android 版本
    desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
    desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
    desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名
    desired_caps["resetKeyboard"] = True # 重置设备的输入键盘
    desired_caps["unicodeKeyboard"] = True  # 采用unicode码输入
    
    # 获取对应的连接
    driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )
    
    # 获取设置界面中的搜索按钮并点击
    driver.find_element_by_id( "com.android.settings:id/search" ).click()
    
    # 进入到搜索界面之后选中 搜索框 并输入测试内容
    driver.find_element_by_id( "android:id/search_src_text" ).send_keys( "测试中文字符" )

5、元素等待操作

一、元素获取等待前言

在我们使用元素定位方法去查找元素的时候由于不同的原因可能会出现某个元素我们无法立即获取到。但有的时候这个元素是真正存在于我们页面 DOM 中的,所以针对这种元素真实存在而我们无法立即获取到的情况,我们就可以在具体获取它之前添加对应的等待操作。其中appium-python-client 中能使用的操作有三种:强制等待、隐式等待、显示等待

二、强制等待

固名思义,所谓的强制等待指的就是在我们定位某个具体元素之前强行的设置一段等待时间,这个操作我们通过 time.sleep() 来设置一定的时间就可以。让代码休眠一段时间后再执行

time.sleep( 3 )  # 表示将代码在等待 3s 之后执行
三、隐式等待

隐式等待由 webdriver 对象实例来调用,它的规则就是如果某个元素在第一时间没有查找到,那么就会等待上一定的时间,然后接着找,如果没有找到那么就会抛出没有找到的异常。

driver.implicitly_wait( 3 )  # 如果元素没有找到则等待 3s 钟之后继续查找,如果找不到则抛出异常
四、显式等待

显式等待指的就是针对于某一个具体元素的获取操作,定义一段时长,在这个时长内每隔一定的时间就去查找一次元素。如果超出我们定义的时长还没有找到,那么就会抛出没有找到的异常

wait = WebDriverWait(driver,5,1) # driver 是当前连接对象  5是自定义timeout时长  1是查询的频率
wait.until( lambda x:x.find_element_by_id( "com.android.settings:id/search" )) # lambda 是匿名函数
五、获取元素等待操作注意事项
  • 使用强制等待的时候我们必须要定义一个明确的时长,但在实际的工作中我们不能精确这个时长
  • 隐式等待在设置的时候属于整个 webdriver 周期,所以一旦设置之后会作用于整个脚本中的元素查找过程。但是有些时候因为 javascript 的存在所以会造成 DOM 中的元素动态加载,因此会造成整个 测试脚本周期的加长
  • 显示等待作用于每一个定义后的元素,是我们比较推荐的一种方式,一般配合 until 使用,它里面接收一个匿名函数

6、webdriver手势操作

一、手势操作前言

我们使用 appium-python-client 里的 webdriver 库最终想要做的事情就是使用它来完成最终的自动化Python脚本去代替之前的手工操作,而在实际的手工操作中我们肯定会用到各种各样的手势动作,所以在 webdriver 库中就会有这样的一些API 存在,此处分为二类进行讲解:单一手势 + TouchAction 类自定义组合手势

二、单一手势操作
  • swipe 滑动:从一个点滑动到另外一个点
# 在此之前执行连接手机操作

# 执行 swipe 操作
driver.swipe( 350,700,350,200,3000 )  # 前四个位置参数为数值,分别表示起始位置的绝对坐标。最后一个参数为时间,单位是毫秒,表示滑动的时长
  • scroll 滑动:专门为 IOS7.X 设计,在默认情况下 Android 是无法使用的。
driver.scroll(  350,700,350,200 ) # 语法规则和 swipe 一样,只是android无效
  • drag_and_drop 拖拽:可以实现从一个点按下拖拽到另外一个点。
# -*- coding=utf-8 -*-

# 导入python需要的 webdriver 库
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.1"  # 当前连接设备的 android 版本
desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名
desired_caps["resetKeyboard"] = True # 重置设备的输入键盘
desired_caps["unicodeKeyboard"] = True  # 采用unicode码输入

# 获取对应的连接
driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )

# 获取 swipe() 操作的起点和终点
save_btn = driver.find_element_by_xpath( "//*[contains(@text,'存储')]" )
more_btn = driver.find_element_by_xpath( "//*[contains(@text,'更多')]" )

# 执行 swipe 操作
driver.drag_and_drop( save_btn,more_btn )

注意:

? 01 swipe() 操作默认具有滑动惯性,只能接收绝对坐标,元点是相对于屏幕左上角为准,不能接收元素对象

? 02 scroll() 在安卓设备上是无法使用的,如果能执行其实和 swipe 是一样的

? 03 drap_and_drop() 操作没有惯性,并且它记录的位置是当前元素被获取时的位置

三、TouchAction 类

上述的三个方法只能满足于单一的手势应用场景,但是在实际的APP使用过程中我们还会遇到其它更多的手势需求,例如左右滑动、轻点屏幕、常按屏幕.......等。因此在 webdriver 库中又提供了一个 TouchAction 类,在该类下定义了几种单一的动作,可以独立使用,同时也可以组合使用,这样我们就可以在使用的时候去自定义自已需要的手势。

  • press(): 短按操作,一般需要配合 release 和 perform 使用
TouchAction( driver ).press( arg ).perform()
# arg 是按下的对象,可以是一个具本的元素对象 ,也可以是一个元素对象绝对坐标位置
# 同时传入元素对象和 元素对象的位置时 ,press 识别的是元素对象
# 如果传入的是绝对坐标值那么需要设置的是关键字参数

  • long_press(): 常按操作,类似于一些按钮常按之后会有弹窗
# 执行前置的连接代码

# 获取要操作的无素
save_btn = driver.find_element_by_xpath( "//*[contains(@text,'存储')]" )
more_btn = driver.find_element_by_xpath( "//*[contains(@text,'更多')]" )
WLAN_btn = driver.find_element_by_xpath( "//*[contains(@text,'WLAN')]" )

# 点击 wlan 按钮进入到对应的界面
WLAN_btn.click()

# 进入到 wlan 界面之后常按 wireless 按钮
wireless_btn = driver.find_element_by_xpath( "//*[contains(@text,'wireless')]" )
TouchAction(driver).long_press( wireless_btn ).perform()   # long_press 的参数规则和 press 完全一样


  • tap(): 轻点屏幕,类似于 click 操作
# 执行前置的连接代码

# 获取要操作的无素
save_btn = driver.find_element_by_xpath( "//*[contains(@text,'存储')]" )
more_btn = driver.find_element_by_xpath( "//*[contains(@text,'更多')]" )
WLAN_btn = driver.find_element_by_xpath( "//*[contains(@text,'WLAN')]" )

# 点击 wlan 按钮进入到对应的界面
TouchAction( driver ).tap().perform()  # tap的参数规则和 press 完全一样

  • release(): 离开操作
TouchAction( driver ).press( obj ).release().perform()  # release 就相当于离开动作
  • wait(): 等待操作,它的出现是为了让脚本模拟的手势更加接近于人类的真实操作
TouchAction( driver ).press( obj ).wait(500).release().perform()  # 可以在某一个动作发生之后设置延时
  • move_to(): 移动到,可以模拟手指在不同位置之间的移动
  • perform(): 上述的操作如果没有 perform 在代码中是不会执行的
四、TouchAction 类之 move_to()

move_to() 是一个常用的单一动作,我们可以通过它来执行多点之前的滑动操作

语法格式:TouchAction(driver).press(起点).move_to(位置1).move_to(位置2).release.perform()

其中在执行 move_to 之前我们需要先通过 press 来确定一个按下的起点,后续在 move_to 里设置我们具体的位置点,每个位置都使用坐标来表示,这个坐标是否为绝对坐标,我们可以依据 appium 服务器的版本来确定,换句话说不需要去死记 move_to() 里用的是相对还是绝对坐标,当我们发现是某种规则的时候我们只需要按着对应的规则去设置即可。

需求:使用 move_to() 去绘制手机设置里的图案解锁功能

示例代码

# -*- coding=utf-8 -*-

# 导入python需要的 webdriver 库
import time
from appium import webdriver

# 定义一个空字典来存放具体的配置参数
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.support.wait import WebDriverWait

desired_caps = dict()

# 书写具体的参数
desired_caps["platformName"] = "android"  # 当前的系统平台名称
desired_caps["platformVersion"] = "5.1.1"  # 当前连接设备的 android 版本
desired_caps["deviceName"] = "emulator-5554" # 当前已连接设备的名称
desired_caps["appPackage"] = "com.android.settings"  # 被测试 APP 的包名
desired_caps["appActivity"] = ".Settings" # 被测试 APP 的启动名
desired_caps["resetKeyboard"] = True # 重置设备的输入键盘
desired_caps["unicodeKeyboard"] = True  # 采用unicode码输入

# 获取对应的连接
driver = webdriver.Remote( "http://localhost:4723/wd/hub",desired_caps )

# 获取 swipe() 操作的起点和终点
save_btn = driver.find_element_by_xpath( "//*[contains(@text,'存储')]" )
more_btn = driver.find_element_by_xpath( "//*[contains(@text,'更多')]" )
WLAN_btn = driver.find_element_by_xpath( "//*[contains(@text,'WLAN')]" )

# 滑动当前的屏幕,直到 安全 按钮出现,然后点击 安全按钮
for i in range(2):
    driver.drag_and_drop( save_btn,more_btn )

# 获取 安全 按钮,并点击
safe_btn = driver.find_element_by_xpath( "//*[contains(@text,'安全')]" ).click()

# 进入到解锁绘制界面
driver.find_element_by_xpath( "//*[contains(@text,'屏幕锁定方式')]" ).click()
driver.find_element_by_xpath( "//*[contains(@text,'图案')]" ).click()

time.sleep( 2 )

# 执行绘制操作
TouchAction(driver).press(x=120,y=425).move_to( x=360,y=425 ).wait(200).move_to(x=360,y=665).wait(200).release().perform()

文章来源:https://blog.csdn.net/dragons_/article/details/135054955
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。