手机自动化测试:appium源码分析之bootstrap三
手机自动化测试:appium源码分析之bootstrap三
研究bootstrap源码,我们可以通过代码的结构,可以看出来appium的扩展思路和实现方式,从中可以添加我们自己要的功能,针对appium进行定制,poptest在2015年10月24日开设appium的课程,课程采用真实的商业项目进行培训,用现在互联网金融的业务。
bootstrap代码中io.appium.android.bootstrap.handler包中的类都是对应的指令类,核心都是execute方法。
下面我们看下HashMap:
private static HashMap<String, CommandHandler> map = new HashMap<String, CommandHandler>();
static {
map.put("waitForIdle", new WaitForIdle());
map.put("clear", new Clear());
map.put("orientation", new Orientation());
map.put("swipe", new Swipe());
map.put("flick", new Flick());
map.put("drag", new Drag());
map.put("pinch", new Pinch());
map.put("click", new Click());
map.put("touchLongClick", new TouchLongClick());
map.put("touchDown", new TouchDown());
map.put("touchUp", new TouchUp());
map.put("touchMove", new TouchMove());
map.put("getText", new GetText());
map.put("setText", new SetText());
map.put("getName", new GetName());
map.put("getAttribute", new GetAttribute());
map.put("getDeviceSize", new GetDeviceSize());
map.put("scrollTo", new ScrollTo());
map.put("find", new Find());
map.put("getLocation", new GetLocation());
map.put("getSize", new GetSize());
map.put("wake", new Wake());
map.put("pressBack", new PressBack());
map.put("dumpWindowHierarchy", new DumpWindowHierarchy());
map.put("pressKeyCode", new PressKeyCode());
map.put("longPressKeyCode", new LongPressKeyCode());
map.put("takeScreenshot", new TakeScreenshot());
map.put("updateStrings", new UpdateStrings());
map.put("getDataDir", new GetDataDir());
map.put("performMultiPointerGesture", new MultiPointerGesture());
map.put("openNotification", new OpenNotification());
}
appium底层调用的是uiautomator的api。我们看下click动作:
package io.appium.android.bootstrap.handler;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObjectNotFoundException;
import io.appium.android.bootstrap.*;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.Hashtable;
/**
* This handler is used to click elements in the Android UI.
*
* Based on the element Id, click that element.
*
*/
public class Click extends CommandHandler {
/*
* @param command The {@link AndroidCommand}
*
* @return {@link AndroidCommandResult}
*
* @throws JSONException
*
* @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android.
* bootstrap.AndroidCommand)
*/
@Override
public AndroidCommandResult execute(final AndroidCommand command)
throws JSONException {
if (command.isElementCommand()) {
try {
final AndroidElement el = command.getElement();
el.click();
return getSuccessResult(true);
} catch (final UiObjectNotFoundException e) {
return new AndroidCommandResult(WDStatus.NO_SUCH_ELEMENT,
e.getMessage());
} catch (final Exception e) { // handle NullPointerException
return getErrorResult("Unknown error");
}
} else {
final Hashtable<String, Object> params = command.params();
final Double[] coords = { Double.parseDouble(params.get("x").toString()),
Double.parseDouble(params.get("y").toString()) };
final ArrayList<Integer> posVals = absPosFromCoords(coords);
final boolean res = UiDevice.getInstance().click(posVals.get(0),
posVals.get(1));
return getSuccessResult(res);
}
}
}
该类中的方法处理点击事件,首先方法会判断你传入的命令参数是针对控件对象的还是坐标的
如果参数是控件,会获得命令中的控件对象,然后调用click方法
AndroidElement.java
public boolean click() throws UiObjectNotFoundException {
return el.click();
}
在代码中el如下定义:private final UiObject el;
说明调用的是uiautomator中的UiObject类的click方法,click方法的作用就是点击该控件中心,点击完成后调用getSuccessResult
/**
* Returns success along with the payload.
*
* @param value
* @return {@link AndroidCommandResult}
*/
protected AndroidCommandResult getSuccessResult(final Object value) {
return new AndroidCommandResult(WDStatus.SUCCESS, value);
}
创建AndroidCommandResult新对象,传入WDStatus.SUCCESS,和value(我们这里传入的值为true).首先看一下SUCCESS的值,该值存放在枚举类WDStatus中。
SUCCESS (0, "The command executed successfully."),
下面进入AndroidCommandResult类的构造方法里。
JSONObject json;
public AndroidCommandResult(final WDStatus status, final Object val) {
json = new JSONObject();
try {
json.put("status", status.code());
json.put("value", val);
} catch (final JSONException e) {
Logger.error("Couldn't create android command result!");
}
}
构造方法里把传入的参数保存在了json对象中,以键值对的形式。好了,条件为控件的情况分析结束,下面开始分析坐标。
坐标
如果是坐标的话,程序会获得命令里的坐标参数,保存在Double数组中。
final Hashtable<String, Object> params = command.params();
final Double[] coords = { Double.parseDouble(params.get("x").toString()),
Double.parseDouble(params.get("y").toString()) };
接下来会通过absPosFromCoords方法将Double转换为List。所以下面来看absPosFromCoords方法的实现:
/**
* Given a position, it will return either the position based on percentage
* (by passing in a double between 0 and 1) or absolute position based on the
* coordinates entered.
*
* @param coordVals
* @return ArrayList<Integer>
*/
protected static ArrayList<Integer> absPosFromCoords(final Double[] coordVals) {
final ArrayList<Integer> retPos = new ArrayList<Integer>();
final UiDevice d = UiDevice.getInstance();
final Double screenX = (double) d.getDisplayWidth();
final Double screenY = (double) d.getDisplayHeight();
if (coordVals[0] < 1 && coordVals[1] < 1) {
retPos.add((int) (screenX * coordVals[0]));
retPos.add((int) (screenY * coordVals[1]));
} else {
retPos.add(coordVals[0].intValue());
retPos.add(coordVals[1].intValue());
}
return retPos;
}
首先会判断传入的坐标是以百分比的形式还是以坐标的形式。如果是百分比说明你传入的不是绝对坐标,而是相对坐标,这种情况你就需要获取屏幕的尺寸,然后和百分比做计算得到当前屏幕中你所要点击的坐标点。如果传入的是坐标,那就直接将Double类型的值转化为Int的值。
经过上面的一番操作以后,会得到确切坐标值保存在数组中返回。
然后程序调用UiDevice的click方法点击啦:
final boolean res = UiDevice.getInstance().click(posVals.get(0), posVals.get(1));
最后返回一个成功的AndroidCommandResult对象。
手机自动化测试:appium源码分析之bootstrap三的更多相关文章
- 手机自动化测试:appium源码分析之bootstrap二
手机自动化测试:appium源码分析之bootstrap二 在bootstrap项目中的io.appium.android.bootstrap.handler包中的类都是对应的指令类, priva ...
- 手机自动化测试:appium源码分析之bootstrap一
手机自动化测试:appium源码分析之bootstrap一 前言: poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.popte ...
- 手机自动化测试:appium源码分析之bootstrap十七
手机自动化测试:appium源码分析之bootstrap十七 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
- 手机自动化测试:appium源码分析之bootstrap十六
手机自动化测试:appium源码分析之bootstrap十六 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
- 手机自动化测试:appium源码分析之bootstrap十五
手机自动化测试:appium源码分析之bootstrap十五 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
- 手机自动化测试:appium源码分析之bootstrap十四
手机自动化测试:appium源码分析之bootstrap十四 poptest(www.poptest.cn)是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开 ...
- 手机自动化测试:appium源码分析之bootstrap十三
手机自动化测试:appium源码分析之bootstrap十三 poptest(www.poptest.cn)是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开 ...
- 手机自动化测试:appium源码分析之bootstrap十一
手机自动化测试:appium源码分析之bootstrap十一 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
- 手机自动化测试:appium源码分析之bootstrap十二
手机自动化测试:appium源码分析之bootstrap十二 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
随机推荐
- BZOJ 1033: [ZJOI2008]杀蚂蚁antbuster(模拟)
坑爹的模拟题QAQ DEBUG多了1kb QAQ 按题意做就行了 注意理解题意啊啊啊啊 尼玛输出忘换行wa了3次QAQ CODE: #include<cstdio>#include< ...
- spring中对象的注入方式
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...
- console深入理解
["$$", "$x", "dir", "dirxml", "keys", "values ...
- 从项目经理的角度看.net的MVC中Razor语法真的很垃圾.
我们知道,Razor语法中我们可以直接使用@if(){}等代码段,这使得.net程序员在写模版时更容易了. 对比如下: 语法名称 Razor 语法 Web Forms 等效语法 代码块(服务端) @{ ...
- ajax跨域请求时,sessionId不一样,导致无法记住登陆状态
遇到这样一个场景,就是前端的域是dev,请求接口时,接口的域是beta,即使在服务端设置了cookie存放的域,'COOKIE_DOMAIN' => '.roboming.com',虽然c ...
- redis的数据类型 (一) 字符串
redis中存储方式是以键值对存储的,所以叫做字典试.redis(Remote dictionary server)远程字典服务器 每个redis数据类型,都会有增加.删除,查看的功能,用实例来学习命 ...
- 模仿Wireshark网络抓包工具实现---c++
最近在用Wireshark抓包工具的时候,老感觉这东西用起来很简单,功能强大,所以想了解他的实现原理,我就自己好奇写了一个实现基本功能的demo吧. 其实叫抓包工具,其实就是抓取流经自己网卡的所有ip ...
- vim编辑器的常见使用功能
Vim是一个类似于vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性. 掌握简单的vim命令可以大大提高我们编辑文档效率,在装有vim编辑器的linux系统终端输入vim ...
- 【JS】JavaScript中的参数传递
ECMAScript中所有函数的参数都是按值传递的,简单讲就是函数外部的值 复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样.切记访问变量有按值访问和按引用访问,而参数只能按值传递. 在向 ...
- 关于使用lazytag的线段树两种查询方式的比较研究
说到线段树,想来大家并不陌生——最基本的思路就是将其规划成块,然后只要每次修改时维护一下即可. 但是尤其是涉及到区间修改时,lazytag的使用往往能够对于程序的质量起到决定性作用(Ex:一般JSOI ...