Appium-Python-Client 源码剖析 (一) driver 的元素查找方法

目录

前言

源码版本:0.9

结构图:

mobileby.py

appium 的 webdriver.py

selenium 的 webdriver.py

seleniumdriver

appiumdriver


前言

Appium-Python-Client是一个用于Python语言的Appium客户端库,它提供了丰富的API和功能,用于编写和执行移动应用程序的自动化测试。在本文中,我们将深入剖析Appium-Python-Client的源码,重点关注driver的元素查找方法。

Appium 的实用方法都藏在 Client 的源码里,我尝试在这里剖析一下 Client 的源码,第一篇,我们直接从大家最关注的元素查找说起。
注意!对于 driver 和 webelement 实例,均有对应的元素查找方法(webelement 查找的是下面的子元素),本文讨论的元素查找针对的是 driver 实例。

源码版本:0.9

结构图:

mobileby.py

OK,现在假如我们需要自定义一些 find 方法,比如 find_element_by_xxxx,我们该怎么做?我们看到,appium 提供了一些扩展的 find 方法,它有它自己的一套方式,例如 ACCESSIBILITY_ID 等,要想自定义实现这些方法,appium 首先做的就是:自定义一个 MobileBy 类,这个类从 By 类中继承,然后添加一些需要的属性,这些属性的 value 就是一些文本,不用担心他们不起作用,假如你熟悉 webdriver 的原理,应该会更好地理解。

#!/usr/bin/env python
from selenium.webdriver.common.by import By

class MobileBy(By): #这里显然是一个继承
    """三个扩展属性,清清楚楚地罗列在这里"""
    IOS_UIAUTOMATION = '-ios uiautomation'
    ANDROID_UIAUTOMATOR = '-android uiautomator'
    ACCESSIBILITY_ID = 'accessibility id'

既然他继承自 By 类,我们直接戳到 By 类看一下,因为 By 类中还有一个 classmethod 下面会用到:

class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"

    @classmethod #好吧,我是一个类方法,下文中会用到我
    def is_valid(cls, by): #cls是把类对象本身传进来
        for attr in dir(cls):
            if by == getattr(cls, attr): #判断是不是可用的查找方式
                return True
        return False

这个 MobileBy 类在哪边起作用?我们去跟踪一下,来到这里:

appium 的 webdriver.py
def find_element_by_ios_uiautomation(self, uia_string):
    """Finds an element by uiautomation in iOS.

    :Args:
     - uia_string - The element name in the iOS UIAutomation library

    :Usage:
        driver.find_element_by_ios_uiautomation('.elements()[1].cells()[2]')
    """
    #这里直接访问Appium自己定义的几个类属性
    return self.find_element(by=By.IOS_UIAUTOMATION, value=uia_string)

def find_elements_by_ios_uiautomation(self, uia_string):
    """Finds elements by uiautomation in iOS.

    :Args:
     - uia_string - The element name in the iOS UIAutomation library

    :Usage:
        driver.find_elements_by_ios_uiautomation('.elements()[1].cells()[2]')
    """
    return self.find_elements(by=By.IOS_UIAUTOMATION, value=uia_string)

def find_element_by_android_uiautomator(self, uia_string):
    """Finds element by uiautomator in Android.

    :Args:
     - uia_string - The element name in the Android UIAutomator library

    :Usage:
        driver.find_element_by_android_uiautomator('.elements()[1].cells()[2]')
    """
    return self.find_element(by=By.ANDROID_UIAUTOMATOR, value=uia_string)

def find_elements_by_android_uiautomator(self, uia_string):
    """Finds elements by uiautomator in Android.

    :Args:
     - uia_string - The element name in the Android UIAutomator library

    :Usage:
        driver.find_elements_by_android_uiautomator('.elements()[1].cells()[2]')
    """
    return self.find_elements(by=By.ANDROID_UIAUTOMATOR, value=uia_string)

def find_element_by_accessibility_id(self, id):
    """Finds an element by accessibility id.

    :Args:
     - id - a string corresponding to a recursive element search using the
     Id/Name that the native Accessibility options utilize

    :Usage:
        driver.find_element_by_accessibility_id()
    """
    return self.find_element(by=By.ACCESSIBILITY_ID, value=id)

def find_elements_by_accessibility_id(self, id):
    """Finds elements by accessibility id.

    :Args:
     - id - a string corresponding to a recursive element search using the
     Id/Name that the native Accessibility options utilize

    :Usage:
        driver.find_elements_by_accessibility_id()
    """
    return self.find_elements(by=By.ACCESSIBILITY_ID, value=id)

所以,我们现在知道了,appium 的这些扩展方法都是通过继承 webdriver.Remote 类来直接扩展的,appium 扩展了 webdriver.Remote 来满足他的需求,我们尝试去追踪一下 find_element 和 find_elements 这两个核心方法!

