Appium自动化常用adb操作封装

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
简介: Appium自动化常用adb操作封装

一、前置说明


在Appium自动化中,经常需要使用adb命令与设备进行交互,所以有必要把常用的adb操作封装成一个类


二、代码实现


import os
import platform
import re
import subprocess
from common import path
from common.exception import AndroidSDKUninstalledError, AndroidDevicesNotFoundError
from common.logger import logger
class ADBRunner:
    def __init__(self):
        self._check_adb_is_installed()
    @staticmethod
    def run_adb(command):
        try:
            result = subprocess.run(command, capture_output=True, text=True, check=True, shell=True)
            logger.debug(f"Execute adb command: {command}")
            return result.stdout.strip()
        except subprocess.CalledProcessError as e:
            logger.error(f"Execute adb command failure: {e}")
            return None
    def _check_adb_is_installed(self):
        result = self.run_adb("adb --version")
        if not result:
            raise AndroidSDKUninstalledError('Android SDK is not installed or configured.')
        return result
    def adb_connect_device(self, device):
        return self.run_adb(f'adb connect {device}')
    def get_connected_device_udids(self):
        """
        获取所有连接设备的序列号udid
        """
        res = self.run_adb('adb devices')
        pattern = r'\b((?!of\b)\S+)\s+device'
        devices = re.findall(pattern, res)
        if not devices:
            raise AndroidDevicesNotFoundError('No connected mobile devices found.')
        logger.info(f'Devices found: {devices}')
        return devices
    @property
    def _grep(self):
        if platform.system() == 'Windows':
            return 'findstr'
        else:
            return 'grep'
    def get_activities(self, udid=None):
        """
        获取当前设备的所有top activities, 输出结果示例:
        ['com.android.settings/.Settings c4e2e17 pid=3637',
        'com.mumu.launcher/.Launcher 9392da7 pid=1434',
        'com.android.browser/com.android.settings de68b73 pid=3722']
        """
        if not udid:
            udid = self.get_connected_device_udids()[0]
        command = f'adb -s {udid} shell dumpsys activity top | {self._grep} ACTIVITY'
        tops = self.run_adb(command).split('ACTIVITY')
        tops = [top.strip(' ').strip('\n') for top in tops if top]
        logger.debug(f'The top activities on device {udid} are: {tops}')
        return tops
    def get_app_package_and_activity(self, udid=None):
        """
        从 com.android.settings/.Settings c4e2e17 pid=3637,获取包名和活动页面名称
        输出:['com.android.settings', '.Settings']
        用途:
            capabilities = {
                "platformName": "Android",
                "automationName": "uiautomator2",
                "deviceName": "9YS0220306003185",
                "appPackage": "com.tencent.mm",  # 包名
                "appActivity": ".ui.LauncherUI",  # 活动页面名称
            }
        """
        last_activity_info = self.get_activities(udid)[-1]
        pattern = r'(\S+) (\S+) pid=(\d+)'
        match = re.match(pattern, last_activity_info)
        if match:
            package, activity = match.group(1).split('/')
            return [package, activity]
        else:
            raise
    def get_apk_path(self, package_name, udid=None):
        """
        从设备中使用包名,获取应用程序的APK路径。
        """
        if not udid:
            udid = self.get_connected_device_udids()[0]
        # 使用pm path命令获取应用程序的APK路径
        command = f'adb -s {udid} shell pm path {package_name}'
        result = self.run_adb(command)
        if result and result.startswith('package:'):
            apk_path = result.replace('package:', '').strip()
            return apk_path
        else:
            logger.error(f"APK path for package '{package_name}' not found on the device {udid}.")
            return None
    def get_apk_version(self, package_name, udid=None):
        """
        获取应用程序的版本号。
        """
        if not udid:
            udid = self.get_connected_device_udids()[0]
        # 使用dumpsys package命令获取应用程序的版本号
        command = f'adb -s {udid} shell dumpsys package {package_name} | {self._grep} versionCode'
        result = self.run_adb(command)
        match = re.search(r'versionCode=(\d+)', result)
        if match:
            version_code = match.group(1)
            return version_code
        else:
            logger.error(f"Version code not found for package '{package_name}'.")
            return None
    def pull_apk_from_device(self, package_name, output_dir=None, apk_name=None, udid=None):
        """
        根据包名从当前设备中将应用程序的APK文件复制至本地。
        用于:
            capabilities = {
                "platformName": "Android",
                "automationName": "uiautomator2",
                "deviceName": "9YS0220306003185",
                "app": apk_path,  # 用在这里
                # "appPackage": "com.tencent.mm",
                # "appActivity": ".ui.LauncherUI",
            }
        """
        if not udid:
            udid = self.get_connected_device_udids()[0]
        if not output_dir:
            output_dir = path.get_apk_resources_dir()
        # 获取应用程序的APK路径
        apk_path = self.get_apk_path(package_name)
        apk_name = apk_name if apk_name else package_name
        apk_version = self.get_apk_version(package_name)
        if apk_path:
            # 构建本地输出路径
            local_output_path = os.path.join(output_dir, f"{apk_name}_{apk_version}.apk")
            # 使用adb pull命令将APK复制到本地
            command = f'adb -s {udid} pull {apk_path} {local_output_path}'
            result = self.run_adb(command)
            if result:
                logger.info(f"APK successfully pulled to: {local_output_path}")
                return local_output_path
            else:
                logger.error("Failed to pull APK from device.")
