App自动化测试_Python+Appium使用手册

一、Appium****的介绍

Appium是一款开源的自动化测试工具,支持模拟器和真机上的原生应用、混合应用、Web应用;基于Selenium二次开发,Appium支持Selenium WebDriver支持的所有语言(java、 Object-C 、 JavaScript 、p hp、 Python等,Appium支持任何一种测试框架,

二、Appium架构

Appium 是一个用Node.js编写的HTTP server,它创建、并管理多个 WebDriver sessions 来和不同平台交互,如 iOS ,Android等等.
Appium 开始一个测试后,就会在被测设备(手机)上启动一个 server ,监听来自 Appium server的指令. 每种平台像 iOS 和Android都有不同的运行、和交互方式。所以Appium会用某个桩程序"侵入"该平台,并接受指令,来完成测试用例的运行

三、Appium****的工作原理

Client端发送自动化指令给Appium server,Appium Server接收到client发送的指令后,转换为移动端能够识别的ADB指令,然后发送给移动端设备,并对移动端设备进行操作。

【工作过程】
脚本请求 --> 4723端口appium server ---> 解析参数给PC端4724端口 ---> 发送给设备4724端口 ---> 通过设备4724端口发给bootstrap.jar ---> Bootstrap.jar把命令发给uiautomator

注意: Bootstrap.jar :是 push 到 Android 手机上的一个应用程序,主要是接受 Appium Server 的执行并 运行这些测试指令。而指令的执行正是通过UIAutomator 来驱动的。

三、Appium环境搭建

使用appium服务需要配置依赖环境,以及各个环境之间的版本需要互相兼容;

我目前使用的版本信息:

# JDK版本

jdk-8u261
# android SDK版本

installer_r24.4.1-windows.exe
# appium客户端

Appium-windows-1.15.1.exe
# Appium-Python-Client

pip install Appium-Python-Client==2.11.1

# selenium版本

selenium==4.21.0
# 模拟器

nox_setup_v7.0.2.7_full.exe

网盘获取:

链接:https://pan.baidu.com/s/18uqZfmX9d9HqqSBIEM73uA?pwd=z5ak

提取码:z5ak

3.1、配置jdk环境

详见JDK配置文章:
Windows配置java环境JDK-CSDN博客

3.2、android SDK环境

详见SDK配置文章:
Android SDK下载安装(_指定版本)-CSDN博客

3.3、安装appium客户端

Appium安装除了安装Appium客户端,还要在Python环境中安装Appium-Python-Client,其作用就是将 Python 与 appium 关联起来;

**需要指定版本:**pip install Appium-Python-Client==2.11.1

详见Appium配置文章:
Appium安装及配置(Windows环境)-CSDN博客

3.5、下载模拟器

详见模拟器配置文章:
Android模拟器下载及配置_夜神模拟器-CSDN博客

四、启动App

操作步骤:

  • 启动桌面Appium客户端
  • 启动模拟器或移动设施(确保连接adb)
  • 启动Python脚本

4.1、启动桌面Appium客户端

双击 桌面Appium客户端-->启动服务器

4.2、启动模拟器或移动设施(确保连接adb)

ADB命令: ADB日常使用命令-CSDN博客

启动模拟器后,一般默认会已经连接adb,如果没有连接需要输入adb命令进行连接

bash 复制代码
# 验证是否连接成功
adb devices
# 建立连接
adb connect 127.0.1: 模拟器端口号〈逍遥模拟器21503〉

已连接

4.3、运行Python脚本,启动App

启动参数:

python 复制代码
# 1.导入appium中的webdriver
from appium import webdriver
import time


def startUp():
    print('准备启动app')
    # 2. 启动参数,配置手机连接的参数内容,
    # 所有参数信息都是键值对的方式进行连接
    desire_caps = {
        "deviceName": "127.0.0.1:62001",  # 参数1:当前设备的名称
        "platformName": "Android",  # 参数2:系统
        "platformVersion": "7.1.2",  # 参数3:系统版本号
        "appPackage": "com.android.contacts",  # 参数4:启动的app名称(包名)
        "appActivity": ".activities.PeopleActivity t12",  # 参数5:app界面名称
        "noReset": True,
        "unicodeKeyboard": True
    }
    # 3.发送连接请求
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_capabilities=desire_caps)
    # 等待时间,防止启动后立马关闭
    time.sleep(4)
    # 关闭驱动
    driver.quit()


