UI测试自动化-Web-Python-Appium

一、Appium-ADB

1.Appiym设计原理:

Appium Web Server

(1)C/S架构,appium的核心是一个web服务器,提供了一套接口,会接收客户端发过来的命令,然后在移动设备上运行命令,最后把运行结果通过HTTP响应包返回给客户端

(2)session,每个client连接到server以后都会创建一个seession,自动化始终围绕一个session进行

2.应用:

(1)Native App : 原生应用

(2)Web APP: 移动浏览器应用,使用移动平台的浏览器访问的应用

(3)Hybrid App:混合应用,把一个基于webview实现的功能进行包装的应用

3.ADB

(1)ADB:Android Debug Bridge ,一个手机调试工具

(2)ADB客户端 ---> ADB服务器

(3)ADB客户端:Client端:运行在开发及其中,用来发送adb命令

(4)ADB服务器:Server端,运行在开发及其中,用来管理Client端和手机的Daemin之间的通信

(5)Daemon守护进程:运行在调试设备中,手机或模拟器用来接收并执行 adb 命令

4.adb常用命令

(1)获取包名和界面名:

adb shell dumpsys window | findstr usedApp

包名(package):决定程序的唯一性(不是应用的名字) 获取包名--操作APP的必要条件

界面名(activity):目前可以理解,一个界面名,对应着一个界面

adb shell dumpsys window(窗口)|findstr usedApp

(2)文件传输--上传文件

adb push 电脑的文件路径 手机的文件夹路径

(3)文件传输 --下载文件

adb pull 手机的文件路径 电脑的文件路径

(4)获取手机日志:

日志是APP手工测试必用的工具

(5)APP启动时间:(性能测试)

adb shell am start -W 包名/启动名

ThisTime:该界面(activity)启动耗时(毫秒)

TotalTime:应用自身启动耗时=ThisTime+应用 application 等资源启动时间(毫秒)

WaitTime:系统启动应用耗时=TotalTime+系统资源启动时间(秒)

(6)冷启动:应用程序未启动到启动

热启动:已经启动了,从后台切到前台的时间

5.当测试过程中发现问题后向获取错误日志信息:

(1)打开被测应用程序,进入到触发缺陷的位置

(2)使用查看日志命令:adb logcat

(3)出发缺陷

(4)获取日志信息

(5)重定向 如:adb logcat >D:\test_file\Appium\logcat\try1.log

6.adb常用命令--其它指令

(1)adb install路径/xx.apk 安装 app 到手机

(2)安装 app 到手机 卸载手机上的 app,需要指定包名

(3)adb devices 获取当前电脑已经连接设备和对应的设备号 --测试自动化时使用 会自动启动服务,也就是(5)

(4)adb shell 进入到安卓手机内部的linux系统命令行中

(5)adb start-server 启动 adb 服务端,出 bug 时使用可以重启服务器,先关闭再启动

(6)adb kill-server 停止 adb 服务端,出 bug 时使用可以重启服务器,先关闭再启动

(7)adb --help 查看 adb 帮助,命令记不清楚时有用

(8)adb connectip:端口 连接手机/模拟器

二、Appium -API

1.appium基础操作api:安装、卸载;appium高级api操作:滑动、拖拽;appium手机操作api(按键)

2.移动端自动化--初始化配置项

(1)platformName:需要连接的手机的平台(不限制大小写)

(2)platformVersion:需要连接的手机的版本号(比如 5.2.1的版本可以填写 5.2.1或5.2或5,以此类推)

(3))devicesName:需要连接的手机的设备号(andoird平台下,可以随便写,但是不能不写)

(4)appPackage:需要启动的程序的包名

(5)appActivity:需要启动的程序的界面名

3.设置中文:

desired_caps[*nicodeKeyboard*]=True

desired_caps[*resetKeyborad*]=True

4.获取driver

driver =webdriver.Remote("http://1270.0.1:4723/wd/hub",

desired caps)

python 复制代码
from appium import webdriver
from appium.options.android import UiAutomator2Options



# Appium启动代码示例
"""
对应 Appium-Python-Client 4.2.4 selenium 4.39.0
"""
# 构造配置项
options = UiAutomator2Options()
options.platform_name = 'Android'
options.platform_version = '12.0'
options.device_name = 'emulator-5556'
options.app_package = 'com.android.settings' # 包名
options.app_activity = '.Settings' # 应用名
# 设置为中文
options.set_capability('unicodeKeyboard', True)
options.set_capability('resetKeyboard', True)
# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', options=options)