if __name__ == '__main__':
    adb = ADBRunner()
    print(adb.get_connected_device_udids())
    print(adb.get_app_package_and_activity())
    print(adb.get_apk_path('cn.com.open.mooc'))
    print(adb.get_apk_version('cn.com.open.mooc'))
    print(adb.pull_apk_from_device('cn.com.open.mooc'))
相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
目录
相关文章
|
22天前
|
测试技术 Android开发 iOS开发
Appium 是一个开源的自动化测试框架,它支持多种平台和多种编程语言
Appium是一款开源自动化测试框架,支持iOS和Android多平台及多种编程语言。通过WebDriver协议,开发者可编写自动化测试脚本。在iPhone上实现屏幕点击等操作需安装Appium及其依赖,启动服务器,并设置所需的测试环境参数。利用Python等语言编写测试脚本,模拟用户交互行为,最后运行测试脚本来验证应用功能。对于iPhone测试,需准备真实设备或Xcode模拟器。
55 1
|
2月前
|
测试技术 API Android开发
《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
【7月更文挑战第15天】这是关于自动化测试框架中Selenium API二次封装的教程总结。教程中介绍了如何设计一个支持不同浏览器测试的页面基类(BasePage),该基类包含了对Selenium方法的二次封装,如元素的输入、点击、清除等常用操作,以减少重复代码。此外,页面基类还提供了获取页面标题和URL的方法。
61 2
|
3月前
|
数据采集 Web App开发 前端开发
Selenium:自动化Web浏览器操作的强大工具
**Selenium** 是一款用于自动化Web应用测试和模拟用户行为的工具,支持多种浏览器和编程语言。安装包括安装Selenium库和对应浏览器的WebDriver。基本用法包括导入库、启动浏览器、查找与操作页面元素、等待元素加载及关闭浏览器。在实际项目中,Selenium常用于Web测试、爬虫、自动化表单填写等,优点是跨平台、模拟真实用户行为,但性能较低且依赖浏览器。
82 9
|
3月前
|
测试技术
Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)
Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)
|
3月前
|
程序员 API 计算机视觉
技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)
技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)
75 0
|
4月前
|
数据采集 Java 开发工具
一文2500字从0到1教你搭建Android自动化python+appium环境
一文2500字从0到1教你搭建Android自动化python+appium环境
一文2500字从0到1教你搭建Android自动化python+appium环境
|
4月前
|
前端开发 JavaScript 测试技术
深入理解自动化测试框架:Selenium与Appium的比较
【5月更文挑战第29天】 在快速发展的软件行业中,自动化测试已成为保证软件质量和缩短发布周期的关键。本文深入分析了两个领先的自动化测试框架——Selenium和Appium,探讨了它们的核心原理、应用场景以及优缺点。通过细致的比较,为软件开发团队提供选择合适测试工具的参考依据,并强调了在不同环境下如何优化测试流程以提高测试效率和准确性。
|
4月前
|
中间件 测试技术 API
探索自动化测试工具的新边界:Selenium与Appium的集成实践
【4月更文挑战第30天】 随着移动应用和Web应用的不断融合,传统的自动化测试工具需要适应新的测试环境。本文将详细分析Selenium和Appium这两款流行的自动化测试工具的集成实践,探讨如何构建一个能够同时支持Web和移动端应用的自动化测试框架。通过对比两者的技术架构、功能特性以及在实际项目中的集成过程,我们旨在为读者提供一个清晰的指导,帮助他们在复杂的应用环境中实现高效、稳定的自动化测试流程。
|
4月前
|
前端开发 JavaScript 测试技术
深入探索自动化测试框架:Selenium与Appium的对比分析
【4月更文挑战第29天】 在快速迭代的软件发展环境中,自动化测试已成为确保软件质量和加速产品上市的关键步骤。本文将重点探讨两种广泛使用的自动化测试框架——Selenium和Appium,通过对比它们的核心特性、适用场景及执行效率,为软件开发和测试团队提供选择指南。文章不仅分析了各自的技术架构和脚本语言支持,还讨论了它们在处理Web应用和移动应用测试时的优缺点,旨在帮助读者根据项目需求做出更加明智的选择。
|
4月前
|
Cloud Native 关系型数据库 MySQL
云原生数据仓库产品使用合集之在云数据仓库ADB中,GROUP BY操作中出现NULL值,如何解决
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。