学习appium必备的避坑指南
首先感谢白月黑羽和imhelloworld提供的在线教程和视频教程。是你们的教程伴我度过了疫情期间的漫漫长夜。
- 第一个坑:永远属于环境
uiautomatorviewer:用来做APP界面定位用的。
这个文件位于androidsdk\tools\bin\uiautomatorviewer.bat,但是从白月黑羽提供的网盘链接下载软件后,它没办法使用jdk11,需要改安装jdk8。可能是androidsdk版本比较老,不想太折腾,所以我也没有再尝试最新的androidsdk是否支持jdk11。
附上环境变量(还需要有nodejs、python环境)设置:
JAVA_HOME C:\Program Files\Java\jdk1.8.0_211
CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
ANDROID_HOME D:\Programs\androidsdk
path D:\Programs\Python37\Scripts\;D:\Programs\Python37\;C:\Program Files\nodejs\;%JAVA_HOME%\bin;D:\Programs\androidsdk\platform-tools
如果依旧报错,也有可能是androidsdk\tools\lib\find_java.bat文件问题,因为r17 以上的版本重写了这个文件,我们只需要把这个文件替换成r16的版本文件即可。老版本的find_java.bat可以从这下载:
链接:https://pan.baidu.com/s/1ng2EeMJ_jjF_QAbNa0s5LQ
提取码:16b3
androidsdk的下载可以直接去官网先下载Android Studio:Download Android Studio & App Tools - Android Developers
然后通过Android Studio去下载sdk。也可以直接去这个网站下载:Download SDK Platform for Android SDK Manager
- 第二个坑:adb devices报错
我尝试了夜神模拟器,做得真不错!但是公司的笔记本配置还是6年前的,有点扯后腿,玩不转。后来我改用数据线连接真机了。需要说明的是,华为手机或者分家之前的荣耀手机,即使升级了HarmonyOS,照样还是可以使用安卓这一套来测试,我看网上很多人都说HarmonyOS底层还是安卓,大概多多少少和这也有点关系吧。
不过从HarmonyOS的开发者文档来看,以及HarmonyOS万物互联的设计思路,我更多的是觉得安卓这块只是为了兼容,HarmonyOS应该是有自己的一套底层逻辑的,说到底,安卓和HarmonyOS都是在linux内核上面做文章。这就像是容器技术一样,一个linux内核,跑两个不同的docker容器,一个是安卓,一个是HarmonyOS,嗯,这么理解应该没错。(扯远了
如果执行adb devices报错,需要将夜神模拟器中nox_adb.exe替换掉。先将Nox\bin\nox_adb.exe重命名为nox_adb.exe.bak备份下,再将androidsdk\platform-tools\adb.exe复制一份,改名为nox_adb.exe,直接放到Nox\bin\下。
- 第三个坑:查找appPackage和appActivity
建议直接连接真机或者模拟器输入命令。不建议通过apk文件来查找,原因在于:一个要考虑apk版本,一个是网上给的命令并不一定能查到结果。而且你最终还是程序还是要在真机或模拟器上面运行的。
真机或模拟器连接成功,且打开APP的某页面。然后在cmd输入命令:
方法一
adb shell dumpsys activity recents | find "intent={"方法二
adb shell dumpsys activity activities
两个方法大同小异,方法二输出的信息更多,得自己过滤。
- 第四个坑:python程序运行报错
SyntaxError: Non-UTF-8 code starting with ‘\xba‘ in file
这个报错我相信大部分人都不会遇到。只有我这种用着6年前配置的电脑,开不起一个Pycharm,只能在nodepad++上写代码才会遇到这样的辛酸。
将程序文件在nodepad++打开后,全选复制一下,然后菜单栏编码处选择使用UTF-8编码,再粘贴覆盖,保存即可。
- 第五个坑:执行 adb devices -l 命令找不到手机
我的荣耀V20升级了HarmonyOS,为了防止意外,我特地翻出了那根原厂USB线(线皮都破了露出了铜丝),连接到笔记本后,颤抖着手,用管理员权限打开命令行窗口,输入了adb devices -l,然后给我下面的反馈:
网上找了下原因,ADB Interface找不到驱动程序。
通过 右击计算机-->点击 “管理” --> 找到 “设备管理器” --> 找到 “其他设备”:
驱动程序有感叹号,得重新安装驱动程序。双击带黄色感叹号的ADB Interface更新驱动程序,选择Windows自动搜索更新驱动程序软件,结果发现驱动程序无法正常安装。手动选择电脑上的文件安装驱动程序,参考谷歌文档:
安装原始设备制造商 (OEM) USB 驱动程序 | Android 开发者 | Android Developers
我用的是荣耀,只能安装通用的驱动程序。可以使用文档中下载的驱动,也可以选择Android SDK中的驱动。
- 第六个坑:error: device unauthorized
重新拔插换个USB接口试试,如果还不行,看下报错信息,里面有这样一句话:
Try 'adb kill-server' if that seems wrong.
在命令行窗口输入adb kill-server 然后直接 adb devices -l 命令,手机上弹出了授权提示框,点击允许,这个问题就解决了!
这个问题其实很简单,能从错误提示中解决。但是设备未授权的原因确实没找出来,而且不执行adb kill-server,手机上就不会弹出授权的对话框,所以容易浪费时间。
- 第七个坑:来自无线调试的由于目标计算机积极拒绝,无法连接
必须在开发者模式下勾选USB调试,和“仅充电”模式下允许ADB调试。手机有adb网络调试的也可以打开。
无线调试不建议使用,我尝试下来,每次断开后都要重新设置一遍,还不如插上USB线来得快。
- 第八个坑:调试程序时Original error: Could not proxy command to the remote server
Encountered internal error running command: UnknownError: An unknown server-side error occurred while processing the command. Original error: Could not proxy command to the remote server. Original error: timeout of 240000ms exceeded
在手机的设置——应用与服务——应用管理下,卸载掉自动安装的Appium Settings、io.appium.uiautomator2.server、io.appium.uiautomator2.server.test,然后手机关机重启,再次执行就正常了。该情况不会多次出现,一般只会出现一次。
- 第九个坑:resetKeyboard=True
resetKeyboard=True, # 执行完程序恢复原来输入法
从两位自动化测试的前辈那里拿来的代码,注释上写的这段其实并不奏效。在测试完之后,还是需要在设置-高级设置-语言和输入法,然后把默认输入法改成自己常用的那个,这样手机在手动输入时,输入法才能调用出来。
- 第十个坑:appium输出日志
appium -g 日志文件名称.log
我使用下来,这里是可以使用相对路径的。并且这个日志文件,不是使用append的方式写入的,而是每次使用时,都是覆盖上次的日志文件。所以如果需要保留上次的日志,日志文件的名称需要注意保持唯一性。
- 第11个坑:python TypeError: 'module' object is not callable
网上资料说:Python导入模块的方法有两种:import module 和 from module import,区别是前者所有导入的东西使用时需加上模块名的限定,而后者不要。
我给的建议是,无论你是用import module 还是 from module import,都尽量加上模块名限定,这样代码不会报错,但是可读性会高很多。
from tasks.TaskUtils import *
from tasks.TiaoZhanDaTi import *# 不含__init__函数
TaskUtils.get_task_btn(driver, '挑战答题').click()
# 含__init__函数,直接调用
TiaoZhanDaTi(driver, db).da_ti()
python的初始化方法 __init__(self, ...) 就很类似java的构造函数。
- 第12个坑:导入自定义模块
python导入自定义模块,对比java其实就是导入一个类的事情,但在python里面,要复杂得多。我尝试下来,相对最简单,也最灵活的方式,先展示项目目录结构:
+---py_project
| +---utils| +---BasePage.py
| +---tasks
| +---TaskUtils.py
TaskUtils.py需要引入BasePage.py,代码如下:
import sys
from os.path import join, dirname
sys.path.append(join(dirname(__file__), '..'))
from utils.BasePage import *
- 第13个坑:python中的None与NULL
None是一个对象,而NULL是一个类型。
Python中没有NULL,只有None,None有自己的特殊类型NoneType。
None不等于0、任何空字符串、False等。
在Python中,None、False、0、""(空字符串)、[](空列表)、()(空元组)、{}(空字典)都相当于False。判断变量是否为空的高效方法是:
if X is None
if not X:当X为None、False、""、0、[]、()、{}时,not X为真,无法分辨
if not X is None:等价于if not (X is None)、if X is not None
————————————————
版权声明:本文为CSDN博主「小小的刀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:python中的None与NULL_小小的刀的博客-CSDN博客_python的none和null
- 第14个坑:Python 字符串前加f,r,u,b的含义
f表示字符串内支持大括号内的python表达式,如:logger.info(f"Total time taken: {time.time() - start_time}");
r表示去掉反斜杠的转移机制,如:logger.info(r"Test\n\n\n") 表示单纯字符串而不表示换行;
u一般出现在中文字符串前,防止出现乱码;
b表示这是一个bytes类型对象,在网络编程中,服务器和浏览器只认bytes类型数据,如:response=b'<h1>Hello World</h1>'————————————————
版权声明:本文为CSDN博主「小小的刀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:Python 字符串前加f,r,u,b的含义_努力搬砖的刷刷碗的博客-CSDN博客_python字符串前加f
- 第15个坑:swipe滑动操作
我要的元素需要通过屏幕下滑才能找到,然后可能还不止滑一次,swipe其实有点不稳定,勉强够用。截取部分代码如下:
"""
查找任务按钮
"""
def get_task_btn(driver, task):print("准备进行> %s <任务" % task)code = '//android.view.View[@text="' + task + '"]/../../android.view.View[@index=3]'i = 0ele = Nonewhile i < 3:try:ele = driver.find_element(AppiumBy.XPATH, code)except NoSuchElementException:i = i + 1print("当前屏幕未找到 %s 按钮,第 %d 次滑动屏幕" % (task, i))BasePage(driver).swipe_up(0.3)else:print(task + "==>" + ele.text)breakreturn ele
"""获取x轴宽度"""
@property
def x(self):return self.get_window_size['width']"""获取y轴高度"""
@property
def y(self):return self.get_window_size['height']"""
手指向上滑动
scale: 滑动距离所占比例
duration: 滑动从起点到终点坐标所耗费的时间ms
起点: 0.5x, (1+scale)*y/2
终点: 0.5x, (1-scale)*y/2
"""
def swipe_up(self, scale=0.8, duration=800):print('swipe_up')self.driver.swipe(self.x*0.5, self.y*(1+scale)/2, self.x*0.5, self.y*(1-scale)/2, duration)
这种滑动操作可以封装到一个模块就行,参考博客:App自动化测试(五)之swipe滑动操作_DesireYang的博客-CSDN博客
如果一个页面遇到多个滚动窗口,参考这个:Multiple scroll views - Appium
By instance
# first scrollView
# FindElement
MobileElement element = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0))" +".scrollIntoView(new UiSelector().text(\"exact_text\"))"));# second scrollView
# FindElement
MobileElement element = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(1))" +".scrollIntoView(new UiSelector().text(\"exact_text\"))"));
By id
# FindElement
MobileElement element = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().resourceIdMatches(\".*part_id.*\").scrollable(true))" +".scrollIntoView(new UiSelector().text(\"exact_text\"))"));
- 最后一个不算是坑的坑:SQLite3获取新插入的记录ID及ROWID
1. 创建表时,主键要创建为 INTEGER PRIMARY KEY,其实我觉得最好再加上自增 AUTOINCREMENT ,这样最简单最完美。
2. 带有 INTEGER PRIMARY KEY 列的SQLite 数据库表,其 rowid 就是 该INTEGER PRIMARY KEY 列。所以,使用 cursor.lastrowid 得到就是我们的ID值了。
注意:INTEGER PRIMARY KEY 不要写成了 int primary key。大小写无所谓,但是 integer 不要写成了 int,因为 int 不是 sqlite 的基本数据类型。
————————————————
版权声明:本文为CSDN博主「qilei2010」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:【Python】SQLite3获取新插入的记录ID及ROWID探究_qilei2010的博客-CSDN博客_sqlite3 获取自增id
学习appium必备的避坑指南相关推荐
- 项目从0到1避坑指南
背景: 物流行业,老板信息化意识弱,不是现有的TMS而是一个新的方向,目前市场上竞品较少 前言: 一个项目从0到1,有相关的固定的考虑事项.然而,由于公司环境.项目涉及的行业等一些实际条件的约束,会在 ...
- 【C语言避坑指南】学习记录
学习自B站Up双笙子佯谬的视频 [C语言避坑指南]看完这个视频,我再也不害怕指针!_哔哩哔哩_bilibili课件:https://github.com/parallel101/course作业:ht ...
- 新媒体人必备!视频号直播避坑指南
其中,禁言.警告都算是小惩,而封停直播一次流量就清零,被封10年.20年的视频号基本"宣判死刑". 春节即将到来(榜哥榜妹明天开始也要放假啦),在这个重要的营销节点,微信的监管力度 ...
- 17条避坑指南:一份来自谷歌的数据库经验贴
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://medium.com/@rak ...
- Serverless 时代前端避坑指南
作者 | 张挺 每个时代,从来不缺机会. 云原生的浪潮席卷而来,从 14 年到现在,上云的声音就没有停歇过,而如今到了 2020,云厂商都已经准备好了,而前端,是否也准备好踏入这纷争的领域,去拥抱时代 ...
- python避坑指南_Linux下Python3.6的安装及避坑指南
Python3的安装 1.安装依赖环境 Python3在安装的过程中可能会用到各种依赖库,所以在正式安装 Python 3之前,需要将这些依赖库先行安装好. yum -y install zlib-d ...
- ext列表禁止滑动_后台列表设计避坑指南(下)
编辑导语:列表页是后台界面的重要组成之一,上篇说了后台列表设计的"搜索"设计(详情见:后台列表设计避坑指南 上):本篇继续讲剩下的两个部分的"坑"和必坑指南,我 ...
- @程序员,区块链开发平台避坑指南!
来源 | Michiel Mulders 译者 | 火火酱 责编 | Carol 出品 | 区块链大本营(blockchain_camp) 市面上有很多不同的区块链网络,就可扩展性和功能而言,每个区块 ...
- 如何处理不能复现的bug?软件测试工程师避坑指南
软件测试工作中常常会遇到不能复现的bug,遇到这种情况其实很正常,但是很多测试新手都按照自己的想法处理,没有提交bug,或者匆匆关闭bug.线上出现问题,就只能自己背锅了.今天我们就说说,遇到这种情况 ...
最新文章
- mysql read only参数_MySQL 参数解析 tx_read_only transaction_read_only
- Android自定义View全解
- 关于bcache的一些事情
- 除了超分辨率,AI 结合 RTC 还有哪些技术实践?
- 如何选择面向对象语言
- 如何辨别二逼互联网公司!?
- P2920 [USACO08NOV]时间管理Time Management
- centos 5 手动分区来安装系统的方法
- 一步步学习SPD2010--第九章节--使用可重用工作流和工作流表单(13)--修改任务表单...
- python,错误、调试和测试
- java实现小程序订阅消息推送(附源码)
- 软考__运筹学__2007年11月真题
- 测试统计学卡方,t检验,Kappa和Kendall评价
- Apache中文URL中有包含“\x85”字节的汉字时导致的Rewrite失败及404问题
- 如果域名被劫持该怎么办?有什么应对方法?
- [luogu3505][bzoj2088][POI2010]TEL-Teleportation【分层图】
- 【JSTL】choose标签
- 英特尔服务器主板型号,支持英特尔® Server Board S2600JF
- javaScript原生版购物车:全选、单选、全删、商品数量增减、计算总价、添加商品(代码)
- 用友NC单据UI基本代码示例
热门文章
- 基于生命周期的开发方法——螺旋开发方法
- David Silver RL课程笔记(一)
- 原生JS超级马里奥(第一天)
- Java日期格式中的DD和dd的差别
- ICRA2023|基于时空融合的驾驶场景视频雨滴移除算法+数据集
- 升讯威微信营销系统开发实践:订阅号和服务号深入分析( 完整开源于 Github)...
- Fc坦克大战java_FC版BattleCity(坦克大战)的Java实现!!!!!(二) | 学步园
- 笨方法学python3: ex43中文魔改
- [AcWing] 1319.移棋子游戏 博弈论 Sg函数板子题
- 终章:蜕变,破茧成蝶!