首先感谢白月黑羽和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必备的避坑指南相关推荐

  1. 项目从0到1避坑指南

    背景: 物流行业,老板信息化意识弱,不是现有的TMS而是一个新的方向,目前市场上竞品较少 前言: 一个项目从0到1,有相关的固定的考虑事项.然而,由于公司环境.项目涉及的行业等一些实际条件的约束,会在 ...

  2. 【C语言避坑指南】学习记录

    学习自B站Up双笙子佯谬的视频 [C语言避坑指南]看完这个视频,我再也不害怕指针!_哔哩哔哩_bilibili课件:https://github.com/parallel101/course作业:ht ...

  3. 新媒体人必备!视频号直播避坑指南

    其中,禁言.警告都算是小惩,而封停直播一次流量就清零,被封10年.20年的视频号基本"宣判死刑". 春节即将到来(榜哥榜妹明天开始也要放假啦),在这个重要的营销节点,微信的监管力度 ...

  4. 17条避坑指南:一份来自谷歌的数据库经验贴

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://medium.com/@rak ...

  5. Serverless 时代前端避坑指南

    作者 | 张挺 每个时代,从来不缺机会. 云原生的浪潮席卷而来,从 14 年到现在,上云的声音就没有停歇过,而如今到了 2020,云厂商都已经准备好了,而前端,是否也准备好踏入这纷争的领域,去拥抱时代 ...

  6. python避坑指南_Linux下Python3.6的安装及避坑指南

    Python3的安装 1.安装依赖环境 Python3在安装的过程中可能会用到各种依赖库,所以在正式安装 Python 3之前,需要将这些依赖库先行安装好. yum -y install zlib-d ...

  7. ext列表禁止滑动_后台列表设计避坑指南(下)

    编辑导语:列表页是后台界面的重要组成之一,上篇说了后台列表设计的"搜索"设计(详情见:后台列表设计避坑指南 上):本篇继续讲剩下的两个部分的"坑"和必坑指南,我 ...

  8. @程序员,区块链开发平台避坑指南!

    来源 | Michiel Mulders 译者 | 火火酱 责编 | Carol 出品 | 区块链大本营(blockchain_camp) 市面上有很多不同的区块链网络,就可扩展性和功能而言,每个区块 ...

  9. 如何处理不能复现的bug?软件测试工程师避坑指南

    软件测试工作中常常会遇到不能复现的bug,遇到这种情况其实很正常,但是很多测试新手都按照自己的想法处理,没有提交bug,或者匆匆关闭bug.线上出现问题,就只能自己背锅了.今天我们就说说,遇到这种情况 ...

最新文章

  1. mysql read only参数_MySQL 参数解析 tx_read_only transaction_read_only
  2. Android自定义View全解
  3. 关于bcache的一些事情
  4. 除了超分辨率,AI 结合 RTC 还有哪些技术实践?
  5. 如何选择面向对象语言
  6. 如何辨别二逼互联网公司!?
  7. P2920 [USACO08NOV]时间管理Time Management
  8. centos 5 手动分区来安装系统的方法
  9. 一步步学习SPD2010--第九章节--使用可重用工作流和工作流表单(13)--修改任务表单...
  10. python,错误、调试和测试
  11. java实现小程序订阅消息推送(附源码)
  12. 软考__运筹学__2007年11月真题
  13. 测试统计学卡方,t检验,Kappa和Kendall评价
  14. Apache中文URL中有包含“\x85”字节的汉字时导致的Rewrite失败及404问题
  15. 如果域名被劫持该怎么办?有什么应对方法?
  16. [luogu3505][bzoj2088][POI2010]TEL-Teleportation【分层图】
  17. 【JSTL】choose标签
  18. 英特尔服务器主板型号,支持英特尔® Server Board S2600JF
  19. javaScript原生版购物车:全选、单选、全删、商品数量增减、计算总价、添加商品(代码)
  20. 用友NC单据UI基本代码示例

热门文章

  1. 基于生命周期的开发方法——螺旋开发方法
  2. David Silver RL课程笔记(一)
  3. 原生JS超级马里奥(第一天)
  4. Java日期格式中的DD和dd的差别
  5. ICRA2023|基于时空融合的驾驶场景视频雨滴移除算法+数据集
  6. 升讯威微信营销系统开发实践:订阅号和服务号深入分析( 完整开源于 Github)...
  7. Fc坦克大战java_FC版BattleCity(坦克大战)的Java实现!!!!!(二) | 学步园
  8. 笨方法学python3: ex43中文魔改
  9. [AcWing] 1319.移棋子游戏 博弈论 Sg函数板子题
  10. 终章:蜕变,破茧成蝶!