if __name__ == '__main__':
    startUp()

启动参数说明

待补充

五、元素定位工具

Android SDK 自带的一个工具,在 sdk 的 tools 目录下(一定关闭 appium-desktop 的自带的定位工具后打 开,否则连接不上模拟器/ 真机 )
找到 sdk 下的 tools 里面的 uiautomatorviewer.bat

详见uiautomatorviewer.bat使用文章:
appium元素定位工具_uiautomatorviewer.bat-CSDN博客

六、元素定位

6.1、单个元素定位:find_element

语法:

# 需要导包
from selenium.webdriver.common.by import By

# 用法 -- 传递两个参数:一个是定位属性,一个是该属性的值
driver.find_element(By. 属性 ,' 属性值 ').操作方法

1.通过id定位

resource-id 的值为id

driver . find_element ( By . ID , " xxxx " )

2.通过class_name定位

取class的属性值

driver . find_element ( By . CLASS_NAME , " xxxx " )

取 text 属性值--文本属性

driver . find_element ( By . LINK_TEXT , " xxxx " )

4.通过xpath定位

取元素xpath路径

driver . find_element ( By . XPATH , " xxxx " )
# 使用文本属性比较实用(推荐)

driver.find_element(By.XPATH, '//*[@text="显示"]').click()

driver.find_element(By.XPATH, '//*[@text="亮度"]').click()

5.通过坐标定位driver.tap()

通过坐标定位有一定的局限性

  • 优先:任意的元素都可以通过坐标进行定位操作

  • 缺点:当手机的分辨率发生变化的时候,元素的坐标值也会发生变化

注意点:通过坐标定位的方法,一般使用场景是固定的机型或者固定的分辨率下进行自动化测试

driver.tap()

左边通过[(x,y)]形式传入

duration:表示触碰时间/ms
# 左上角
driver.tap([(144,1327)], duration=100)
# 右下角
driver.tap([(208, 1370)], duration=100)

6.2、多个元素定位find_elements

与 find_element 方式基本一致,这个方法可以同时定位多个元素,返回一个列表
例如:通过 ID 定位到多个元素,我想点击第一个元素

driver . find_elements ( By . ID , "xxxxx" )[ 0 ]. click ()

list1 = driver . find_elements ( By . ID , "xxxxx" )
list1 [ 0 ]. click ()

七、元素操作方法

Appium元素的操作方法与Selenium元素操作方法,基本一样

1. click():点击

python 复制代码
# 模拟鼠标点击操作
driver.find_element(By.ID," xxxx ").click()

2. clear():清空

python 复制代码
# 清空元素输入框中内容
driver.find_element(By.ID," xxxx ").clear()

3. send_keys():输入

python 复制代码
# 往输入框中,输入内容值
driver.find_element(By.ID," xxxx ").send_keys("输入的内容")

4. text:获取文本属性值

python 复制代码
# 获得元素的text内容
result = driver.find_element(By.XPATH," xxxx").text
print(result)

5. get_attribute():获取某个标签,元素的属性

python 复制代码
# 获取标签xxx的元素的 class 属性值
driver.find_element(By.ID,'xxx').get_attribute('class')

6. size:获取元素的大小(宽、高)

python 复制代码
# 获取元素的大小,得到一个字典如:{'height': 48, 'width': 640}
driver.find_element(By.ID,' xxxx ').size

7. **location:**获取元素的坐标

python 复制代码
# 获取元素的坐标,得到的是一个字典{}
res = driver.find_element(By.ID,' xxxx ').location

print(res)  # {'x': 108, 'y': 380}

8. **is_selected():**判断元素是否被选中

