很多人喜欢写框架,喜欢所谓配置和代码分离,事实上页面元素本来就应该和 PageObject 对应,这种对应关系越近,理解就越容易,而且修改代码有 ide 的 navigation,维护代码有 git 的 branch。就好比写个 orm 框架,数据库字段的配置还要存到数据库,大部分时候,真的好累
小心而彻底的真实
个人的危机还是若隐若现.时刻像一个定时炸弹
这其中其实并没有自己的贡献. 觉得也有些失落
如今 java-client 3.2 也提供了类似的服务https://github.com/appium/java-client/blob/master/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java
使用 builder 模式 api 更友好,但在 kill process 方便更相信 appium 本身
创业公司->淘宝 ->创业公司->携程 大公司相对少的努力可以获得比小公司多的待遇上回报,可是为何还想去创业公司,就是内心想燃烧的冲动,不想就这样的活,可是到了小公司又并没有改变什么,相反是各种技术人遇到的痛苦,就这样来回奔波,然后,一种情怀吧
#23 楼 @sunflower
如果用 nodejs npm 安装 appium,chromedriver 是被包含进去的,不会直接去 chromedriver 站点下载
#6 楼 @springs412
我的几个帖子,其实就是和 appium/selenium grid 的方式相反了,通过在一台 node 上,并行启动 appium,让 testng 去管理。当时是鉴于 appium 的不稳定,所以这样做。
比较简单,但正是区别优秀与一般的好知识,好文
#16 楼 @ganyunxiao
开始我也用的 chimpchat 后来发现还是 ddmlib 更通用,功能也更全,忘记了,貌似 chimpchat 是基于 ddmlib
#7 楼 @xcgspring 看了一下写的很赞!
这也正是 selenium 中的最佳实践推荐
https://seleniumhq.github.io/docs/best.html#best_practices
#2 楼 @chenhengjie123 locale 改为 en_US 了,应该没编码问题,至于中文...其实方法名称就差不多了
appium 和设备之间没有什么直接的关系。我们一台电脑启动两个 appium instance, 分别连一个 device 没有问题。有问题也是 appium 本身对多进程的支持小 bug,但不影响你问的问题
.....最简单的方式,把一个 appium server 实例看成一个 process,关闭它就好了。如果直接使用 nodejs 来启停,有对应的 stop 或 unbind 方法。如果使用其他语言,就按照操作 process 方式。java 语言可以参考http://testerhome.com/topics/1864
#5 楼 @chenhengjie123 恩,第一遍看的不够细。我是直接把下载 chromedriver 那一段,人工做了。
如果需要 build android chrome 的,chromedriver 如果没代理也下载不下来,需要调整下 reset.sh
#5 楼 @zhubaitian 工作中用不到 mokeyrunner,看了你几篇原理分析部分,分析的很透彻,很赞。期望下面出现你要找的人
支持一下! mokeyrunner 似乎基于 ddmlib/chimpchat 我倒是对 ddmlib 源码比较熟悉一点,可以共同学习。
Lazy 这个想法很好,这也正是 PageObjectFactory 本身帮我们做了的事情。PageObject 中的元素本身就是延迟加载,并且可以使用查询 cache
http://relevantcodes.com/pageobjects-and-pagefactory-design-patterns-in-selenium/#CacheLookup
如果我们对第三方框架多了解一些,很多美好的想法,都已经实现了。这也正是在 ctrip 比较难过的事情,很多框架各种封装,所谓简单,都已经改变了一些标准和第三方框架本身的设计,面目全非,经不起推敲,而繁琐。
通过 ddmlib 获取也可以,代码也容易维护,升级。我基于 ddmlib 本想封装一下,可发现原生的也不那么难用...
https://github.com/cosysoft/device
不需要绝对正确,端口范围很大,不会出问题就行
/**
* A simple rather userful port finder
*
* @author ctrip
*
*/
public class AvailablePortFinder {
public static final int MIN_PORT_NUMBER = 40000;
public static final int MAX_PORT_NUMBER = 60000;
private static int current = MIN_PORT_NUMBER;
private AvailablePortFinder() {
}
public synchronized static int getNextAvailable() {
if (++current == MAX_PORT_NUMBER) {
current = MIN_PORT_NUMBER;
}
return getNextAvailable(current);
}
private synchronized static int getNextAvailable(int fromPort) {
if ((fromPort < MIN_PORT_NUMBER) || (fromPort > MAX_PORT_NUMBER)) {
throw new IllegalArgumentException("Invalid start port: "
+ fromPort);
}
for (int i = fromPort; i <= MAX_PORT_NUMBER; i++) {
if (available(i)) {
return i;
}
current++;
}
throw new NoSuchElementException("Could not find an available port "
+ "above " + fromPort);
}
private static boolean available(int port) {
if ((port < MIN_PORT_NUMBER) || (port > MAX_PORT_NUMBER)) {
throw new IllegalArgumentException("Invalid start port: " + port);
}
ServerSocket ss = null;
DatagramSocket ds = null;
try {
ss = new ServerSocket(port);
ss.setReuseAddress(true);
ds = new DatagramSocket(port);
ds.setReuseAddress(true);
return true;
} catch (IOException e) {
} finally {
if (ds != null) {
ds.close();
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
/* should not be thrown */
}
}
}
return false;
}
}
#3 楼 @lihuazhang 恩我得先问问老大。可以先写个 ppt 什么的,其实 Appium 一路走来还是蛮苦的