selenium 的 webdriver.py

OK,我们终于来到实现的主体(核心)部分:find_element,find_elements:

def find_element(self, by=By.ID, value=None):
        """
        'Private' method used by the find_element_by_* methods.

        :Usage:
            Use the corresponding find_element_by_* instead of this.

        :rtype: WebElement
        """
        if not By.is_valid(by) or not isinstance(value, str):
            raise InvalidSelectorException("Invalid locator values passed in")

        return self.execute(Command.FIND_ELEMENT,
                             {'using': by, 'value': value})['value']

    def find_elements(self, by=By.ID, value=None):
        """
        'Private' method used by the find_elements_by_* methods.

        :Usage:
            Use the corresponding find_elements_by_* instead of this.

        :rtype: list of WebElement
        """
        if not By.is_valid(by) or not isinstance(value, str):
            raise InvalidSelectorException("Invalid locator values passed in")

        return self.execute(Command.FIND_ELEMENTS,
                             {'using': by, 'value': value})['value']

OK,我们从头到尾再试着理一下:

appium 为了实现自己的 find 查找方式,首先自定义了一个 MobileBy 类,给这个类对象塞入了它定义的一些扩展属性,这些属性的值会通过 webdriver 协议推送到 server 端去识别和执行,为了让这些属性运用到 find 方法中,appium 很好地继承和扩展了 webdriver.Remote,然后通过调用 driver 实例的 find_element 和 find_elements 两个核心方法实现元素查找,所以,既然是扩展,appiumdriver 实例可以使用 seleniumdriver 的所有关于元素查找的实例方法,他们的列表我们就可以整理出来了

seleniumdriver

find_element_by_id
find_elements_by_id
find_element_by_name
find_elements_by_name
find_element_by_link_text
find_elements_by_link_text
find_element_by_partial_link_text
find_elements_by_partial_link_text
find_element_by_tag_name
find_elements_by_tag_name
find_element_by_xpath
find_elements_by_xpath
find_element_by_class_name
find_elements_by_class_name
find_element_by_css_selector
find_elements_by_css_selector

appiumdriver

find_element_by_ios_uiautomation
find_elements_by_ios_uiautomation
find_element_by_android_uiautomator
find_elements_by_android_uiautomator
find_element_by_accessibility_id
find_elements_by_accessibility_id

 

  作为一位过来人也是希望大家少走一些弯路

在这里我给大家分享一些自动化测试前进之路的必须品,希望能对你带来帮助。

(软件测试相关资料,自动化测试相关资料,技术问题答疑等等)

相信能使你更好的进步!

点击下方小卡片

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/38769.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg 命令行实现居中高清上下模糊播放效果

FFmpeg 命令行实现居中高清上下模糊播放效果。 1、16:9 的横屏原视频,以 16:9 竖屏上下模糊播放 以该效果播放视频的命令如下: ffplay -i horizontal_test_video_169.mp4 -vf \ "split[a][b]; \ [a]crop(ih/16*9):ih,scaleiw/10:-1,gblursigma5…

周考一之重做