python 复制代码
# 选中返回True,否则返回False
res = driver.find_element(By.ID, 'xxxx').is_selected()
print(res)  # True/False

9. **is_enabled():**判断元素是否被启用

python 复制代码
# 判断元素是否被启用,返回True / False
res = driver.find_element(By.ID, 'xxxx').is_enabled()
print(res)

10. **is_displayed():**判断元素是否显示

python 复制代码
#判断元素是否显示,返回True / False
res = driver.find_element(By.ID, 'xxxx').is_displayed()
print(res)

八、其它操作

8.1、操作应用包

1、判断是否安装

python 复制代码
# 语法 返回True/False
driver.is_app_installed("应用的包名")

# 可以简单做一个判断,然后进行安装或卸载
if driver.is_app_installed('io.manong.developerdaily'):
    driver.remove_app('io.manong.developerdaily')
    print('app卸载成功')
else:
    driver.install_app(r'D:\MS_App_auto_24_529\toutiao.apk')
    print('app安装成功')

2、安装应用

python 复制代码
install_app("app的绝对路径")

3、卸载应用

python 复制代码
remove_app("应用的包名")

4、获取当前操作的应用的界面名称

current_activity
5、获取包名
driver.current_package

8.2、操作屏幕页面

1.获取屏幕尺寸

方法:driver.get_window_size

python 复制代码
# 得到的是一个字典,width是屏幕的宽度,height为屏幕的高度
dic = driver.get_window_size()

print(dic )  #{'width': 1080, 'height': 1776}
2.页面滑动

app界面为了保证内存优化性,所有可操作的元素只是当前界面存在的元素,所以需要滑动屏幕,进行元素定位

方式1:坐标定位.swipe()

方法 : driver.swipe(x1, y1, x2, y2,duration)
参数
(x1, y1):开始坐标,(x2, y2):结束坐标,duration:滑动时间
注意 :滑动的坐标不能超过屏幕的宽高
**实现思路1:**通过 driver.get_window_size() 获得窗口高和宽 -->按比例滚动

python 复制代码
# 获取屏幕尺寸得到所用坐标
def getSize(driver):
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    x1 = x * 0.75
    x2 = x * 0.25
    y1 = y * 0.75
    y2 = y * 0.25
    return x1, y1, x2, y2

# 完成上滑操作
def swipeUp(driver):
    x1, y1, x2, y2 = getSize(driver)
    driver.swipe(x1, y1, x1, y2, 100)

**实现思路2:**获取两个元素的坐标,在掉用swipe方法,从a元素 滚动到 b元素

python 复制代码
# 获取元素坐标
a_dic = driver.find_element(By.XPATH,'//*[@text="WLAN"]').location  # {'x': 144, 'y': 799}
b_dic = driver.find_element(By.XPATH,'//*[@text="通知"]').location  # {'x': 144, 'y': 1471}

# 将通知 滚动到 WLAN
driver.swipe(b_dic["x"], b_dic["y"], a_dic["x"], a_dic["y"], duration=100)
方式2: 通过元素的相对位置进行滚动
python 复制代码
# 页面滚动
el1 = driver.find_element(By.XPATH, '//*[@text="显示"]')
el2 = driver.find_element(By.XPATH, '//*[@text="WLAN"]')
# 将"显示" 滚动到 "WLAN"位置
driver.scroll(el1, el2)

如图所示,将下面的"显示"滑动到上面的"WLAN"位置

3.获取界面的xml源码

方法 : driver.page_source()
用法 :可以用来断言或检查

python 复制代码
page = driver.page_source()
assert '登陆成功' in page
4.拖拽操作driver.drag_and_drop()

语法:driver.drag_and_drop(el1, el2) --元素1:el1,元素2:el2
作用:将el1元素,拖拽到el2

python 复制代码
# 拖拽操作
el1 = driver.find_element(By.XPATH, '//*[@text="浏览器"]')
el2 = driver.find_element(By.XPATH, '//*[@text="开发者头条"]')
driver.drag_and_drop(el1, el2)
5、事件链TouchAction

