基于Appium,封装自己的常用方法
Appium算是老牌移动端App自动化测试工具了,在使用它的过程中,使用者经常会根据个人习惯,把较常用的方法封装在一起,方便调用。以下是我的封装,希望对你有启发。
from typing import Dict, NoReturn, Tuple, List, Union, Optional
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from appium.webdriver.webelement import WebElement as MobileWebElement
from selenium.webdriver.common.by import By
from loguru import logger
import time class AppDriver:
def __init__(self, command_executor: str, desired_caps: Optional[Dict]) -> NoReturn:
self.driver = webdriver.Remote(command_executor, desired_caps) def find_element(self, element: Tuple[str, Union[str, Dict]]) -> MobileWebElement:
"""
寻找元素
"""
by = element[0]
value = element[1]
try:
if self.is_element_exist(element):
if by == "id":
return self.driver.find_element(By.ID, value)
elif by == "name":
return self.driver.find_element(By.NAME, value)
elif by == "class":
return self.driver.find_element(By.CLASS_NAME, value)
elif by == "text":
return self.driver.find_element(By.LINK_TEXT, value)
elif by == "partial_text":
return self.driver.find_element(By.PARTIAL_LINK_TEXT, value)
elif by == "xpath":
return self.driver.find_element(By.XPATH, value)
elif by == "css":
return self.driver.find_element(By.CSS_SELECTOR, value)
elif by == "tag":
return self.driver.find_element(By.TAG_NAME, value)
else:
raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.")
except Exception as e:
logger.error(">>>>>>>> failed to find element: %s is %s. Error: %s" % (by, value, e)) def find_elements(self, element: Tuple[str, Union[str, Dict]]) -> Union[List[MobileWebElement], List]:
"""
寻找一组元素
"""
by = element[0]
value = element[1]
try:
if self.is_element_exist(element):
if by == "id":
return self.driver.find_elements(By.ID, value)
elif by == "name":
return self.driver.find_elements(By.NAME, value)
elif by == "class":
return self.driver.find_elements(By.CLASS_NAME, value)
elif by == "text":
return self.driver.find_elements(By.LINK_TEXT, value)
elif by == "partial_text":
return self.driver.find_elements(By.PARTIAL_LINK_TEXT, value)
elif by == "xpath":
return self.driver.find_elements(By.XPATH, value)
elif by == "css":
return self.driver.find_elements(By.CSS_SELECTOR, value)
elif by == "tag":
return self.driver.find_elements(By.TAG_NAME, value)
else:
raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.")
except Exception as e:
logger.error(">>>>>>>> failed to find elements: %s is %s. Error: %s" % (by, value, e)) def find_all_child_element_by_xpath(self, element: Tuple[str, Union[str, Dict]]) -> Union[List[MobileWebElement], List]:
"""
寻找元素的所有子元素
"""
by = element[0]
value = element[1]
try:
if self.is_element_exist(element):
if by == "xpath":
child_value = value + '/child::*'
return self.driver.find_elements(By.XPATH, child_value)
else:
raise NameError("Please enter the correct targeting elements 'xpath'.")
except Exception as e:
logger.error(">>>>>>>> failed to find elements: %s is %s. Error: %s" % (by, value, e)) def save_screenshot(self, picture_name: str) -> NoReturn:
"""
获取屏幕截图
"""
fmt = '%Y%m%d%H%M%S' # 定义时间显示格式
date = time.strftime(fmt, time.localtime(time.time())) # 把传入的元组按照格式,输出字符串
picture_name = "../Result/" + picture_name + "-" + date + ".jpg"
self.driver.get_screenshot_as_file(picture_name) def get_screen_size(self) -> Tuple[int, int]:
"""
获取手机屏幕大小
"""
x = self.driver.get_window_size()['width']
y = self.driver.get_window_size()['height']
return x, y def swipe_screen(self, direction: str, duration_ms: int = 800) -> NoReturn:
"""
屏幕向上滑动
"""
location = self.get_screen_size()
if direction.lower() == "up":
x = int(location[0] * 0.5)
start_y = int(location[1] * 0.75)
end_y = int(location[1] * 0.25)
self.driver.swipe(x, start_y, x, end_y, duration_ms)
elif direction.lower() == "down":
x = int(location[0] * 0.5)
start_y = int(location[1] * 0.25)
end_y = int(location[1] * 0.75)
self.driver.swipe(x, start_y, x, end_y, duration_ms)
elif direction.lower() == "left":
start_x = int(location[0] * 0.75)
y = int(location[1] * 0.5)
end_x = int(location[0] * 0.05)
self.driver.swipe(start_x, y, end_x, y, duration_ms)
elif direction.lower() == "right":
start_x = int(location[0] * 0.05)
y = int(location[1] * 0.5)
end_x = int(location[0] * 0.75)
self.driver.swipe(start_x, y, end_x, y, duration_ms)
else:
print("请输入正确的方向") def tap_screen(self, positions: List[Tuple[int, int]], duration: Optional[int] = None) -> NoReturn:
"""
用最多五个手指轻拍一个特定的地方,保持一定的时间
用法:tap_screen([(100, 20), (100, 60), (100, 100)], 500)
"""
self.driver.tap(positions, duration) def click(self, element: Tuple[str, Union[str, Dict]], found_index: int = -1) -> NoReturn:
"""
点击按钮
"""
if found_index == -1:
self.find_element(element).click()
else:
self.find_elements(element)[found_index].click() def send_keys(self, element: Tuple[str, Union[str, Dict]], value: str, clear_first: bool = False, click_first: bool = False, found_index: int = -1) -> NoReturn:
"""
键盘输入
"""
if found_index == -1:
if click_first:
self.find_element(element).click()
if clear_first:
self.find_element(element).clear()
self.find_element(element).send_keys(value)
else:
if click_first:
self.find_elements(element)[found_index].click()
if clear_first:
self.find_elements(element)[found_index].clear()
self.find_elements(element)[found_index].send_keys(value) def scroll_to_text(self, text) -> NoReturn:
"""
滚动到指定的text
"""
uiautomator_cmd = "new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text(\"%s\").instance(0))" % text
self.driver.find_element_by_android_uiautomator(uiautomator_cmd) def get_attribute(self, element: Tuple[str, Union[str, Dict]], attribute_name: str = 'text', found_index: int = -1) -> Optional[Union[str, Dict]]:
"""
获取元素属性
"""
if found_index == -1:
return self.find_element(element).get_attribute(attribute_name)
else:
return self.find_elements(element)[found_index].get_attribute(attribute_name) def is_element_exist(self, element: Tuple[str, Union[str, Dict]], wait_seconds: int = 10) -> bool:
"""
判断元素是否存在
"""
by = element[0]
value = element[1] try:
if by == "id":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.ID, value)))
elif by == "name":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.NAME, value)))
elif by == "class":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.CLASS_NAME, value)))
elif by == "text":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.LINK_TEXT, value)))
elif by == "partial_text":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.PARTIAL_LINK_TEXT, value)))
elif by == "xpath":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.XPATH, value)))
elif by == "css":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.CSS_SELECTOR, value)))
elif by == "tag":
WebDriverWait(self.driver, wait_seconds, 1).until(expected_conditions.presence_of_element_located((By.TAG_NAME, value)))
else:
raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.")
except:
return False
return True def is_text_exist(self, text: str, wait_seconds: int = 10) -> bool:
"""
判断text是否于当前页面存在
"""
for i in range(wait_seconds):
if text in self.driver.page_source:
return True
time.sleep(1)
return False def quit(self) -> NoReturn:
"""
退出驱动
"""
self.driver.quit()
基于Appium,封装自己的常用方法的更多相关文章
- 基于APPIUM测试微信公众号的UI自动化测试框架(结合Allure2测试报告框架)
框架初衷 前两周组内的小伙伴跟我说她现在测试的微信公众号项目(保险)每次上新产品时测试起来很费时,存在大量的重复操作(点点点),手工测试每个产品可能需要半天到一天的时间,复杂的产品需要两天. 由于保险 ...
- 基于appium的app自动化测试框架
基于appium框架的app自动化测试 App自动化测试主要难点在于环境的搭建,appium完全是基于selenium进行的扩展,所以app测试框架也是基于web测试框架开发的 一.设备连接 (即构建 ...
- 基于highcharts封装的组件-demo&源码
前段时间做的项目中需要用到highcharts绘制各种图表,其实绘制图表本身代码很简单,但是由于需求很多,有大量的图形需要绘制,所以就不得不复制粘贴大量重复(默认配置等等)的代码,所以,后来抽空自己基 ...
- 零成本实现Android/iOS自动化测试:基于Appium和Test Perfect
https://item.taobao.com/item.htm?spm=a230r.1.14.14.42KJ3L&id=527677900735&ns=1&abbucket= ...
- 基于appium的移动端自动化测试,密码键盘无法识别问题
基于appium做自动化测试,APP密码键盘无法识别问题解决思路 这个问题的解决思路如下: 1.针对iOS无序键盘:首先,iOS的密码键盘是可识别的,但是,密码键盘一般是无序的.针对这个情况,思路是用 ...
- 基于jQuery封装的分页组件
前言: 由于项目需要实现分页效果,上jQuery插件库找了下,但是木有找到自己想要的效果,于是自己封装了个分页组件. 思路: 主要是初始化时基于原型建立的分页模板然后绑定动态事件并实现刷新DOM的分页 ...
- 基于AFN封装的带缓存的网络请求
给大家分享一个基于AFN封装的网络请求 git: https://github.com/zhouxihi/NVNetworking #带缓存机制的网络请求 各类请求有分带缓存 , 不带缓存, 可自定义 ...
- 基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件
目录 1. 前言 2. 关于vue-simple-uploader 3. 基于vue-simple-uploader封装全局上传组件 4. 文件上传流程概览 5. 文件分片 6. MD5的计算过程 7 ...
- 基于dispatch_after封装YXTimer
基于dispatch_after封装YXTimer 本人根据dispatch_after封装了一个定时器,支持block以及代理的方式来激活定时器,适用于对精度要求低,耗时短的地方,高端大气上档次,低 ...
- 基于epoll封装的事件回调miniserver
epoll技术前两节已经阐述过了,目前主要做一下封装,很多epoll的服务器都是采用事件回调方式处理, 其实并没有什么复杂的,我慢慢给大家阐述下原理. 在networking.h和networking ...
随机推荐
- GE ifix 5.5中关于历史报警表的制作
在关于污水处理厂项目实施过程中,按照业主要求,需要用到报警历史的查询功能,遂搜资料,整理在ifix5.5下如何实现报警历史的查询,经过一天的研究,以及多天的入坑,出坑,总算完成.现整理如下,供后来人参 ...
- Verilog function的使用
function的用法 function的标准写法如下: function <返回值的类型或是范围> (函数名): <端口说明语句> //input xxx <变量类 ...
- Netty入门(三):EventLoop
前言 Netty系列索引: 1.Netty入门(一):ByteBuf 2.Netty入门(二):Channel IO相关: 1.Java基础(一):I/O多路复用模型及Linux中的应用 上文提到,早 ...
- kali linux重启网卡失败:Job for networking.service failed because the control process exited with error code. See "systemctl status networking.service" and "journalctl -xe" for details. 问题排查
linux菜鸡的时候,总是为了配置网络而烦恼,重启网卡的原因有很多,我这次是因为配置了固定IP[使用第三方工具连接]所以需要重启网卡,出现 Job for networking.service fai ...
- Java面向对象13——抽象类
抽象类 package oop.demon01.demon08; //abstract 抽象类: 类 extends: 类---单继承 (接口可以多继承) public abstract c ...
- JMeter(1)-介绍+环境+安装+使用
一.开发接口测试案例的整体方案: 分析出测试需求,并拿到开发提供的接口说明文档: 从接口说明文档中整理出接口测试案例(包括详细的入参和出参数据以及明确的格式和检查点). 和开发一起对评审接口测试案例 ...
- 37岁Android程序员裸辞,四个月被497家公司拒绝,问猎头后懵了
一位网友在职场论坛上发了一个帖子,他说自己今年三十七岁了,是一名Android老兵,因为和上家公司的领导闹矛盾有了嫌隙,一气之下就裸辞了,如今已经辞职四个月了,也失业了四个月. 每天都在努力投简历,共 ...
- CentOS帮助类语法
目录 一.man获取帮助信息 二.help获得shell内置命令的帮助信息 三.history查看所有命令历史 补充:Linux常用快捷键 一.man获取帮助信息 基本语法:man [命令或配置文件] ...
- Sqli-Labs less13-16
less-13 首先,输入用户名和密码,发现只有成功和失败两种显示,没有数据回显: 然后我们抓包拿到数据: 我们通过上述观察,已经知道这是典型的盲注,可以采用布尔盲注或者时间盲注. 构造注入语句:un ...
- Java虚拟机漫漫学习路,我终于悟了
毕业8年,前5年的职业规划是做计算广告,后来感觉计算广告这一行更注重的是业务而非技术,而自己的性格更适合做技术,所以毅然决然的辞职, 全职1年半时间写了2本关于Java编译器与虚拟机的书,今年年初来到 ...