Appium+Python+Android使用技巧

本文介绍了Appium,一个开源的自动化测试工具,支持Android和iOS平台,可与多种编程语言集成。文章详细讲解了环境配置、自动化原理、常用命令和PythonAPI示例,以及定位工具和常见问题解决方法。
摘要由CSDN通过智能技术生成

Appium介绍

Appium 是一个开源的自动化测试工具,支持 Android、iOS 平台上的原生应用,支持 Java、Python、PHP 等多种语言,开发可快速上手,用于提供各种手机事件模拟接口,通过编写代码模拟用户真实操作进行测试。Appium 封装了 Selenium,安卓自动化和web自动化语法上互通。

Appium环境

以下仅本人配置:
Ubuntu 22.04.1
jdk 11.0.19 (安装Android Studio的时候自动装的)
Python 3.10.6
Android SDK 34
PyCharm 2023.1.3

App自动化原理

如何通过代码操作不同操作系统不同版本的手机终端?

自动化脚本 —>> Appium Server —>> Android SDK 环境 —>> 被测手机终端

启动Appium Server,并通过adb连接手机
在这里插入图片描述
Python自动化脚本如何操作手机终端(Appium日志角度):

  • 自动化脚本发送http请求,请求参数:终端设置的参数
  • 创建会话
  • 确认终端设备是否连接,并确定安卓版本,确认设置参数是否与终端的设置一样
  • Appium会推送一个包 ‘AppiumBootsrap.jar’,模拟器上 api包:appium server指令今夕接受操控手机端(自测没有这个jar)
  • 相应的http请求,如200或者500

常用adb 命令

adb shell ip route show table main   # 查看路由表
adb shell cat /proc/net/dev|grep rmnet_data  # 获得流量变化
adb shell cat /proc/net/dev|grep wlan0  # 获得wifi变化
adb shell ip -f inet addr  # 查看手机数据方式
adb shell ifconfig  # 可以查看网络类型和网速

常用python命令

driver.terminate_app(package_name)  # 退出应用,防止干扰下一次操作

driver.current_package   # 获取包名
driver.cirrent_activiry  # 获取活动名

x_locate, y_locate = qqlive_driver.get_window_size()['width'], qqlive_driver.get_window_size()['height']
qqlive_driver.tap([(0.94 * x_locate, 0.092 * y_locate)])  # 点击

driver.implicitly_wait(5)  # 隐式等待,5秒内查找到元素则执行,5秒后还没找到才报错
WebDriverWait(self.driver, 10).until(lambda x: x.find_element(by=AppiumBy.XPATH, value='//*[@text="通讯录"]')).click()  # 显示等待

print(i.get_attribute("enabled"))  # 通过id i获取控件属性值
print(i.get_attribute("clickable"))
print(i.get_attribute("text"))
print(i.get_attribute("resourceId")) # 返回resource-id,需API>=18
print(i.get_attribute("className"))  # 返回class,需API>=18
print(i.get_attribute("name"))  # 返回content-desc/text, 这个测试不生效
get_attribute('contentDescription') # 返回content-desc

# 有惯性传元素:scroll;无惯性传元素:drag_and_drop;
# 有惯性传坐标:swip;  无惯性传坐标:swipe & duration;
swipe(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: int = 0) # 开始和结束的x,y值,还有区间时间
scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Optional[int] = None) # 从一个元素,移动到另一元素,有惯性
drag_and_drop(self, origin_el: WebElement, destination_el: WebElement) # 从一个元素,移动到另一元素替换原元素位置

# 点击目标下一个元素
friend_start = self.driver.find_element(by=AppiumBy.XPATH, value='//*[@text="联系人"]').location
friend_end = self.driver.find_element(by=AppiumBy.XPATH, value='//*[@text="联系人"]').size
friend_start_new_y = friend_start['y'] + friend_end['height'] + 10
self.driver.tap([(friend_start['x'], friend_start_new_y)])

# python打印时间
milliseconds = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] 
time.time()  # 当前时间秒数显示

print("测试", end="\n\n")  # 打印“测试”,并空一个空行
print(f"测试{a}")    # a是变量,假设a = Appium,打印“测试Appium”
print("耗时{:.2f}s!".format(a))  # a是变量,假设a = 1.11111,打印"耗时1.11s!"

常用代码

# numpy处理数组
rx_speed = [0, 0.1, 0.12, 3.12, 4.124, 3.223, 3.339, 0.45, 0.78, 0.43]
print(numpy.median(rx_speed))  # 求中位数:0.615
print(numpy.mean(rx_speed))  # 求平均值:1.5685999999999998
print(np.sum(rx_speed))  # 求和:15.685999999999998
print(max(rx_speed) / 4)  # 最大值除以4: 1.031
print(np.array(rx_speed) > 0)   # [False  True  True  True  True  True  True  True  True  True]
print(np.extract(np.array(rx_speed) > 1, rx_speed)) # [3.12  4.124 3.223 3.339]
print(np.partition(rx_speed, -1)[-1])   # 最大值 4.124
print(np.partition(rx_speed, -2)[-2])   # 次大值 3.339
print(np.partition(rx_speed, 0)[0])     # 最小值 0.0
print(np.partition(rx_speed, 1)[1])     # 次小值 0.1

# 去掉所有0的列
np.delete(speed_up, np.argwhere(np.all(speed_up[..., :] == 0, axis=0)), axis=1).flatten()

# 保留和最大列
speed_down = speed_down[:, np.argmax(np.sum(speed_down, axis=0))]

def extract_info(string):
    """
    分离字符串中的小数和字符,输入字符串12.3MB或者12MB,输出12.3和MB或者12和MB
    :param string:字符串12.3MB
    :return:(12.3, MB)
    """
    match = re.search(r"(\d+\.\d+)([MB])", string)
    if match:
        number = float(match.group(1))
        unit = match.group(2)
        return number, unit
    else:
        match = re.search(r"(\d+)([MB])", string)
        if match:
            number = int(match.group(1))
            unit = match.group(2)
            return number, unit
        else:
            return None, None


def unifiedUnit(number, unit):
    """
    统一单位为兆,如输入1GB,输出1024.MB
    :param number:数量
    :param unit:单位
    :return:以MB结尾的数量
    """
    match unit:
        case "GB":
            number = number * 1024
        case "MB":
            pass
        case "KB":
            number = number / 1024
    return round(number, 3)   # 保留三位小数

常用定位工具

https://github.com/appium/appium-inspector/releases

获取应用的包名和启动页

  1. 已经安装应用的话,直接打开应用输入以下命令(获取的Activity不一定是启动页):
    adb shell dumpsys activity | grep mFocusedApp
    > com.netease.cloudmusic/.activity.MainActivity    # 以网易云为例,包名/Activity名字\
    
  2. 使用aapt工具(有时候也不靠谱):
    aapt dump badging '/home/xxx/software/安装包/安卓安装包/网易云音乐-8.10.80.apk' | grep package
    > package: name='com.netease.cloudmusic' versionCode='8010080' versionName='8.10.80' compileSdkVersion='34' compileSdkVersionCodename='14'
    aapt dump badging '/home/zhangtao/software/安装包/安卓安装包/网易云音乐-8.10.80.apk' |grep launchable-activity
    > launchable-activity: name='com.squareup.leakcanary.internal.DisplayLeakActivity'  label='Leaks' icon='res/mipmap-anydpi-v26/a.xml'
    

常见问题

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值