**作用:**构建相对比较复杂的,连续的触摸行为

使用步骤
通过" TouchAction" 类,创建事件链对象,然后传入 driver对象
通过添加各种方法完成事件

  • 按下
  • 长按
  • 移动
  • 等待
  • 松手
  • 轻敲
  • ...
    代码示例:
python 复制代码
# 事件链操作TouchAction
# 导包
from appium.webdriver.common.touch_action import TouchAction
# 实例化对象
action = TouchAction(driver)
time.sleep(1)
# 定位元素
ele1 = driver.find_element(By.XPATH, "//*[@text='通知']")
ele2 = driver.find_element(By.XPATH, "//*[@text='WLAN']")

# 拖拽操作,将ele2,拖到 ele1位置
# press:按下操作  .wait(100):按下持续时间 move_to(ele1):移动到目标元素或坐标
action.press(ele1).wait(1000).move_to(ele2)
# 完成后,松手操作 release():松手动作
action.release()
# 提交事件链,生效
action.perform()

# 再次滑动
ele3 = driver.find_element(By.XPATH, "//*[@text='电池']")
action.press(ele3).wait().move_to(ele1)
# 完成后,松手操作 release():松手动作
action.release()
# 提交事件链,生效
action.perform()

# 点击安全
ele4 = driver.find_element(By.XPATH, "//*[@text='安全']")
ele4.click()
time.sleep(0.5)
# 通过事件链,绘制锁屏图案
# 点击屏幕锁定
driver.find_element(By.XPATH, "//*[@text='屏幕锁定']").click()
time.sleep(0.5)
# 点击图案
driver.find_element(By.XPATH, "//*[@text='图案']").click()
time.sleep(2)

# 拖拽绘制图案
action.press(x=182, y=775)\
    .wait(100).move_to(x=449, y=1044) \
    .wait(100).move_to(x=190, y=1311) \
    .wait(100).move_to(x=714, y=1299)
6、截图/截屏
python 复制代码
driver.get_screenshot_as_file('网络情况.png')
time.sleep(1)
driver.save_screenshot('网络情况2.png')
7、其它操作

重置 app
方法 : driver.reset()
用法 :相当于卸载重装应用,所以本地缓存会失效。
模拟摇晃设备
方法 : driver.shake
退出键盘
方法 : driver.hide_keyboard()
app 置于后台运行 x
方法 : driver.background_app(x)
用法 : x 为置于后台的秒数
模拟系统按键
方法 :driver.press_keycode(KEYCODE_BACK)
用法 :根据 AndroidkeyCode 来完成指定操作

键名 描述 键值
KEYCODE_CALL 拨号键 5
KEYCODE_ENDCALL 挂机键 6
KEYCODE_HOME 按键 Home 3
KEYCODE_MENU 菜单键 82
KEYCODE_BACK 返回键 4
KEYCODE_SEARCH 搜索键 84
KEYCODE_CAMERA 拍照键 27
KEYCODE_FOCUS 拍照对焦键 80
KEYCODE_POWER 电源键 2

获取手机的网络信息

- 获取手机的网络信息:网络信息三种模式分别对应数值

飞行模式: 1

无线网络: 2

移动网络: 4

网络情况可以进行组合: 3=1+2,6=2+4

python 复制代码
print(driver.network_connection)

# - 设置手机网络信息

python 复制代码
driver.set_network_connection(2)
time.sleep(1)
print(driver.network_connection)

# - 获取当前手机时间

python 复制代码
print(driver.device_time)

# - 打开通知栏

python 复制代码
driver.open_notifications()

九、时间等待

待补充

十、APP自动化框架设计思想

参考文档:

Appium使用教程_Android篇-CSDN博客

相关推荐
思则变2 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络3 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find4 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取5 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector7 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习7 小时前
Python入门Day2
开发语言·python
Vertira7 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉7 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗7 小时前
黑马python(二十四)
开发语言·python
晓13138 小时前
OpenCV篇——项目(二)OCR文档扫描
人工智能·python·opencv·pycharm·ocr