美文网首页
Appium关于WebView和Safar调试

Appium关于WebView和Safar调试

作者: Peter杰 | 来源:发表于2020-12-01 10:41 被阅读0次

    前言

    在苹果的官方文档 https://developer.apple.com/safari/tools/,我们可以看到Safari包含Web Inspector,这是一个功能强大的工具,可轻松修改,调试和优化网站,以在两个平台上实现最佳性能和兼容性。借助自适应设计模式,您甚至可以预览网页以获取各种屏幕尺寸,方向和分辨率。要访问这些工具,请在Safari的“高级”偏好设置中启用“开发”菜单。

    Web Inspector是您的命令中心,可让您快速轻松地访问Web浏览器中包含的最丰富的开发工具集。它可以帮助您检查网页上的所有资源和活动,从而使跨macOS,iOS和tvOS的开发更加高效。简洁统一的设计将每个核心功能放在一个单独的选项卡中,您可以对其进行重新排列以适合您的工作流程。在macOS Sierra中,您可以发现新的方法来使用时间轴调试内存,并使用控件的微调样式来调整150多种最常见的CSS属性。

    ios_webkit_debug_proxy 原理

    所以关于iOS获取WebView和Safari上的Elements,需要用到Web Inspector库。
    Appium借助ios_webkit_debug_proxy来获取WebView和Safari上的Elements。

    ios_webkit_debug_proxy(又名iwdp)通过websocket连接代理来自usbmuxd守护进程的请求,允许开发人员在真实和模拟的iOS设备上向MobileSafari和UIWebViews发送命令。

    Source

    设计如下如


    各种客户端如下所示

    ios_webkit_debug_proxy的主要组件是:
    监听iOS设备添加/删除事件的device_listener
    每个设备的(端口,webinspector)对,例如:
    [(端口9222 <-> iphoneX的检查器,
    (端口9223 <-> iphoneY的检查器,...]
    零个或多个活动的WebSocket客户端,例如:
    [websocketA已连接到:9222 / devtools / page / 7,...]
    一个处理所有套接字I / O的socket_manager

    device_listener头文件

    `// Google BSD license [https://developers.google.com/google-bsd-license](https://developers.google.com/google-bsd-license)`
    
    `// Copyright 2012 Google Inc. wrightt@google.com`
    
    `//`
    
    `// iOS device add/remove listener.`
    
    `//`
    
    `#ifndef DEVICE_LISTENER_H`
    
    `#define DEVICE_LISTENER_H`
    
    `#ifdef  __cplusplus`
    
    `extern` `"C"` `{`
    
    `#endif`
    
    `#include <stdbool.h>`
    
    `#include <stdint.h>`
    
    `#include <stdlib.h>`
    
    `typedef` `uint8_t dl_status;`
    
    `#define DL_ERROR 1`
    
    `#define DL_SUCCESS 0`
    
    `// Create a device add/remove connection.`
    
    `// @param recv_timeout milliseconds, negative for non_blocking`
    
    `// @result fd, or -1 for error`
    
    `int` `dl_connect(``int` `recv_timeout);`
    
    `struct` `dl_struct;`
    
    `typedef` `struct` `dl_struct *dl_t;`
    
    `dl_t dl_new();`
    
    `void` `dl_free(dl_t self);`
    
    `struct` `dl_private;`
    
    `typedef` `struct` `dl_private *dl_private_t;`
    
    `// iOS device add/remove listener.`
    
    `struct` `dl_struct {`
    
    `//`
    
    `// Use these API:`
    
    `//`
    
    `// Call once after startup.`
    
    `dl_status (*start)(dl_t self);`
    
    `// Call to append data, calls on_attach/on_detach when we have a full`
    
    `// input packet.`
    
    `dl_status (*on_recv)(dl_t self, ``const` `char` `*buf, ssize_t length);`
    
    `void` `*state;`
    
    `bool` `*is_debug;`
    
    `//`
    
    `// Set these callbacks:`
    
    `//`
    
    `// Called to send "listen" and other output packets.`
    
    `dl_status (*send_packet)(dl_t self, ``const` `char` `*buf, ``size_t` `length);`
    
    `// Called by on_recv.`
    
    `// @param device_id 40-character hex iOS device identifier.`
    
    `// @param device_num usbmuxd device identifier`
    
    `dl_status (*on_attach)(dl_t self, ``const` `char` `*device_id, ``int` `device_num);`
    
    `dl_status (*on_detach)(dl_t self, ``const` `char` `*device_id, ``int` `device_num);`
    
    `// For internal use only:`
    
    `dl_private_t private_state;`
    
    `};`
    
    `#ifdef  __cplusplus`
    
    `}`
    
    `#endif`
    
    `#endif  /* DEVICE_LISTENER_H */`
    
    

    两个“公共API”函数

    dl_status (*start)(dl_t self);
    dl_status (*on_recv)(dl_t self, const char *buf, );
    

    和三个“抽象”回调函数:

    dl_status (*send)(dl_t self, const char *buf, size_t length);
    dl_status (*on_attach)(dl_t self, const char *device_id);
    dl_status (*on_detach)(dl_t self, const char *device_id);
    

    以及供客户使用的字段: void *state;

    examples / dl_client.c创建一个侦听器并设置缺少的回调:

     int fd = dl_connect();
     dl_t dl = dl_new(); // sets the "start" and "on_recv" functions
     dl->state = fd;     // for use by "my_send"
     dl->send = my_send; // --> send((int)dl->state, buf, length);
     dl->on_attach = my_on_attach; // --> printf("%s", device_id);
     dl->on_detach = my_on_detach; // --> ditto
    

    然后

    dl->start();
    

    最后,客户端将所有套接字输入转发到侦听器的“ on_recv”处理程序:

    char buf[1024];
     while (1) {
         int len = recv(fd, buf, 1024);
          if (dl->on_recv(dl, buf, len)) break;
      }
    
    

    其中,“ on_recv”会缓冲输入内容,并在有完整消息时调用“ my_on_message”。

    请注意,“ on_recv”和“发送”功能从接口提取I / O,从而简化了调试和单元测试。

    详细设计如下所示:


    image.png

    红色行由主“ ios_webkit_debug_proxy”控制。例如,尽管该图显示了从socket_manager的“ on_recv”到ios_webkit_debug_proxy的处理程序的直接红线,但这是通过ios_webkit_debug_proxy_main的“ iwdpm_on_recv(...)”实现的回调。这种设计将组件彼此隔离,并简化了离线和按组件的单元测试。

    安装与使用

    与Web视图进行交互Appium使用自定义的远程调试器建立连接。在模拟器上执行时,由于模拟器和Appium服务器在同一台计算机上,因此直接建立了连接。Appium可以自动执行WkWebViewUIWebView 元素。

    不管是iOS平台的web view还是safari浏览器都需要安装及设置以下三点:

    1、brew install --HEAD libimobiledevice

    2、brew install ios-webkit-debug-proxy

    3、settings(设置) > safari(浏览器) > advanced(高级) > web inspector(网页检查器) -> on(打开)

    启用ios-webkit-debug-proxy 要添加startIWDP:true
    iOS WebView

    import time
    from appium import webdriver
    
    class TestDemo:
    
        def setup(self):
            desired_caps = {}
            desired_caps['platformName'] = 'iOS'
            desired_caps['platformVersion'] = '11.2'
            desired_caps['automationName'] = "xcuitest"
            desired_caps['deviceName'] = 'wj'
            desired_caps['udid'] = '7e2ab74a0a110f43a46009bda771f409f20e6ca2'
            desired_caps['bundleId'] = 'com.xes.WJTest'
            desired_caps['startIWDP'] = True;
    
            self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
            self.driver.implicitly_wait(5)
        
        def testWebView(self):
            self.driver.switch_to.context(self.driver.contexts[1])
            #打印网页源文件
            print(self.driver.page_source)
    
        def teardown(self):
            self.driver.quit()
    

    iOS Safari

    import time
    from appium import webdriver
    
    class TestDemo:
    
        def setup(self):
            desired_caps = {}
            desired_caps['platformName'] = 'iOS'
            desired_caps['platformVersion'] = '11.2'
            desired_caps['automationName'] = "xcuitest"
            desired_caps['deviceName'] = 'wj'
            desired_caps["browserName"] = "Safari"
            desired_caps['udid'] = '7e2ab74a0a110f43a46009bda771f409f20e6ca2'
            #desired_caps['bundleId'] = 'com.xes.WJTest'
            #desired_caps['startIWDP'] = True;
    
            self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
            self.driver.implicitly_wait(5)
    
        def test_safair(self):
            self.driver.get("https://testerhome.com")
            time.sleep(3)
            print(self.driver.page_source)
            self.driver.find_element_by_link_text("社团").click()
            time.sleep(1)
            self.driver.find_element_by_link_text("BlackTest").click()
    
        def teardown(self):
            self.driver.quit()
    

    相关文章

      网友评论

          本文标题:Appium关于WebView和Safar调试

          本文链接:https://www.haomeiwen.com/subject/jsgjwktx.html