zoukankan      html  css  js  c++  java
  • Appuim源码剖析(Bootstrap)

    Appuim源码剖析(Bootstrap) 

    SkySeraph Jan. 26th 2017

    Email:skyseraph00@163.com

    更多精彩请直接访问SkySeraph个人站点www.skyseraph.com 

    About

    Appuim

    Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用。

    这里有很关键一点,跨平台。更多了解Appuim多平台支持相关信息,参考官方platform-support

    相关概念

    • C/S 架构
      Appium 的核心是一个 web 服务器,它提供了一套 REST 的接口,接收客户端的连接,监听到命令,接着在移动设备上执行这些命令,然后将执行结果放在 HTTP 响应中返还给客户端。
    • Session机制
      Appuim的自动化测试是在一个 session 的上下文中运行,可以理解成Appuim会话。
      每一次当Appium server成功启动后,客户端的测试库(client library)会要求与Server创建一个会话(session)。
      会话的作用是为了确保能区别不同的客户端请求与不同的被测应用,每个特定的会话都有一个特定的sessionId参数。每次测试开始时,客户端将初始化一个session会话,虽然不同的语言初始化的方式不同,但是他们都要发送POST/session请求到服务器端,这些请求里面都会带有一个对象:desired capabilities ,这个时候服务器端会启动自动化session然后返回一个session ID,以后的命令都会用这个seesion ID去匹配。

    • Appuim服务端
      包含众多语言库(Java, Ruby, Python, PHP, JavaScript,C#等),都实现了 Appium 对 WebDriver 协议的扩展。

    • JSON wire protocol
      Appuim中非常重要的协议

    Appuim 架构

    Appuim基于Nodejs编写,基于HTTP协议,可以看成一个类似selenium webdriver的基于移动平台的webdriver,遵循RESTful设计风格web服务器,接受客户端的连接然后在手机设备上执行命令,最后通过HTTP的响应收集命令执行的结果。

    如下为我整理的Appuim Android平台下架构原理图,iOS也类似,只是Bootstrap部分由Instruments替换,UiAutomator由UIAutomation替换。

    如下两图参考testerhome PPT的Appuim Android和iOS平台下数据流程图。

    其中,Android平台下,Android API 17+,底层调用android平台自带的UI测试框架Uiautomator;反之,调用的selendroid测试框架来完成。

    Bootstrap源码剖析

    源码结构

    如下所示,Appuim Bootstrap部分源码结构,分UiWatchers、Bootstrap和UIAutomator三部分,非常清晰。

    启动时序

    Bootstrap入口类为Bootstrap.java,继承自UiAutomatorTestCase,然后开启Socket接收命令,时序如下。

    类关系图

    类关系如下图所示,很简单。

    源码分析

    Bootstrap整体分SocketServer部分,CommandHandler部分,Watchers部分和UiAutomator四部分。

    • SocketServer。完成PC Server端命令接收和解析,再通过CommandHandler的execute操作调用UiAutomator实现触控操作。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    try {
    client = server.accept();
    Logger.debug("Client connected");
    in = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
    out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));
    while (keepListening) {
    handleClientData();
    }
    in.close();
    out.close();
    client.close();
    Logger.debug("Closed client connection");
    } catch (final IOException e) {
    throw new SocketServerException("Error when client was trying to connect");
    }
    • CommandHandler,虚基类,功能类都集成自该类完成execute操作,通过HashMap映射,如下。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    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("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());
    map.put("source", new Source());
    map.put("compressedLayoutHierarchy", new CompressedLayoutHierarchy());
    map.put("configurator", new ConfiguratorHandler());
    }

    具体映射通过AndroidCommandExecutor中的execute实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public AndroidCommandResult execute(final AndroidCommand command) {
    try {
    Logger.debug("Got command action: " + command.action());

    if (map.containsKey(command.action())) {
    return map.get(command.action()).execute(command);
    } else {
    return new AndroidCommandResult(WDStatus.UNKNOWN_COMMAND,
    "Unknown command: " + command.action());
    }
    } catch (final JSONException e) {
    Logger.error("Could not decode action/params of command");
    return new AndroidCommandResult(WDStatus.JSON_DECODER_ERROR,
    "Could not decode action/params of command, please check format!");
    }
    }
    • Watchers,Android ANR 和 Crash,如下代码。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public void registerAnrAndCrashWatchers() {
    UiDevice.getInstance().registerWatcher("ANR", new UiWatcher() {
    @Override
    public boolean checkForCondition() {
    UiObject window = new UiObject(new UiSelector()
    .className("com.android.server.am.AppNotRespondingDialog"));
    String errorText = null;
    if (window.exists()) {
    try {
    errorText = window.getText();
    } catch (UiObjectNotFoundException e) {
    Log.e(LOG_TAG, "dialog gone?", e);
    }
    onAnrDetected(errorText);
    postHandler();
    return true; // triggered
    }
    return false; // no trigger
    }
    });
    • UiAutomator,通过UiAutomator执行触控操作。

    Refs



    文章更新, 请移步个人站点查看

    SYNC POST

    ========  

    By SkySeraph-2017

    www.skyseraph.com 

  • 相关阅读:
    MFC单文档中进行plc点云显示
    modbus发送和接收
    测试左移和测试右移
    2021软件测试笔试题
    202106月份总结测试开发面试题
    KuaiShou面试题
    阿拉伯数学手写体。
    GeminiScrollbar
    vue-core-video-player
    webpack
  • 原文地址:https://www.cnblogs.com/skyseraph/p/6443596.html
Copyright © 2011-2022 走看看