输入一个学生的成绩,如果学习成绩>90分的同学用A表示,60-89分之间用B表示,60分以下的用C表示(10) public static void main(String[] args){ Scanner scanner new Scanner(System.in); System.out.println(“请输入学生成绩:…

短视频seo抖音矩阵号系统源码开发搭建分享

我们自主研发的短视频矩阵系统源码,技术研发的独立核心算法的视频内容管理和展示功能。无需额外的流量接口费用和复杂的配置,轻松地创建和管理短视频内容,短视频矩阵源码是指将抖音平台上的视频资源进行筛选、排序等操作,进而提升…

Python应用实例(二)数据可视化(一)

数据可视化(一) 1.安装Matplotlib2.绘制简单的折线图2.1 修改标签文字和线条粗细2.2 矫正图形2.3 使用内置样式2.4 使用scatter()绘制散点图并设置样式2.5 使用scatter()绘制一系列点2.6 自动计算数据2.7 自定义颜色2.8 使用颜色映射2.9 自动保存图表 数…

一文详解 requests 库中 json 参数和 data 参数的用法

在requests库当中,requests请求方法,当发送post/put/delete等带有请求体的请求时,有json和data2个参数可选。 众所周知,http请求的请求体格式主要有以下4种: application/jsonapplicaiton/x-www-from-urlencodedmult…

国内流行的数据可视化软件工具

在信息爆炸的时代,越来越多的数据堆积如山。但是,这些密集的数据没有重点且可读性较差。因此,我们需要数据可视化来帮助数据易于理解和接受。相比之下,可视化更直观、更有意义,使用适当的数据可视化工具来可视化数据非…

接下来讲一讲Vue的数据代理

首先讲一下原生js的数据代理 原生的 Object.defineProperty() let aa wewewlet person {name: "王李斌",age: 12} Object.defineProperty(person, "address", {// value: 14, 给字段设置值//enumerable:true, 设置动态设置的字段为可以遍历/…

C# MVC 多图片上传预览

一.效果图: 开发框架:MVC,Layui 列表主界面这里就不展示了,可以去看看这篇文章:Layui项目实战,这里讲的是“上传Banner”界面功能: 其中包括,多文件上传,预览&#xff0c…

MySQL数据库,冷备份,热备份,温备份,物理备份,逻辑备份

🧊冷备份 MySQL数据库冷备份的优点包括: 快速备份:冷备份只需要拷贝文件,因此备份速度非常快,不会影响数据库的读写操作。易于归档和恢复:冷备份可以通过简单拷贝文件进行归档和恢复,而且可以…

配置Hadoop_0

配置Hadoop_0 1配置Hadoop100模板虚拟机1.1配置Hadoop100模板虚拟机硬件1.2配置Hadoop100模板虚拟机软件1.3配置Hadoop100模板虚拟机IP地址1.4配置Hadoop100模板虚拟机主机名称/主机名称映射1.5配置Hadoop100模板虚拟机远程操作工具 1配置Hadoop100模板虚拟机 Hadoop100 内存…

信音电子在创业板IPO:募资约9亿元,预计上半年收入约4.3亿元

7月17日,信音电子(中国)股份有限公司(下称“信音电子”,SZ:301329)在深圳证券交易所创业板上市。本次上市,信音电子的发行价为21.00元/股,发行数量为为4300万股,募资总额…

uniapp 小程序 picker 日期时间段选择(精确到年月日时分+周几)

效果图&#xff1a; picker时间选择器 精确到年月日时分周几 需要引入moment.js&#xff0c;有可能引入后在项目内会报错&#xff0c;可以考虑把选择日期作为一个组件引入 1、timepage.vue组件封装 <template><view><picker mode"multiSelector" :va…

什么是计算机蠕虫?

计算机蠕虫诞生的背景 计算机蠕虫的诞生与计算机网络的发展密切相关。20世纪60年代末和70年代初&#xff0c;互联网还处于早期阶段&#xff0c;存在着相对较少的计算机和网络连接。然而&#xff0c;随着计算机技术的进步和互联网的普及&#xff0c;计算机网络得以迅速扩张&…

【产品设计】通用后台管理系统需求及原型设计

后台管理系统&#xff0c;会根据不同公司、不同业务的要求做出改变。 网上很多系统的参考多数为业务中台&#xff0c;过于带有业务色彩。做过三四个后台管理系统&#xff0c;从中总结了一个通用的功能和需求设计模版&#xff0c;供大家参考。本文适用于0-2岁的产品经理做基础功…

J2EEJSP自定义标签库01out标签if标签

目录 一.什么是标签 二.JSP自定义标签库 2.1 JSP标签库是什么 2.2 处理流程 2.3 如何自定义标签 2.4 标签类型 三.开发示例 3.1 out标签 1.创建助手类 2.编写tld&#xff08;标签库的描述&#xff09;文件&#xff0c;&#xff08;必须放在WEB-INF目录或其目录下&a…

基于深度学习的高精度安全帽背心检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度安全帽背心检测识别系统可用于日常生活中或野外来检测与定位安全帽背心目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的安全帽背心目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用…

python与深度学习(二):ANN和手写数字识别二

目录 1. 说明2. 手写数字识别的ANN模型测试2.1 导入相关库2.2 加载数据和模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章训练的模型进行测试…

常见java知识点1

目录 1 什么是Spring框架&#xff1f;Spring框架有哪些主要模块&#xff1f; 2 使用Spring框架有什么好处&#xff1f; 3 Java常用的包&#xff08;列举六个&#xff09; 4 Arraylist 和 Linkedlist 的区别 5 HashMap和Hashtable的区别 6 Java中常见的…

【监控系统】Prometheus监控组件Mysql-Exporter配置实战

Mysql-Exporter主要监控Mysql数据库的稳定性、吞吐量、连接情况、缓冲池使用情况、查询性能等各项指标&#xff0c;是我们压测时常常需要监控的一些指标。 目前&#xff0c;Exporter 支持高于5.6版本的 MySQL 和高于10.1版本的 MariaDB。在 MySQL/MariaDB 低于5.6版本时&#…

推荐10款设计师都在用的3d机械工程软件

新产品和系统的研究和开发需要特定的软件。您必须能够设计建筑物、系统、机械和设备的蓝图和示意图。您还需要能够与其他工程师、绘图员和团队成员协作&#xff0c;同时有效且高效地工作。设计工程师的软件必须简化其流程&#xff0c;以避免妨碍他们的设计和开发工作。 好的工…