刚才 iOS 版的也测试稳定了,顺便分享艰辛的喜悦。
两周前写过一篇文章关于深度优先的探索性遍历工具的设计和实现,写明了原因。前期调研,这方面的资料不多,感谢 testerhome 的创始人 seveniruby,已经用 scala 开发完成品,还有两篇相关的文章,给我提供了很好的借鉴,没有他前面走过的路,我必定要走很多弯路,也不可能这么快就能做出来。所以,很荣幸能进入 testerhome 这个社区,开拓了的视野。在做的过程中踩了不少坑,以每周少睡 20 多个小时的代价寻求解决方案,今天主要是说一下设计思路和技术细节。
我相信有很多代码能力在我之上的,开源的目的是为了提供参考方案和解决思路,目前只是基础版,还请提出宝贵建议,源码传送门
方案一、把支持的参数都封装成 bean 读取,后来想了想觉得不够灵活,如果以后有弃用或增加的参数还要改代码;
方案二、以键值对的方式存入字典对象,遍历读取,这样就不必担心扩展了。
方案一、用 md5,容易受到各种干扰,特别是窗口位置的细微变化。
方案二、用 activity,普通窗口没问题,带 TAB 页的窗口就无法区分,切换 TAB 页内容不同就不要区分。
方案三、用 xpath 表达式寻求能鉴别窗口唯一性的特征元素,例如:Title。有的 app 对于控件的命名很不规范,导致很难发现共性。
方案四、也就是现在的方案,从窗口头部开始往下取几个节点(可配置),去掉坐标干扰后再生成 md5,这个方案对于窗口鉴别还算稳定。
<!--窗口鉴定策略,默认取前8个节点生成md5-->
<identify-default>8</identify-default>
<!--Tab窗口用selected区别,可能要多选几个节点到达-->
<identify-special>
<define>专题,直播,要闻,选股>>24</define>
<define>简单理财,投资,保险,贷款,信用卡>>30</define>
</identify-special>
有两种场景需要用到:
1.欢迎界面划屏至登录成功
2.app 可能由多个项目组完成,每个项目组负责一个模块,需要引导到指定模块
考虑再三,用简单的关键字驱动方式实现引导
<iosGuideFlow>
<!--滑动类型设置-->
<step>slide>>2</step>
<!--点击类型设置-->
<step>click>>xpath:://UIAApplication[1]/UIAWindow[1]/UIAScrollView[1]/UIAButton[1]</step>
<step>click>>xpath:://UIAApplication[1]/UIAWindow[1]/UIAButton[3]</step>
<!--输入类型设置-->
<step>input>>xpath:://UIAApplication[1]/UIAWindow[1]/UIAScrollView[1]/UIATextField[1]|13012345678</step>
<step>click>>xpath:://UIAApplication[1]/UIAWindow[1]/UIAScrollView[1]/UIAButton[1]</step>
<step>input>>xpath:://UIAApplication[1]/UIAWindow[1]/UIAScrollView[1]/UIASecureTextField[1]|123456</step>
<step>click>>xpath:://UIAApplication[1]/UIAWindow[1]/UIAScrollView[1]/UIAButton[1]</step>
<step>input>>xpath:://UIAApplication[1]/UIAWindow[3]/UIATextField[1]|8888</step>
<step>click>>xpath:://UIAApplication[1]/UIAWindow[3]/UIAButton[2]</step>
<!--手势密码设置-->
<step>gesture>>xpath:://UIAButton[@name='blue circle']</step>
</iosGuideFlow>
这个踩的坑最多,也耗费了我大部分时间。
1.获取可操作元素
a) 预加载:获取窗口后,用类似于这种方法取到当前窗口的所有可执行元素。对于 Android 遍历影响不大,对于 IOS 遍历简直就是灾难,慢的无法接受;
List<WebElement> elementList = ((AppiumDriver) driver).findElements(By.xpath("//*[@clickable='true' and @enabled='true']"));
b) 懒加载:获取窗口后,生成所有可执行元素的 xpath,遍历出栈后再根据 xpath 获取 WebElement。
2.减少无效操作
a) 引入控件白名单机制
名单内的类才会被允许去遍历。UIAStaticText 对 iOS 来说,误杀 1% 可以减少很多不必要的遍历
<!--控件白名单-->
<click>
<class>UIAImage</class>
<class>UIAButton</class>
<class>UIASwitch</class>
<class>UIATableCell</class>
<!--<class>UIAStaticText</class>-->
<class>UIAPickerWheel</class>
<class>UIACollectionCell</class>
</click>
<input>
<class>UIATextField</class>
<class>UIASearchBar</class>
<class>UIASecureTextField</class>
</input>
b) 增加过滤策略
有的窗口会隐藏重复的入口,遍历工具能遍历到,这些过滤掉也能提升效率
以 iOS 为例,设计了 4 种过滤策略,不设置为默认不过滤
<!--1:id+clazz+name 2:id+clazz+name+label 3:id+clazz+name+label+value 4:no filter-->
<filter>1</filter>
c) runtime 黑名单机制,出栈的节点任务会加入黑名单列表,确保不再重复执行
a) 黑名单机制
有些窗口想屏蔽掉,最好的办法是从根源解决,就是屏蔽入口,以 iOS 为例,支持 text,name,label 等属性的模糊匹配,xpath 精确匹配
<!--黑名单-->
<blackList>
<item>相机</item>
<item>相册</item>
<item>照片</item>
<item>退出登录</item>
<item>拍摄名片</item>
<item>credit card camera</item>
<item>如您已完成添加,请重新登录</item>
<item>重新登录</item>
<item>//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIAButton[1]</item>
<item>//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIAButton[2]</item>
<item>//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIAButton[3]</item>
</blackList>
b) 触发器机制
满足 xx 条件,触发 xx 操作。根据遍历中遇到的情况,支持返回、延时、点击、手势密码盘解锁。
<trigger>
<item>分享到>>back</item>
<item>我的权益>>delay->8</item>
<item>温馨提示|立即开通|取消>>//UIAApplication[1]/UIAWindow[4]/UIAButton[1]</item>
<item>更多解锁方式>>gesture->//UIAButton[@name='blue circle']</item>
</trigger>
日志分为系统日志和 APP 日志,系统日志又分为 info 和 error,error 的格式是固定的,便于分析出报告。
关于 APP 日志的设计
最初,如何打印日志,程序内部写死的,灵活性不高;
最终,如何打印日志,用什么工具、用哪些参数,支持用户定制化。
<log>
<ios>idevicesyslog -u #udid#</ios>
<android>adb -s #udid# logcat -v time -b events *:I | grep pingan</android>
</log>
a) 截屏功能
Android 没有用 appium 的方法,直接调用命令比基于请求的效率更高;
iOS 使用 idevicescreenshot,比 appium 截图提高 10 倍效率。
b) 录像功能
把操作过程转化为流媒体,提升用户体验
可定制化 Appium Server 的 port 和 host
可配置遍历深度和遍历时间
可配置截图和视频的目录
<global>
<!--Appium port-->
<port>5757</port>
<!--Appium host-->
<host>127.0.0.1</host>
<!--测试类型 1.android 2.ios 3.web-->
<mode>1</mode>
<!--遍历深度-->
<depth>0</depth>
<!--截图和视频的目录-->
<screenshot>/Users/mac/Desktop/png</screenshot>
<!--遍历时间 分-->
<duration>0</duration>
<!--延时等待 秒-->
<interval>3</interval>
<!--超时 秒-->
<timeout>30</timeout>
</global>
之前测试用的非完整版,水平有限勿喷,主要分为节点任务执行前、执行后的处理,后进先出的结构
/**
* 基于dfs的探索性遍历
*
* @param taskStack
* @param depth
*/
public void dfsSearch(Stack<UiNode> taskStack, int depth) {
int thisDepth, newTaskCount, repeatCount = 0;
UiNode thisNode;
WebElement element;
Stack<UiNode> children;
Stack<UiNode> existsTaskStack;
List<String> triggerList;
List<UiNode> blackList = new ArrayList<>();
String xpath, thisWindow, preWindow, thisPageSource, doBackWin;
// 首次获取窗口内容和窗口标识
thisPageSource = driver.getPageSource();
thisWindow = parser.getCurrentWindowID(thisPageSource);
preWindow = thisWindow;
triggerList = config.getTriggerList();
while (!taskStack.isEmpty()) {
if (repeatCount > config.getAllowSameWinTimes())
break;
thisNode = taskStack.pop();
blackList.add(thisNode);
try {
// 截图
screenShot();
// 触发器预处理
if (triggerProcessing(driver.getPageSource(), triggerList)) {
screenShot();
thisPageSource = driver.getPageSource();
thisWindow = parser.getCurrentWindowID(thisPageSource);
}
if (!thisWindow.equals(thisNode.getWindowID())) {
// 在任务栈中搜索当前窗口,如果存在,则获取该窗口下所有任务节点
existsTaskStack = searchByWindowID(thisWindow, taskStack);
// 如果当前窗口已存在任务栈中
if (null != existsTaskStack) {
repeatCount = 0;
resetTaskStack(taskStack, existsTaskStack);
} else {
Log.logInfo(thisNode.getWindowID() + " >> " + thisWindow + ", 窗口迁移至新窗口......");
if (preWindow.equals(thisWindow)) {
repeatCount = repeatCount + 1;
} else {
repeatCount = 0;
}
preWindow = thisWindow;
thisDepth = thisNode.getDepth();
// 遍历深度控制,0表示未限制
if (depth == 0 || thisDepth < depth) {
thisPageSource = driver.getPageSource();
thisWindow = parser.getCurrentWindowID(thisPageSource);
children = getTaskStack(Type.XML, thisPageSource, thisNode.getDepth() + 1);
// 是否获取到新窗口节点任务
newTaskCount = null != children ? children.size() : 0;
Log.logInfo(newTaskCount + "个新任务准备入栈......");
children = removeNodes(blackList, children);
children = filterNodes(taskStack, children);
children = updateTaskStack(children, thisNode);
// 如果有新的节点任务生成,把当前节点任务先压栈,新生成的节点任务出栈
if (null != children && children.size() > 0) {
Log.logInfo(children.size() + "个新任务允许入栈......");
taskStack.push(thisNode);
taskStack.addAll(children);
// 更新任务栈后,新任务出栈
thisNode = taskStack.pop();
blackList.add(thisNode);
}
if (newTaskCount == 0 || children.size() == 0 && needBack(thisWindow, taskStack)) {
doBack();
}
} else {
doBack();
}
}
}
// 每次迭代懒加载元素对象
xpath = thisNode.getId().split("-")[3];
element = driver.findElement(By.xpath(xpath));
if (thisNode.getAction().equals(Action.CLICK)) {
element.click();
} else if (thisNode.getAction().equals(Action.INPUT)) {
// todo something
}
// 任务执行后获取窗口内容和窗口标识
TimeUnit.SECONDS.sleep(config.getInterval());
thisPageSource = driver.getPageSource();
thisWindow = parser.getCurrentWindowID(thisPageSource);
// 如果同窗口的任务栈已处理完毕,并且还停留在该窗口,返回至上一个窗口
if (thisNode.getWindowID().equals(thisWindow) && needBack(thisNode.getWindowID(), taskStack)) {
// 获取返回后的窗口内容和窗口标识
doBackWin = doBack();
thisPageSource = null == doBackWin ? thisPageSource : doBackWin;
thisWindow = parser.getCurrentWindowID(thisPageSource);
}
} catch (NoSuchElementException e) {
continue;
} catch (org.openqa.selenium.ElementNotVisibleException e) {
continue;
} catch (org.openqa.selenium.NoSuchSessionException e) {
break;
} catch (org.openqa.selenium.SessionNotCreatedException e) {
break;
} catch (org.openqa.selenium.NotFoundException e) {
continue;
} catch (Exception e) {
continue;
}
}
}
转载请注明作者和出处
通过遍历元素对比两个版本的 ui 差异性,是否可以在源码层去做呢?毕竟 git svn 都带各个版本的 diff,拿到 diff 根据变更文件,指定变更文件扫描
—— 来自 TesterHome 官方 安卓客户端
IOS 如果控件没有 label,怎么识别控件的唯一性?@quqing 我邮箱给你了,想和你私聊一下
#3 楼 @qiangf1213 现在不能访问外网的邮箱,晚上
给你加精了, 之所以鼓励你重写. 是因为大多数人估计都学不会 scala. 行业需要一个 java 的产品.
#8 楼 @seveniruby 现在的痛点是 ios 的截图慢,大一点的要 5 秒以上
#10 楼 @seveniruby idevicescreenshot 用这个截图杠杠的 平均 300~400ms
我倒是对 scala 版本感兴趣,然后看了一下https://github.com/seveniruby?tab=repositories
里面并没有
看完你的帖子有几个问题请教下:
1、我的理解主要是 crash 监测,比 monkey 更有效,但看你说的为 APP 性能测试服务,莫非是埋点收集性能数据?
2、看了下你的核心算法,想确认下:resetTaskStack(taskStack, existsTaskStack);是将栈做更新,确保 existsTaskStack 中数据先出么?
问题有点多,非常感谢
请问楼主,有开源吗?
请教一下遍历是只针对 GET 的操作么,如果涉及到一些表单提交等问题,是如何应对呢?
这两天也学了 Appium,也实现了一个简易的 Demo,代码 100 多行,没有楼主的这么系统
#24 楼 @afdsghjk 可以给你参考下,写得比较简单,一般有基础的都能看懂
https://github.com/quqing0930/AutoTraveler
ERROR running Appium command: Cannot read property 'curDeviceId' of null 这种情况怎么处理呢
xpath 识别有点问题
info: [debug] [BOOTSTRAP] [debug] Got data from client: {"cmd":"action","action":"find","params":{"strategy":"xpath","selector":"//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.ImageButton[2]","context":"","multiple":false}}
info: [debug] [BOOTSTRAP] [debug] Got command of type ACTION
info: [debug] [BOOTSTRAP] [debug] Got command action: find
info: [debug] [BOOTSTRAP] [debug] Finding //android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.ImageButton[2] using XPATH with the contextId: multiple: false
info: [debug] [BOOTSTRAP] [debug] Returning result: {"status":7,"value":"Could not find an element using supplied strategy. "}
现在的设计是遍历完毕后卸载 app,这是内部需求,后续会加开关进行控制
你按 ReadMe 里面的说明把环境配好了吗?你的报错是 Appium 报的,应该是环境问题
你好,请问怎么处理登录问题,我遍历测试很多 app
的时候都会遇到需要登录的情况
深度遍历怎么保证回溯就能回到父节点,比如有些 button 点完之后只是切换 Tag 选项
#38 楼 @cryingdream94 基于深度,先进后出
@quqing hiahia~想通了,是深度。我之前也写过自动遍历工具,原打算采用 DFS 遍历,但是回溯存在一种情况回不到父节点而到了爷爷节点。
#40 楼 @cryingdream94 用任务栈重置应该可以解决
@quqing 任务栈发生重置的情况有哪些呢?
#42 楼 @cryingdream94 当前窗口和当前出栈的任务节点不一致
值得收藏
值得学习
为什么我把程序打 jar 包的时候提示我
jar 打不成功
#46 楼 @304764691 问题描述清楚才能解答啊
appium 小白,对这个项目挺感兴趣的,试用了一下来遍历知乎 app。
程序不能遍历整个 app 的所有页面,日志出现 NoSuchElementException 异常,看 app 的操作像是因为页面没有后退到前一个窗口,所以无法找到元素,之后就异常退出了。
想请教一下@quqing:能帮忙看下是什么原因?是不是配置文件没有正确配置导致的?
log 输出如下:
2016-07-04 10:27:55 sys_log : [INFO] ########################################################################
2016-07-04 10:28:02 sys_log : [INFO] 遍历测试持续时间 -> 30.01s
2016-07-04 10:28:12 sys_log : [INFO] 遍历测试持续时间 -> 40.01s
2016-07-04 10:28:17 sys_log : [INFO] click -> com.zhihu.android:id/login_btn
2016-07-04 10:28:21 sys_log : [INFO] input -> com.zhihu.android:id/username, sendKeys ->xxxxxx@qq.com
2016-07-04 10:28:22 sys_log : [INFO] 遍历测试持续时间 -> 50.02s
2016-07-04 10:28:32 sys_log : [INFO] 遍历测试持续时间 -> 1.00m
2016-07-04 10:28:33 sys_log : [INFO] input -> com.zhihu.android:id/password, sendKeys -> xxxxxx
2016-07-04 10:28:42 sys_log : [INFO] click -> com.zhihu.android:id/btn_progress
2016-07-04 10:28:42 sys_log : [INFO] 遍历测试持续时间 -> 1.17m
2016-07-04 10:28:50 sys_log : [INFO] ########################### 开始执行探索性遍历测试 ###########################
2016-07-04 10:28:50 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有6个任务待运行, [android.widget.ImageButton,,,], 43caaf86fb1026d4d4072053d7468557-0,50-112,162-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[3]/android.widget.ImageButton[1]
2016-07-04 10:28:51 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:28:51 sys_log : [INFO] [android.widget.ImageButton,,,], 43caaf86fb1026d4d4072053d7468557 >> 开始执行节点任务......
2016-07-04 10:28:51 sys_log : [INFO] click -> [info = android.widget.ImageButton,,,], [depth = 1]43caaf86fb1026d4d4072053d7468557-0,50-112,162-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[3]/android.widget.ImageButton[1]
2016-07-04 10:28:52 sys_log : [INFO] 遍历测试持续时间 -> 1.33m
2016-07-04 10:28:54 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有5个任务待运行, [android.widget.TextView,,搜索,com.zhihu.android:id/action_search], 43caaf86fb1026d4d4072053d7468557-576,58-672,154-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[3]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.TextView[1]
2016-07-04 10:28:55 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:28:55 sys_log : [INFO] [android.widget.TextView,,搜索,com.zhihu.android:id/action_search], 43caaf86fb1026d4d4072053d7468557 >> 开始执行节点任务......
2016-07-04 10:28:55 sys_log : [INFO] click -> [info = android.widget.TextView,,搜索,com.zhihu.android:id/action_search], [depth = 1]43caaf86fb1026d4d4072053d7468557-576,58-672,154-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[3]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.TextView[1]
2016-07-04 10:29:01 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有4个任务待运行, [android.widget.TextView,,通知,com.zhihu.android:id/action_notification], 43caaf86fb1026d4d4072053d7468557-672,58-768,154-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[3]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.TextView[2]
2016-07-04 10:29:02 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:29:02 sys_log : [INFO] [android.widget.TextView,,通知,com.zhihu.android:id/action_notification], 43caaf86fb1026d4d4072053d7468557 >> 开始执行节点任务......
2016-07-04 10:29:02 sys_log : [INFO] click -> [info = android.widget.TextView,,通知,com.zhihu.android:id/action_notification], [depth = 1]43caaf86fb1026d4d4072053d7468557-672,58-768,154-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[3]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.TextView[2]
2016-07-04 10:29:02 sys_log : [INFO] 遍历测试持续时间 -> 1.50m
2016-07-04 10:29:05 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有3个任务待运行, [android.widget.FrameLayout,,,com.zhihu.android:id/fragment_paging_layout], 43caaf86fb1026d4d4072053d7468557-0,162-768,1184-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]
2016-07-04 10:29:06 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:29:06 sys_log : [INFO] [android.widget.FrameLayout,,,com.zhihu.android:id/fragment_paging_layout], 43caaf86fb1026d4d4072053d7468557 >> 开始执行节点任务......
2016-07-04 10:29:06 sys_log : [INFO] click -> [info = android.widget.FrameLayout,,,com.zhihu.android:id/fragment_paging_layout], [depth = 1]43caaf86fb1026d4d4072053d7468557-0,162-768,1184-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]
2016-07-04 10:29:12 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有2个任务待运行, [android.widget.ImageButton,,,], 43caaf86fb1026d4d4072053d7468557-608,1020-752,1180-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.View[1]/android.widget.ImageButton[1]
2016-07-04 10:29:12 sys_log : [INFO] 遍历测试持续时间 -> 1.67m
2016-07-04 10:29:13 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> false
2016-07-04 10:29:13 sys_log : [INFO] 43caaf86fb1026d4d4072053d7468557 >> b53af60e24e148535cfda9304fa975e4, 窗口迁移至新窗口......
2016-07-04 10:29:13 sys_log : [INFO] 相同窗口执行次数 -> 0
2016-07-04 10:29:13 sys_log : [INFO] 6个新任务准备入栈......
2016-07-04 10:29:13 sys_log : [INFO] 6个新任务允许入栈......
2016-07-04 10:29:13 sys_log : [INFO] 任务栈已更新, 6个新任务允许入栈, 现在还有9个任务待运行......
2016-07-04 10:29:13 sys_log : [INFO] 任务栈已更新,现在还有8个任务待运行......
2016-07-04 10:29:13 sys_log : [INFO] [android.widget.FrameLayout,,,com.zhihu.android:id/fragment_paging_layout], b53af60e24e148535cfda9304fa975e4 >> 开始执行节点任务......
2016-07-04 10:29:13 sys_log : [INFO] click -> [info = android.widget.FrameLayout,,,com.zhihu.android:id/fragment_paging_layout], [depth = 2]b53af60e24e148535cfda9304fa975e4-0,0-768,1184-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]
2016-07-04 10:29:17 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有7个任务待运行, [android.widget.ImageView,,,com.zhihu.android:id/avatar], b53af60e24e148535cfda9304fa975e4-48,536-128,616-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.View[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.ImageView[1]
2016-07-04 10:29:18 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:29:18 sys_log : [INFO] [android.widget.ImageView,,,com.zhihu.android:id/avatar], b53af60e24e148535cfda9304fa975e4 >> 开始执行节点任务......
2016-07-04 10:29:22 sys_log : [INFO] 遍历测试持续时间 -> 1.83m
2016-07-04 10:29:32 sys_log : [INFO] 遍历测试持续时间 -> 2.00m
2016-07-04 10:29:42 sys_log : [INFO] 遍历测试持续时间 -> 2.17m
2016-07-04 10:29:48 sys_log : [ERROR] 节点任务 -> [info = android.widget.ImageView,,,com.zhihu.android:id/avatar], NoSuchElementException, 弹出下一个节点任务, b53af60e24e148535cfda9304fa975e4-48,536-128,616-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.View[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.ImageView[1]
2016-07-04 10:29:48 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有6个任务待运行, [android.widget.LinearLayout,,,], b53af60e24e148535cfda9304fa975e4-32,1096-160,1160-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]
2016-07-04 10:29:49 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:29:49 sys_log : [INFO] [android.widget.LinearLayout,,,], b53af60e24e148535cfda9304fa975e4 >> 开始执行节点任务......
2016-07-04 10:29:52 sys_log : [INFO] 遍历测试持续时间 -> 2.33m
2016-07-04 10:30:02 sys_log : [INFO] 遍历测试持续时间 -> 2.50m
2016-07-04 10:30:12 sys_log : [INFO] 遍历测试持续时间 -> 2.67m
2016-07-04 10:30:19 sys_log : [ERROR] 节点任务 -> [info = android.widget.LinearLayout,,,], NoSuchElementException, 弹出下一个节点任务, b53af60e24e148535cfda9304fa975e4-32,1096-160,1160-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]
2016-07-04 10:30:19 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有5个任务待运行, [android.widget.ImageButton,,,], b53af60e24e148535cfda9304fa975e4-0,50-112,162-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[2]/android.widget.ImageButton[1]
2016-07-04 10:30:20 sys_log : [INFO] 当前节点任务所属窗口是否就是当前窗口 -> true
2016-07-04 10:30:20 sys_log : [INFO] [android.widget.ImageButton,,,], b53af60e24e148535cfda9304fa975e4 >> 开始执行节点任务......
2016-07-04 10:30:22 sys_log : [INFO] 遍历测试持续时间 -> 2.83m
2016-07-04 10:30:32 sys_log : [INFO] 遍历测试持续时间 -> 3.00m
2016-07-04 10:30:37 sys_log : [INFO] 开始统计异常信息...
Exception in thread "Timer-0" java.lang.ArrayIndexOutOfBoundsException: 0
at pers.quq.filedb.tool.BytesEncodingDetect.utf16_probability(EncodingDetect.java:688)
at pers.quq.filedb.tool.BytesEncodingDetect.detectEncoding(EncodingDetect.java:98)
at pers.quq.filedb.tool.BytesEncodingDetect.detectEncoding(EncodingDetect.java:80)
at pers.quq.filedb.tool.EncodingDetect.getJavaEncode(EncodingDetect.java:13)
at pers.quq.filedb.core.FileFilterImpl.grep(FileFilterImpl.java:34)
at pers.traveler.robot.AndroidRobot.catchAppException(AndroidRobot.java:40)
at pers.traveler.robot.Robot.afterTravel(Robot.java:235)
at pers.traveler.robot.Robot$1.run(Robot.java:140)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
2016-07-04 10:30:50 sys_log : [ERROR] 节点任务 -> [info = android.widget.ImageButton,,,], 发生未知异常, 弹出下一个节点任务, b53af60e24e148535cfda9304fa975e4-0,50-112,162-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[2]/android.widget.ImageButton[1]
2016-07-04 10:30:51 sys_log : [ERROR] org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 30.27 seconds
Build info: version: '2.53.0', revision: '35ae25b', time: '2016-03-15 16:57:40'
System info: host: 'MACPROmatoMac-Pro.local', ip: '192.168.0.2', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.5', java.version: '1.8.0_65'
Driver info: io.appium.java_client.android.AndroidDriver
Capabilities [{app=/Volumes/lee-soft/mac_yang_slave/test_ws/testAppium/apps/zhihu.apk, appPackage=com.zhihu.android, networkConnectionEnabled=true, noReset=false, noSign=false, warnings={}, appiumVersion=1.0, language=zh-Hans, databaseEnabled=false, deviceName=192.168.56.101:5555, platform=LINUX, appActivity=.app.ui.activity.MainActivity, desired={app=/Volumes/lee-soft/mac_yang_slave/test_ws/testAppium/apps/zhihu.apk, appPackage=com.zhihu.android, noReset=false, noSign=false, appiumVersion=1.0, language=zh-Hans, deviceName=Mi4, appActivity=.app.ui.activity.MainActivity, autoLaunch=true, platformVersion=4.3, unicodeKeyboard=true, udid=192.168.56.101:5555, platformName=Android, resetKeyboard=true}, autoLaunch=true, platformVersion=5.1, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, unicodeKeyboard=true, udid=192.168.56.101:5555, platformName=Android, resetKeyboard=true}]
*** Element info: {Using=xpath, value=//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[2]/android.widget.ImageButton[1]}
2016-07-04 10:30:51 sys_log : [INFO] 报告主人,有1个节点任务出栈并加入黑名单 -> 现在还有4个任务待运行, [android.widget.TextView,,分享,com.zhihu.android:id/action_share], b53af60e24e148535cfda9304fa975e4-592,58-688,154-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[2]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.TextView[1]
2016-07-04 10:30:51 sys_log : [ERROR] 会话丢失,退出 >> 节点任务 -> [info = android.widget.TextView,,分享,com.zhihu.android:id/action_share], NoSuchSessionException, 弹出下一个节点任务, b53af60e24e148535cfda9304fa975e4-592,58-688,154-//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.widget.DrawerLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.view.View[1]/android.view.View[2]/android.support.v7.widget.LinearLayoutCompat[1]/android.widget.TextView[1]
Exception in thread "main" org.openqa.selenium.remote.SessionNotFoundException: Session ID is null. Using WebDriver after calling quit()?
2016-07-04 10:30:54 sys_log : [INFO] 开始创建视频......
Build info: version: '2.53.0', revision: '35ae25b', time: '2016-03-15 16:57:40'
2016-07-04 10:30:54 sys_log : [INFO] 创建视频完毕!
System info: host: 'MACPROmatoMac-Pro.local', ip: '192.168.0.2', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.5', java.version: '1.8.0_65'
Driver info: driver.version: AppiumDriver
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:134)
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:64)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:644)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:43)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:216)
at io.appium.java_client.AppiumDriver.closeApp(AppiumDriver.java:264)
at pers.traveler.robot.Robot.afterTravel(Robot.java:229)
at pers.traveler.robot.AndroidRobot.working(AndroidRobot.java:88)
at pers.traveler.robot.Robot.working(Robot.java:146)
at pers.traveler.robot.Robot.travel(Robot.java:190)
at pers.traveler.test.Main.main(Main.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Process finished with exit code 1
#48 楼 @jennyyung 看日志应该是配置了遍历时间是 3 分钟,时间到会结束,另:appium session 也丢失了,session 丢失我也会做退出处理。
具体原因还要看你的配置文件
好的,感谢@quqing回复,我的配置文件是这样的:
<config>
<!--Appium 服务关键字-->
<capability>
<appiumVersion>1.0</appiumVersion>
<autoLaunch>true</autoLaunch>
<noReset>false</noReset>
<language>zh-Hans</language>
</capability>
<androidCapability>
<app>/Volumes/jenny-soft/mac_yang_slave/test_ws/testAppium/apps/zhihu.apk</app>
<udid>192.168.56.101:5555</udid>
<platformName>Android</platformName>
<platformVersion>4.3</platformVersion>
<deviceName>Mi4</deviceName>
<appPackage>com.zhihu.android</appPackage>
<appActivity>.app.ui.activity.MainActivity</appActivity>
<unicodeKeyboard>true</unicodeKeyboard>
<resetKeyboard>true</resetKeyboard>
<noSign>false</noSign>
</androidCapability>
<!--引导流 关键字驱动,引导至所需模块再开始遍历-->
<androidGuideFlow>
<!--滑动类型设置-->
<step>slide>>2</step>
<!--点击类型设置-->
<step>click>>id::com.zhihu.android:id/login_btn</step>
<!--输入类型设置-->
<step>input>>id::com.zhihu.android:id/username|xxxxxx@qq.com</step>
<step>input>>id::com.zhihu.android:id/password|xxxxxx</step>
<step>click>>id::com.zhihu.android:id/btn_progress</step>
</androidGuideFlow>
<rule>
<!--窗口鉴定策略,默认取前8个节点生成md5-->
<identify-default>8</identify-default>
<!--Tab窗口用selected区别,可能要多选几个节点到达-->
<identify-special>
<define>首页,搜索,通知>>16</define>
</identify-special>
<!--窗口执行顺序 1:从上到下(默认) 2:从下到上-->
<reverse>1</reverse>
<!--控件白名单-->
<click>
<class>android.widget.Button</class>
<class>android.widget.ImageButton</class>
<class>android.widget.TextView</class>
<class>android.widget.ImageView</class>
<class>android.widget.FrameLayout</class>
<class>android.widget.LinearLayout</class>
</click>
<input>
<class>android.widget.EditText</class>
</input>
<!--启动界面提示框,包含的关键字及操作的控件,针对Android-->
<tips>取消>>//android.widget.Button[@resource-id='android:id/button3']</tips>
<!--无需返回的列表,需配置识别窗口唯一性的内容-->
<notback>
<item>首页</item>
</notback>
<!--黑名单 支持text,name,resourceId的过滤-->
<blackList>
<item>相机</item>
</blackList>
<!--触发器 条件>>动作 支持返回,点击,手势密码解锁,延时等待-->
<!--过滤级别 1:clazz+text+content_desc+resourceId 2:winID+clazz+text+content_desc+resourceId 3:taskID-->
<filter>2</filter>
<!--退出遍历的条件:同一窗口内的停留次数-->
<allowSameWinTimes>10</allowSameWinTimes>
</rule>
<!--app日志-->
<log>
<android>adb -s #udid# logcat -b main -b system -b events -b radio *:D | grep pingan</android>
</log>
<global>
<!--Appium port-->
<port>4723</port>
<!--Appium host-->
<host>127.0.0.1</host>
<!--测试类型 1.android 2.ios 3.web-->
<mode>1</mode>
<!--遍历深度-->
<depth>8</depth>
<!--截图和视频的目录-->
<screenshot>/Volumes/jenny-soft/zhihu/pic_output</screenshot>
<!--遍历时间 分-->
<duration>3</duration>
<!--延时等待 秒-->
<interval>3</interval>
<!--超时 秒-->
<timeout>30</timeout>
</global>
</config>
#50 楼 @jennyyung 遍历时间 0 是不限制
<!--遍历时间 分-->
0
@quqing 修改了遍历时间终于跑起来了,但一旦遇到弹层提示框就无法处理直接退出了,这个已经有解决方案了吗?
#52 楼 @jennyyung 触发器、黑名单都可以,建议用触发器,满足 xx 条件,触发 xx 动作
xiong$ java -jar AutoTraveler.jar ios confige/ios.xml
Exception in thread "main" java.lang.NoClassDefFoundError: org/jim2mov/core/MovieSaveException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at pers.traveler.robot.RobotFactory.build(RobotFactory.java:13)
at pers.traveler.test.Main.main(Main.java:23)
Caused by: java.lang.ClassNotFoundException: org.jim2mov.core.MovieSaveException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 4 more
这个是我环境没配好吗
#55 楼 @304764691 类没找到,这个 jar 包有点老了,最近更新过源码,git 源码试试吧
#56 楼 @quqing xiong$ java -jar AutoTraveler.jar ios config/ios.xml
Exception in thread "main" java.lang.NoClassDefFoundError: pers/quq/filedb/core/Filter
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at pers.traveler.robot.RobotFactory.build(RobotFactory.java:13)
at pers.traveler.test.TravelerTest.main(TravelerTest.java:16)
Caused by: java.lang.ClassNotFoundException: pers.quq.filedb.core.Filter
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 4 more
我更新了还是一样 是不是我打包打的有问题啊
#57 楼 @304764691 filedb 是我写的一个插件,都放里面了,应该是打包问题
#59 楼 @304764691 你应该是 IDE 没用好,这几个问题都是 jar 包没引入导致的,这个没法手把手教,google 吧
这遍历太耗能了
—— 来自 TesterHome 官方 安卓客户端
赞
—— 来自 TesterHome 官方 安卓客户端
@quqing 通过 eclipse 和 gradle 以及 jar 命令,打出来的 jar 文件都不能使用。
求提供一个可用的 jar 文件试用。谢谢
其他朋友要是有的话,也感谢提供。
执行:java -jar AutoTraveler.jar ios confige/ios.xml
terminal 显示:AutoTraveler.jar 中没有主清单属性
@jennyyung 刚试用了下你的配置遍历知乎,出现了个问题是页面跳转后,当前节点任务所属窗口还是当前窗口,窗口没更新导致无法运行下去。
现在发现一个问题,提个 issue,
应该把 xml 里面的&# 过滤掉
有些 app 里面不可避免有 emoji。emoji 正则表达式包含了这样的&# 非法字符,需要过滤
这得要多少信息量啊
#65 楼 @zengjunzhou 这边没遇到过这种问题,是不是堆栈中有很多无效节点造成的呢,配置文件有默认值处理的逻辑
<!--退出遍历的条件:同一窗口内的停留次数-->
10
@quqing 经调试,是默认的窗口鉴定策略没配置好,没有使用 identify-special, 使用 identify-default,原配置对比的值 8 太小,很多页面前 8 个元素都相同导致窗口 id 返回值相同,最后索性传了整个 driver.getPageSource() 进去 md5 加密得以解决。遇到新的问是遍历过程中出现退回到桌面的情况。
#70 楼 @zengjunzhou 这个配置里面对不需要返回的窗口有规则支持(窗口内容对规则内所有的关键字都包含才会命中),
首页,财经快讯,我,我的资产,财富加速,财富排名,健康,房产
首页,财经快讯,我,我的订单,活期,定期
首页,财经快讯,我,直播,要闻,专题,选股
首页,财经快讯,我,账户余额,银行卡,订单中心,我的信用
@quqing,开始设置遍历深度 3 出现退回桌面情况,加大遍历深度后遍历效果有所改善,目前还没出现过返回桌面情况。建议加个包名判断,如果包名变化,新界面的节点不入任务栈并返回。
m
—— 来自 TesterHome 官方 安卓客户端
楼主请问 idevicescreenshot 这是怎么用的,我有项目用 appium 截图性能太差了,有没有源码参考一下,感谢!
Exception in thread "main" java.lang.UnsupportedClassVersionError: pers/quq/filedb/core/Filter : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at pers.traveler.robot.RobotFactory.build(RobotFactory.java:13)
at pers.traveler.test.TravelerTest.main(TravelerTest.java:16)
我在 github 上拿到源码,一直在看,还没有跑成功,报错如上
Windows7
android 6.0
测试 Apk zhihu
请教一下,我没找到 pers/quq/filedb/core/Filter 这个在哪
新手一个,请问 clone 下来用什么 ide? 我用的 eclipse 不行啊?
#92 楼 @oo0vini0oo intelliJ idea
运行会出现以及回到 Home 了还会继续执行的情况(测试环境 Windows)
#94 楼 @adfghzhang 不是回到 Home 就会结束,如果 Home 的节点没遍历完,会继续执行
#90 楼 @quqing 确实 JDK1.8 上是可以奔跑的!赞!
还遇到一个问题,影响性能不知如何破解,UiNode 存储 Id 包含 xpath,之后 pop 出来会根据 xpath 在当前页面进行懒加载,
element 获取不到,抛出 NoSuchElementException,从开始找到抛异常间隔时间太长了,这个时间能否缩短。
Appium Server 端 log 如下
info: [debug] [BOOTSTRAP] [debug] Got data from client: {"cmd":"action","action"
:"find","params":{"strategy":"xpath","selector":"//android.widget.FrameLayout[1]
/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.LinearLa
yout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.wid
get.LinearLayout[2]/android.widget.FrameLayout[1]/android.widget.ListView[1]/and
roid.widget.LinearLayout[1]/android.widget.LinearLayout[2]/android.widget.Linear
Layout[4]","context":"","multiple":false}}
info: [debug] [BOOTSTRAP] [debug] Got command of type ACTION
info: [debug] [BOOTSTRAP] [debug] Got command action: find
info: [debug] [BOOTSTRAP] [debug] Finding //android.widget.FrameLayout[1]/androi
d.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]
/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.Lin
earLayout[2]/android.widget.FrameLayout[1]/android.widget.ListView[1]/android.wi
dget.LinearLayout[1]/android.widget.LinearLayout[2]/android.widget.LinearLayout[
4] using XPATH with the contextId: multiple: false
info: [debug] [BOOTSTRAP] [debug] Returning result: {"status":7,"value":"Could n
ot find an element using supplied strategy. "}
@quqing 关于 android 的深度遍历,getPageSource 是获取不到页面不可见部分的元素吧,比如 ListView 需要下拉才会显示的部分。看到 github 上的代码 iOS 和 Android 公用一个 dfsSearch,最新的代码有这方面的改进吗?
AutoTraveler.jar 可以在哪里下载
学习了 感谢了楼主
谢谢分享。这种思路是很赞的。
@quqing 我的配置:
<?xml version="1.0" encoding="UTF-8"?>
<!--Appium 服务关键字-->
1.0
true
false
zh-Hans
E:/nddoc/soft/commomsoft/activity.apk
1115fb8502812b05
Android
18
1115fb8502812b05
com.nd.sdp.component.debug
com.nd.smartcan.appfactory.demo.SplashActivity
true
true
1200
true
<!--引导流 关键字驱动,引导至所需模块再开始遍历-->
<!--输入类型设置-->
click>>id::com.nd.sdp.component.debug:id/login_account
input>>id::com.nd.sdp.component.debug:id/login_account|421490@ndtest
input>>id::com.nd.sdp.component.debug:id/etPsw|123456
click>>id::com.nd.sdp.component.debug:id/btn_login
<!--窗口鉴定策略,默认取前 8 个节点生成 md5-->
8
<!--Tab 窗口用 selected 区别,可能要多选几个节点到达-->
设置,我,活动>>24
<!--窗口执行顺序 1:从上到下 (默认) 2:从下到上-->
1
<!--控件白名单-->
android.widget.Button
android.widget.ImageButton
android.widget.TextView
android.widget.ImageView
android.widget.FrameLayout
android.widget.LinearLayout
UIATextField
UIASearchBar
UIASecureTextField
android.widget.EditText
<!--启动界面提示框,包含的关键字及操作的控件-->
<!-- 禁止 | 允许>>//android.widget.Button[@resource-id='com.huawei.systemmanager:id/btn_allow']-->
<!--无需返回的列表,需配置识别窗口唯一性的内容-->
设置
<!--黑名单 支持 text,name,resourceId 的过滤-->
相机
退出登录
<!--触发器 条件>>动作 支持返回,点击,手势密码解锁,延时等待-->
<!--过滤级别 1:clazz+text+content_desc+resourceId 2:winID+clazz+text+content_desc+resourceId 3:taskID-->
2
<!--退出遍历的条件:同一窗口内的停留次数-->
10
<!--app 日志-->
adb -s #udid# logcat -b main -b system -b events -b radio *:D | grep xxx
<!--Appium port-->
5757
<!--Appium host-->
127.0.0.1
<!--测试类型 1.android 2.ios 3.web-->
1
<!--运行模式 1.遍历模式 2.业务场景模式-->
1
<!--遍历深度-->
3
<!--截图和视频的目录-->
F:\ndtest\traveler\log
<!--启动 appium-->
D:/Program Files (x86)/Appium/node.exe D:/Program Files (x86)/Appium/node_modules/appium/bin/appium.js -p #port# -bp 5760 --session-override --command-timeout 7200 --udid #udid#
<!--遍历时间 分-->
3
<!--延时等待 秒-->
4
<!--超时 秒-->
30
跑不起来,public void dfsSearch(Stack taskStack, int depth) taskStack.size 一直为 0;麻烦帮我看下 ~
#115 楼 @huangejuan appium 启动命令没有替换掉 port 和 udid,遍历时间只有 3 分钟,建议延长
@quqing 启动,udid 替换了呀,port 也替换成我本机的了
#115 楼 @huangejuan 你是 windows 上跑?我只在 mac 上测试过,windows 上跑可能需要自己修改
@quqing 是的,我在 window 上跑的!
<!--窗口鉴定策略,默认取前 8 个节点生成 md5-->
8
<!--Tab 窗口用 selected 区别,可能要多选几个节点到达-->
设置,我,活动>>24
这个的配置是指页面上 tab 切换吗
@quqing 创建视频报这样的异常
javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.BasicMux$BasicMuxDataSource@2793b2a5
at pers.traveler.review.core.Jim2Mov.saveMovie(Jim2Mov.java:148)
at pers.traveler.review.PicToAvi.convertPicToAvi(PicToAvi.java:64)
at pers.traveler.robot.Robot.afterTravel(Robot.java:255)
at pers.traveler.robot.Robot$1.run(Robot.java:165)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Caused by: javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.BasicMux$BasicMuxDataSource@2793b2a5
at javax.media.Manager.createDataSink(Manager.java:1894)
at pers.traveler.review.sun.ImagesToMovie.createDataSink(ImagesToMovie.java:177)
at pers.traveler.review.sun.ImagesToMovie.saveMovie(ImagesToMovie.java:115)
at pers.traveler.review.core.Jim2Mov.saveMovie(Jim2Mov.java:144)
... 5 more
是怎么解决呢?
Exception in thread "main" java.lang.NoClassDefFoundError: org/openqa/selenium/C
apabilities
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at pers.traveler.robot.RobotFactory.build(RobotFactory.java:13)
at pers.traveler.test.Main.main(Main.java:20)
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.Capabilities
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 4 more
報這樣的錯,請問是什麼原因呢?java 是 1.8
#120 楼 @huangejuan 我这边没法重现,从 2 个方面排查
1.配置文件项发给我看看:例如:/Users/mac/Desktop/png
2.装个暴风影音试试,看看是不是编码问题
@quqing F:\ndtest\traveler\log这个是我的配置,正常编码是什么呢 ?
到这一步异常,ImagesToMovie 类中 dsink = createDataSink(p, outML) ,outML 是有值的
#121 楼 @l84222780 用源码跑的还是 jar 包跑的?看错误应该是参数错误导致工厂反射到具体 robot 的时候出的问题
java -jar jar 包名 ios/android 配置文件路径
#123 楼 @huangejuan 改成这样试试F:\\ndtest\\traveler\\log,另外装个暴风影音再试试
@quqing 不行,还是报这样的异常,暴风影音也装了
#126 楼 @l84222780 你 windows 跑的还是 mac,如果是 windows 文件分隔符不一样的
#127 楼 @huangejuan 这边也无法重现,有空我跟一下吧
#131 楼 @l84222780 windows 没测试过,工作太忙,过完这阵会更新的,如果急着用可以自己先研究下源代码
quqing,您好,能不能建一个 qq 交流群呀,那样的话交流起来效率会比较高。
#132 楼 @quqing 这两天在 mac 上跑也是这样的报错。请问是为什么呢?打包有问题?addcndeMacBook-Pro:AutoTraveler-master addcn$ java -jar AutoTraveler.jar android confige/android.xml
Exception in thread "main" java.lang.NoClassDefFoundError: org/openqa/selenium/Capabilities
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at pers.traveler.robot.RobotFactory.build(RobotFactory.java:13)
at pers.traveler.test.Main.main(Main.java:20)
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.Capabilities
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 4 more
#134 楼 @l84222780
at pers.traveler.robot.RobotFactory.build(RobotFactory.java:13) 可能是这个问题,你 package 结构有没有改过?
通过反射动态创建的,执行到这一步报错了:Class clazz = Class.forName(Package.ROBOT.replaceAll("#type#", robotType));
public class RobotFactory {
public static Robot build(String robotType, String configFile) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Class.forName(Package.ROBOT.replaceAll("#type#", robotType));
return (Robot) clazz.getConstructor(String.class).newInstance(configFile);
}
}
很有可能是这个 package 找不到:Package.ROBOT
public interface Package {
String DEVICE = "pers.traveler.device.#type#Device";
String ENGINE = "pers.traveler.engine.#type#Engine";
String ROBOT = "pers.traveler.robot.#type#Robot";
}
你好! 我这边 已经跑起来了! 不过我希望能把每个页面的资源拉出来,检查 里面是否包含有一些特定的值,如:卡壳、系统错误等等异常信息,用来捕获遍历过程中发现业务异常,不知道该怎么做? 或者最新的版本中有考虑这些吗 ?
非常感谢,楼主开源的代码,虽然已经能够做一些改造,但如果作者已经有了这方面的设计,还是希望用原版的,呵呵!
#138 楼 @mengde0077 这篇是否符合你的需求,https://testerhome.com/topics/5836
您好,想请教两个问题:1、当前窗口唯一标识符是根据什么原理来确定的? 2、限制遍历深度是为什么呢?一直遍历到底不行,难道是因为怕遍历到底会很深,容易乱?
@quqing 编译没包含类!
谁有编译好的 jar 包,能发网盘或者我邮箱么 hsqzggg@qq.com,谢谢!
配置好Android,run以后提示这个
Exception in thread "main" java.lang.IllegalArgumentException: character to be escaped is missing
at java.util.regex.Matcher.appendReplacement(Matcher.java:809)
at java.util.regex.Matcher.replaceAll(Matcher.java:955)
at java.lang.String.replaceAll(String.java:2223)
at pers.traveler.robot.Robot.beforeTravel(Robot.java:124)
at pers.traveler.robot.AndroidRobot.working(AndroidRobot.java:57)
at pers.traveler.robot.Robot.travel(Robot.java:200)
at pers.traveler.test.Main.main(Main.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
您好,我的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--Appium 服务关键字-->
1.4.16
true
false
zh-Hans
E:/sohuVideoMobile_6.0.2_680_20161123125646.apk
9bb30df4
Android
4.4.2
vivo Xplay3S
com.sohu.sohuvideo
com.sohu.sohuvideo.ui.MainActivity
true
true
true
<!--引导流 关键字驱动,引导至所需模块再开始遍历-->
tips>>禁止 | 允许>>//android.widget.Button[@resource-id='com.huawei.systemmanager:id/btn_allow']
<!--滑动类型设置-->
slide>>2
<!--点击类型设置-->
click>>id::com.xxx.xxx:id/btnnext
click>>id::com.xxx.xxx:id/text_home_head_login
<!--输入类型设置-->
click>>id::com.xxx.xxx:id/otp_tv_login_with_username
input>>id::com.xxx.xxx:id/tv_loginAccount|13012345678
input>>id::com.xxx.xxx:id/loginPassword|123
click>>id::com.xxx.xxx:id/tv_login
<!--手势密码-->
gesture>>xpath:://android.widget.FrameLayout[@resource-id='com.xxx.xxx:id/gesture_container']//android.view.View[1]//android.widget.ImageView
gesture>>xpath:://android.widget.FrameLayout[@resource-id='com.xxx.xxx:id/gesture_container']//android.view.View[1]//android.widget.ImageView
<!--窗口鉴定策略,默认取前 8 个节点生成 md5-->
8
<!--Tab 窗口用 selected 区别,可能要多选几个节点到达-->
专题,直播,要闻,选股>>24
简单理财,投资,保险,贷款,信用卡>>30
<!--窗口执行顺序 1:从上到下 (默认) 2:从下到上-->
1
<!--控件白名单-->
UIAImage
UIAButton
UIASwitch
UIATableCell
UIAStaticText
UIAPickerWheel
UIACollectionCell
android.widget.Button
android.widget.ImageButton
android.widget.TextView
android.widget.ImageView
android.widget.FrameLayout
android.widget.LinearLayout
UIATextField
UIASearchBar
UIASecureTextField
android.widget.EditText
<!--启动界面提示框,包含的关键字及操作的控件-->
禁止 | 允许>>//android.widget.Button[@resource-id='com.huawei.systemmanager:id/btn_allow']
<!--无需返回的列表,需配置识别窗口唯一性的内容-->
首页
财经快讯,我,我的订单,活期,定期
<!--黑名单 支持 text,name,resourceId 的过滤-->
相机
退出登录
如您已完成添加,请重新登录
重新登录
//UIAApplication[1]/UIAWindow[4]/UIAPicker[1]/UIAPickerWheel[1]
//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIATableCell[2]/UIACollectionView[1]/UIACollectionCell[5]
<!--触发器 条件>>动作 支持返回,点击,手势密码解锁,延时等待-->
拍照>>back
相册>>back
扫描框>>back
分享到>>back
我的权益>>delay->3
选择银行>>back
选择保险公司>>back
检测到新版本>>back
添加产品 | 保存>>back
消息 | 全部>>back
closeButton>>//android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.ImageButton
安全验证 | 立即验证 | 以后再说>>//android.widget.Button[@resource-id='xxx.xxx.xxx:id/rightBtn']
更多解锁方式>>gesture->//android.widget.FrameLayout[@resource-id='com.xxx.xxx:id/gesture_container']//android.view.View[1]//android.widget.ImageView
<!--过滤级别 1:clazz+text+content_desc+resourceId 2:winID+clazz+text+content_desc+resourceId 3:taskID-->
2
<!--退出遍历的条件:同一窗口内的停留次数-->
10
<!--app 日志-->
adb -s #udid# logcat -b main -b system -b events -b radio *:D | grep xxx
<!--Appium port-->
4723
<!--Appium host-->
127.0.0.1
<!--测试类型 1.android 2.ios 3.web-->
1
<!--运行模式 1.遍历模式 2.业务场景模式-->
1
<!--遍历深度-->
3
<!--截图和视频的目录-->
/Users/mac/Desktop/png
<!--启动 appium-->
/Applications/Appium.app/Contents/Resources/node/bin/node /Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js -p #port# -bp 5760 --session-override --command-timeout 7200 --udid #udid#
<!--遍历时间 分-->
10
<!--延时等待 秒-->
3
<!--超时 秒-->
30
运行时出现如下错误:
2016-11-24 18:33:22 sys_log : [INFO] Appium Server -> http://127.0.0.1:4723/wd/h
ub
log4j:WARN No appenders could be found for logger (org.apache.http.client.protoc
ol.RequestAddCookies).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.openqa.selenium.remote.UnreachableBrowserExceptio
n: Could not start a new session. Possible causes are invalid address of the rem
ote server or browser start-up failure.
Build info: version: '2.53.0', revision: '35ae25b', time: '2016-03-15 17:00:58'
System info: host: 'changhe-tj', ip: '10.7.40.59', os.name: 'Windows 7', os.arch
: 'amd64', os.version: '6.1', java.version: '1.8.0_91'
Driver info: driver.version: AndroidDriver
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.ja
va:665)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGener
icMobileDriver.java:43)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.jav
a:1)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriv
er.java:249)
at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.jav
a:131)
at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.jav
a:144)
at io.appium.java_client.DefaultGenericMobileDriver.(DefaultGeneri
cMobileDriver.java:39)
at io.appium.java_client.AppiumDriver.(AppiumDriver.java:69)
at io.appium.java_client.AppiumDriver.(AppiumDriver.java:78)
at io.appium.java_client.android.AndroidDriver.(AndroidDriver.java
:67)
at pers.traveler.robot.Robot.beforeTravel(Robot.java:118)
at pers.traveler.robot.AndroidRobot.working(AndroidRobot.java:57)
at pers.traveler.robot.Robot.working(Robot.java:163)
at pers.traveler.robot.Robot.travel(Robot.java:202)
at pers.traveler.test.Main.main(Main.java:21)
Caused by: org.openqa.selenium.WebDriverException: org.apache.http.conn.HttpHost
ConnectException: Connect to 127.0.0.1:4723 [/127.0.0.1] failed: Connection refu
sed: connect
Build info: version: '2.53.0', revision: '35ae25b', time: '2016-03-15 17:00:58'
System info: host: 'changhe-tj', ip: '10.7.40.59', os.name: 'Windows 7', os.arch
: 'amd64', os.version: '6.1', java.version: '1.8.0_91'
Driver info: driver.version: AndroidDriver
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumComm
andExecutor.java:76)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.ja
va:644)
... 15 more
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to 127.0.0.1:4
723 [/127.0.0.1] failed: Connection refused: connect
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect
(DefaultHttpClientConnectionOperator.java:151)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(
PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClie
ntExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.
java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java
:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java
:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttp
Client.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttp
Client.java:71)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttp
Client.java:55)
at org.openqa.selenium.remote.internal.ApacheHttpClient.fallBackExecute(
ApacheHttpClient.java:144)
at org.openqa.selenium.remote.internal.ApacheHttpClient.execute(ApacheHt
tpClient.java:90)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExe
cutor.java:142)
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumComm
andExecutor.java:64)
... 16 more
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocke
t(PlainConnectionSocketFactory.java:74)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect
(DefaultHttpClientConnectionOperator.java:134)
... 29 more
2016-11-24 18:33:32 sys_log : [INFO] 遍历测试持续时间 -> 40.00s
2016-11-24 18:33:42 sys_log : [INFO] 遍历测试持续时间 -> 50.00s
2016-11-24 18:33:52 sys_log : [INFO] 遍历测试持续时间 -> 1.00m
2016-11-24 18:34:02 sys_log : [INFO] 遍历测试持续时间 -> 1.17m
2016-11-24 18:34:12 sys_log : [INFO] 遍历测试持续时间 -> 1.33m
请问这是什么原因呢??
LZ,你的项目是否可以使用 UIautomator2,直接在打包成 apk 跑?
log4j:ERROR Could not read configuration file [/Users/admin/Desktop/src/log4j.properties].
java.io.FileNotFoundException: /Users/admin/Desktop/src/log4j.properties (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.(FileInputStream.java:138)
at java.io.FileInputStream.(FileInputStream.java:93)
at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:306)
at org.apache.log4j.PropertyConfigurator.configure(PropertyConfigurator.java:324)
at pers.traveler.log.Log.(Log.java:17)
at pers.traveler.robot.Robot.travel(Robot.java:172)
at pers.traveler.test.Main.main(Main.java:21)
log4j:ERROR Ignoring configuration file [/Users/admin/Desktop/src/log4j.properties].
该怎么搞啊?
楼主在使用 Windows 引导执行 driver.manage().window().getSize().width;就报了下面这个错误,我把部分功能提取出来单独运行没有任何问题,不知道有没有人遇到类似的情况,折腾 1 天了 还是没解决
error: Unhandled error: Error: read ECONNRESET
at exports._errnoException (util.js:896:11)
at TCP.onread (net.js:556:26) context: [POST /wd/hub/session {"desiredCapab
lities":{"app":"D:\AndroidSDK\sdk\build-tools\22.0.1\doctor.apk","appPacka
e":"com.szyino.patientclient","noReset":"false","noSign":"true","platformVersio
":"4.4.4","unicodeKeyboar]
@quqing 你好,问下节点的唯一性是如何解决的呢,可能会变化的吧
请问下,报以下错误是撒回事了
@quqing
Exception in thread "main" org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Failed to set language: zh-CN and country: null (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 2.39 seconds
Build info: version: '2.53.0', revision: '35ae25b', time: '2016-03-15 17:00:58'
System info: host: 'MacBook-Pro.local', ip: '10.88.xx.xx', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.14.5', java.version: '1.8.0_211'
Driver info: io.appium.java_client.android.AndroidDriver
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:678)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:43)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:249)
at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:131)
at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:144)
at io.appium.java_client.DefaultGenericMobileDriver.(DefaultGenericMobileDriver.java:39)
at io.appium.java_client.AppiumDriver.(AppiumDriver.java:69)
at io.appium.java_client.AppiumDriver.(AppiumDriver.java:78)
at io.appium.java_client.android.AndroidDriver.(AndroidDriver.java:67)
at pers.traveler.robot.Robot.beforeTravel(Robot.java:118)
at pers.traveler.robot.AndroidRobot.working(AndroidRobot.java:57)
at pers.traveler.robot.Robot.travel(Robot.java:200)
at pers.traveler.test.TravelerTest.main(TravelerTest.java:18)