三、Appium-基础Api:

1.app基础操作-应用跳转

(1)driver.start_activity(appPackage,appActivity)

appPackage:要打开的程序的包名

appActivity:要打开的程序的界面名

python 复制代码
from time import sleep

from appium import webdriver
# from appium.options.android import UiAutomator2Options

# Appium启动代码示例

#定义字典变量
desired_cap={}
# 构造配置项
desired_cap['platformName']='Android'
desired_cap['platformVersion']='12.0'
desired_cap['deviceName']='emulator-5556'
desired_cap['appPackage']='com.android.settings'
desired_cap['appActivity']='.Settings'

# 设置为中文
desired_cap['unicodeKeyboard']=True
desired_cap['resetKeyboard']=True

# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_cap)

"""
    需求:
        1.情动设置后,暂停三秒,打开通讯录
        2.答应当前默认应用包名、启动名
"""
sleep(3)

driver.start_activity(app_package='com.google.android.contacts', app_activity='com.android.contacts.activities.PeopleActivity')


# 打印包名 、启动名
print("当前所在应用包名:",driver.current_package)
print("当前所在应用启动名:",driver.current_activity)
driver.quit()

2.app基础操作-关闭驱动和app

(1)关闭当前操作的app,不会关闭驱动对象

driver.close_app()

(2)退出app应用

driver.quit()

python 复制代码
from appium import webdriver

"""
对应 Appium-Python-Client 4.2.4 selenium 4.39.0
"""
# from appium.options.android import UiAutomator2Options
options = UiAutomator2Options()
options.platform_name = 'Android'
options.platform_version = '12.0'
options.device_name = 'emulator-5556'
options.app_package = 'com.android.settings' # 包名
options.app_activity = '.Settings' # 应用名
# 设置为中文
options.set_capability('unicodeKeyboard', True)
options.set_capability('resetKeyboard', True)
# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', options=options)
# 在初始化后,先检查driver的类型和可用方法
print("Driver类型:", type(driver))
print("Driver的MRO:", type(driver).__mro__)

# 检查是否有 start_activity 方法
print("是否有 start_activity 方法:", hasattr(driver, 'start_activity'))

# 查看所有方法
methods = [method for method in dir(driver) if not method.startswith('_')]
print("可用方法数量:", len(methods))
print("包含 'activity' 的方法:", [m for m in methods if 'activity' in m.lower()])

# 尝试调用 start_activity
if hasattr(driver, 'start_activity'):
    driver.start_activity(
        app_package='com.android.contacts',
        app_activity='com.android.contacts.activities.PeopleActivity'
    )
else:
    print("driver对象没有start_activity方法")
    # 查看driver的实际类
    print(f"driver的实际类是: {driver.__class__}")

3.安装卸载app 是否安装app

(1)部分应用管理平台在安装了app后,会自动进行检测,如已安装了则会显示【启动】

(2)安装app,app_path为安装文件完整路径名

driver.install_app(app_path)

(3)卸载app,app_id为app包名

driver.remove_app(app_id)

(4) 判断app是否变装,app_id为app包名

driver.is app installed(app id)

python 复制代码
from time import sleep

from appium import webdriver

# Appium启动代码示例

#定义字典变量
desired_cap={}
# 构造配置项
desired_cap['platformName']='Android'
desired_cap['platformVersion']='12.0'
desired_cap['deviceName']='emulator-5556'
desired_cap['appPackage']='com.android.settings'
desired_cap['appActivity']='.Settings'

# 设置为中文
desired_cap['unicodeKeyboard']=True
desired_cap['resetKeyboard']=True

# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_cap)

"""
    需求:
        1.判断微信是否安装,安装--->卸载;没有安装:安装
        2.启动设置界面
        3.置于后台 3秒
        4.关闭设置界面
        5.关闭app驱动
"""
# 判断是否安装 --包名
if driver.is_app_installed("com.tencent.mm"):
    # 卸载
    driver.remove_app("com.tencent.mm")
else:
    # 安装
    driver.install_app(r"D:\test_file\Appium\APK\weixin8066android2980_0x28004234_arm64.apk")

sleep(10)
# 启动设置界面
driver.start_activity('com.android.settings','.Settings')
sleep(3)
# 置于后台3秒
driver.background_app(3)
sleep(3)
# 关闭设置界面
driver.close_app()
print("关闭设置app后获取包名:",driver.current_package)
sleep(3)
# 关闭驱动
driver.quit()

