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 Byclass 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 Truereturn 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 theId/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 theId/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

 

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

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

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

相信能使你更好的进步!

点击下方小卡片

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cocosCreator 3.6以上接入腾迅Bugly 捕捉JS错误 Android

cocosCreator3.6以上接入Bugly上报其实很简单,不需要网上那么多弯弯绕,三须三步走。 1. 按照官网方式接入android的bugly 2. android端写一个Bugly上报管理类 3. 修改你工程目录下native\engine\common\Classes\目录下的Game.h, Game.cpp两个文件&…

字符串编程练习(C++)

ex1 字符串变形 描述 对于一个长度为 n 字符串,我们需要对它做一些变形。 首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把这个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。…

JS-27 前端数据请求方式;HTTP协议的解析;JavaScript XHR、Fetch的数据请求与响应函数;前端文件上传XHR、Fetch

目录 1_前端数据请求方式1.1_前后端分离的优势1.2_网页的渲染过程 – 服务器端渲染1.3_网页的渲染过程 – 前后端分离 2_HTTP协议的解析2.1_HTTP概念2.2_网页中资源的获取2.3_HTTP的组成2.4_HTTP的版本2.5_HTTP的请求方式2.6_HTTP Request Header2.7_HTTP Response响应状态码 3…

多媒体开发之cgo

go语言作为近十年来优秀的现代开发语言的代表,由于继承了c语言的简洁和很多现代语言的表达方式,在广泛的应用场景中得到众多爱好者的喜爱,如何将go和c、c进行联合开发,拓展整个开发生态,不用重复造轮子,掌握…

P1403 [AHOI2005] 约数研究

题目描述 科学家们在 Samuel 星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机 Samuel II 的长时间运算成为了可能。由于在去年一年的辛苦工作取得了不错的成绩,小联被允许用 Samuel II 进行数学研究。 小联最近在研究和约数有关的问题&…

【redis】redis管道简述

redis管道可以一次性发送多条命令。 命令示例如下: [xxxlocalhost ~]$ echo -e "set k4 99\nincr k4\nget k4" | nc localhost 6379 \OK :100 $3 100下面先简述一下这条命令的组成,再简述一下管道的常用场景和注意事项。 首先,|是…

IDEA 搭建Android 开发环境

项目实战 废话不多说开始创建先第一个 Android 项目 步骤一 FILE → New → Project 步骤二-选择 Android 项目模板 选那个安卓机器人,如果没有这个选项,需要升级IDEA版本或者安装安卓插件 选择*Basic Activity* Next-下一步 步骤三-项目初始化 名称、包名、安装位置自行调整…

双电源并用问题与解决方案

双电源并用问题 曾经有客户在电源模块应用过程中出现过这样的应用场景,如下图1所示。客户使用两路电源给后端电路进行供电,要求在不断电的情况下切换输入电源,此过程中发现后端电路会出现损坏。对各个节点波形进行分析后发现,在给…

【C++】STL之list容器的模拟实现

个人主页:🍝在肯德基吃麻辣烫 分享一句喜欢的话:热烈的火焰,冰封在最沉默的火山深处。 文章目录 前言一、list的三个类的关系分析图vector和list的区别1.节点的成员变量以及构造函数2.list的迭代器 二、list的增删查改工作2.1inse…

MFC第十六天 CFileDialog、CEdit简介、(线程)进程的启动,以及Notepad的开发(托盘技术-->菜单功能)

文章目录 CCommonDialogCFileDialogCEdit托盘技术进程的启动附录1:启动线程方式附录2:MFC对话框的退出过程 CCommonDialog 通用对话框 CCommonDialog 这些对话框类封装 Windows 公共对话框。 它们提供了易于使用的复杂对话框实现。 CFileDialog 提供用于打开或保存文件的标准对…

C#在工业自动化领域的应用前景如何?

在2021年,C#与工业自动化已经开始结合,并且这种趋势有望在未来继续发展。C#是一种功能强大的编程语言,其面向对象的特性、跨平台支持以及丰富的类库和工具,使其成为在工业自动化领域应用的有力工具。 我这里刚好有嵌入式、单片机…

Nautlius Chain主网正式上线,模块Layer3时代正式开启

Nautilus Chain 是在 Vitalik Buterin 提出 Layer3 理念后, 对 Layer3 领域的全新探索。作为行业内首个模块化 Layer3 链,我们正在对 Layer3 架构进行早期的定义,并有望进一步打破公链赛道未来长期的发展格局。 在今年年初,经过我…