Appium关于WebView和Safar调试

2020-12-01  本文已影响0人  Peter杰

前言

在苹果的官方文档 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()
上一篇 下一篇

猜你喜欢

热点阅读