4.app基础操作-置于后台

(1)登陆后置于后台一段时间后,这类安全系数高的APP再重新打开使用时会要求重新登陆!

(2)driver.background app(seconds)

四、Appium -元素定位

1.定位单个元素:

(1)ID定位:driver.find_element by_id(resource-id属性值)

(2)class定位:driver.find element by class name(class属性值)

(3)xpath定位:driver.find element by_xpath(xpath表达式)

(4)name定位:driver.find element by accessibility id(content-desc属性值)

(5)当定位到多个符合条件的元素时,默认返回第一个

2.定位一组元素

(1)使用定位一组元素时,返回的数据是列表

python 复制代码
from appium import webdriver

# Appium启动代码示例

#定义字典变量
desired_cap={}
# 构造配置项
desired_cap['platformName']='Android'
desired_cap['platformVersion']='12.0'
desired_cap['deviceName']='emulator-5556'
desired_cap['appPackage']='com.android.settings'
desired_cap['appActivity']='.Settings'

# 设置为中文
desired_cap['unicodeKeyboard']=True
desired_cap['resetKeyboard']=True

# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_cap)

五、元素操作-API

1.模拟操作

(1)模拟点击 element.click()

(2)模拟输入 element.send_keys(value)

(3)清除文本 element.clear()

2.获取元素信息-文本[断言时使用]、位置、大小

(1)获取文本 element.text

(2)获取位置: element.location

(3)获取大小: element.size

python 复制代码
from time import sleep

from appium import webdriver
from selenium.webdriver.common.by import By

# Appium启动代码示例

#定义字典变量
desired_cap={}
# 构造配置项
desired_cap['platformName']='Android'
desired_cap['platformVersion']='12.0'
desired_cap['deviceName']='emulator-5556'
desired_cap['appPackage']='com.android.settings'
desired_cap['appActivity']='.Settings'

# 设置为中文
desired_cap['unicodeKeyboard']=True
desired_cap['resetKeyboard']=True

# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_cap)
# 获取所有id 为:android:id/title
els=driver.find_elements(By.ID,'android:id/title')
# 遍历打印输出
for el in els:
    print(el.text)
sleep(3)
driver.quit()

3.获取元素属性值 ---用于判断是否为希望的元素

(1)获取属性值:element.get_attribute(属性名)

(2)获取属性值对应的属性名与实际工具(如Appium Inspector)显示可能不一致,如

获取resource-id属性值,el.get_attribute('resourceId')

获取content-desc,el.get_attribute('name')

获取class,el.get_attribute('className')

获取text,el.get_attribute('text')

python 复制代码
from time import sleep

from appium import webdriver
from selenium.webdriver.common.by import By

# Appium启动代码示例

#定义字典变量
desired_cap={}
# 构造配置项
desired_cap['platformName']='Android'
desired_cap['platformVersion']='12.0'
desired_cap['deviceName']='emulator-5556'
desired_cap['appPackage']='com.android.settings'
desired_cap['appActivity']='.Settings'

# 设置为中文
desired_cap['unicodeKeyboard']=True
desired_cap['resetKeyboard']=True

# 获取driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_cap)
# 获取所有id 为:android:id/title
els=driver.find_elements(By.ID,'android:id/title')
# 遍历打印输出
# for el in els:
#     print(el.text)
# sleep(3)

# 使用get_attribute获取这些元素的enable text content-desc ...
for el in els:
    print("1.enabled属性值为:",el.get_attribute('enabled'))
    print("2.text属性值为:",el.get_attribute('text'))
    print("3.content-desc属性值为:",el.get_attribute('name'))
    print("4.resource-id属性值为:",el.get_attribute('resourceId'))
    print("5.class属性值为:",el.get_attribute('className'))
    print("-----------------------------------------")
driver.quit()

六、手势滑动

1.滑动和拖拽设置

2.swipe滑动[原生应用 -如]:

(1)从一个坐标位置滑动到另一个主表为止,只能是两个点之间的滑动

(2)driver.swipe(start_x, start y, end x, end _y, duration=None)

start x:start y:起点Y轴坐标

end x:终点X轴坐标

end y:终点Y轴坐标

duration:滑动这个操作一共持续的时间长度,单位:ms

3.滑动[WebView --如浏览器]:

TouchAction(driver).press(x=start_x, y=start_y).wait(ms=1000).move_to(x=end_x, y=end_y).release().perform()

4.Scoll滑动

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

(2)driver.scroll(origin el,destination el)

origin el:滑动开始的元素

destination el:滑动结束的元素

(3)scroll滑动是两个元素之间的滑动只适合滑动一次的操作

惯性很大

七、手势API

1.TouchAction

(1)创建TouchAction对象

touch_action=TouchAction(driver)

(2)调用高级手势对象所提供的手势方法

touch_action.手势方法

(3)执行手势

touch_action_perform()

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

2.TouchAction-轻敲(类似于点击)

(1)模拟手指对某个元素或坐标按下并快速抬起

(2)实现:元素对象或坐标二选一

touch_action.tap(element=....).perform()

touch_action.tap(x=...,y=...).perform()

python 复制代码
from time import sleep

from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from driver_util import AppiumClient
import warnings
# 忽略DeprecationWarning类型的警告
warnings.filterwarnings("ignore", category=DeprecationWarning)
# 调用示例
client = AppiumClient('com.android.settings', '.Settings')
driver = client.start_driver()
# 业务操作...

"""
    手势操作:TouchAction类
    1.轻敲:tap()
    需求:wifi设置
"""
# 1.轻敲
wlan=driver.find_element(By.XPATH,"//android.widget.TextView[@resource-id='android:id/title' and @text='网络和互联网']")
TouchAction(driver).tap(wlan).perform()
sleep(3)

client.quit_driver()

3.为什么要使用手势操作?

红包雨、九宫格解锁,需要手动操作,之前学习的api最多支持两个元素之间或两个坐标之间进行操作

4.TouchAction-按下和抬起

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

(2)实现:元素对象或坐标二选一

touch_action.press(el=...)perform()

touch_action.release(x=...,y=...)perform()

TouchAction(driver).press(x=loc.get('x'),y=loc.get('y')).release().perform()

python 复制代码
from platform import release
from time import sleep

from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from driver_util import AppiumClient
import warnings
# 忽略DeprecationWarning类型的警告
warnings.filterwarnings("ignore", category=DeprecationWarning)
# 调用示例
client = AppiumClient('com.android.settings', '.Settings')
driver = client.start_driver()
# 业务操作...

"""
    手势操作:TouchAction类
    1.轻敲:tap()
    需求:wifi设置
"""
# 1.轻敲
wlan=driver.find_element(By.XPATH,"//android.widget.TextView[@resource-id='android:id/title' and @text='网络和互联网']")
loc=wlan.location
print(loc)
sleep(3)
# 2.按下和抬起 --效果类似点击
TouchAction(driver).press(x=loc.get('x'),y=loc.get('y')).release().perform()
sleep(3)
client.quit_driver()

5.TouchAction-长按--有个时间

(1)模拟手指对元素或坐标的长按操作

(2)实现:元素或坐标二选一

TouchAction(driver).long_press(el=...,duration=1000).perform()

(3)场景:有些长按和点击出现的菜单不一样;有些是只有长按才出现菜单

6.移动和等待 move_to(x,y) wait()

python 复制代码
from platform import release
from time import sleep

from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from driver_util import AppiumClient
import warnings
# 忽略DeprecationWarning类型的警告
warnings.filterwarnings("ignore", category=DeprecationWarning)
# 调用示例
client = AppiumClient('com.android.settings', '.Settings')
driver = client.start_driver()
# 业务操作...


# 长按
driver.find_element(By.XPATH,"//android.widget.TextView[@resource-id='android:id/title' and @text='网络和互联网']").click()
sleep(3)

# 3.长按
el=driver.find_element(By.XPATH,"//android.widget.TextView[@resource-id='android:id/title' and @text='互联网']").click()
TouchAction(driver).long_press(x=300,y=700,duration=5).perform()
sleep(3)
client.quit_driver()
相关推荐
qq_417695051 小时前
机器学习与人工智能
jvm·数据库·python
漫随流水1 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
yy我不解释2 小时前
关于comfyui的mmaudio音频生成插件时时间不一致问题(一)
python·ai作画·音视频·comfyui
踩着两条虫2 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
紫丁香3 小时前
AutoGen详解一
后端·python·flask
FreakStudio3 小时前
不用费劲编译ulab了!纯Mpy矩阵micronumpy库,单片机直接跑
python·嵌入式·边缘计算·电子diy
jzlhll1233 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
蓝冰凌4 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛4 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js