IE Driver

IE 是一个很有意思的浏览器,它是由一些协同工作的COM接口构建成的,这一直延伸到Javascript引擎,常见的Javascript变量实际参考了隐含的COM实例。Javascript窗口是一个IHTML窗口,文档是一个COM接口IHTML文档的实例。微软已经做了非常出色的工作通过增强浏览器来维护现有的行为。这意味着如果一个应用程序如果支持IE6的COM类,它仍可以支持IE9。

IEDriver随着时间推移体系结构也跟着演变,一个非常迫切的需求设计是为了避免安装程序,这是个不常用的需求,所以需要一些解释。首先,当一个开发人员下载个包,在很短暂的时间内,它使用 WebDriver很难通过5分钟的测试,更重要的是WebDriver用户不能在自己的机器上安装软件,这意味着当项目想在IE上测试时,大家不需要记得登陆到持续集成的服务器上运行一个安装文件,,最后, 有些语言并不需要运行安装包,常见的JAVA就是添加JAR文件路径到CLASSPATH中,并且我的经验告诉我需要安装包的那些类库并不太受欢迎。

所以,最后选择结果是不需要安装包。

在windows上编程使用的自然语言是运行于.NET上可能是C#。 通过使用在每个版本的window中都有的IE COM自动化接口,IEDriver集成了IE。特别是,我们通过调用原生的MSHTML和ShDocVw的dll文件使用COM接口,从而形成IE的一部分。在C# 4中,CLR/COM互操作性通过使用单独的主互操作程序集(PIAs)完成,PIA本质上是一个在CLR和COM上的一座桥梁。

遗憾的是,使用C# 4将意味着使用一个很新的.NET RUNTIME版本,很多公司避免走在技术的前沿,更喜欢稳定性好的和问题已知的老版本。使用C# 4我们会自动排除一定比例的用户群,使用PIA也有一些其他缺点。考虑到许可的限制,在于微软协商后,很明确的是,Selenium项目不会有权利发布PIA,无论是MSHTML或ShDocVw类库。即使被授权,每个安装的windows和IE都有一个类库的唯一组合,这意味着我们需要处理很多这样的事情,按需构建客户机的PIA也并不可行,因为他们需要一些可能在普通用户机器上并不存在的开发者工具。

所以,尽管C#是一种很有吸引力的编程语言,但不能选它。至少在与IE通信时,我们需要使用一些原生的东西。很自然的下一个选择就是C++,这也是我们最后选择的语言。使用C++有一个优势就是我们不需要使用PIA,但是它意味着我们需要重新发布Visual Studio C++ 运行的 DLL,除非我们静态链接他们。因为为了能使用那个DLL我们需要运行一个安装程序,链接类库与IE进行通信。

如果不使用安装程序确实需要支付非常高的成本,但是,回想以前复杂的方案,为了让我们的用户更容易的使用是很值得投资的。结论就是我们对当前的工作重新评估,因为为了给用户带来好处,需要付出的是能给一个高级C++开源项目做贡献的人数看起来似乎比那些贡献于同样的C#项目的人要少。

IE driver原始设计如下图:

从堆栈底你可以看到我们使用IE的COM自动化接口,为了在概念层面上更容易的应付,我们包装了这些原始的接口使用了一组C++类,深刻反映了主要的WebDriver API。为了获得与C++通信的的JAVA类,我们使用了JNI,通过COM接口的C++ 抽象的JNI方法实现。

这种方法当JAVA是唯一的客户端语言时很适用,但是如果每种语言都需要改变底层类库的话,它就很痛苦且过于复杂。所以虽然JNI能起效,但是它不提供正确的抽象层。

什么是正确的抽象层呢?每种语言,我们想支持的每种语言都有一种直接调用C代码的机制,在C#里,需要PInvoke的形式。在Ruby里是FFI,Python是ctypes,而在JAVA里,有一个很棒的库JNI(JAVA Native Architecture)。我们需要使用最常用标准来开发API,通过我们的对象模型,扁平化,使用一个简单的两三个字母前缀表示主接口方法,WD代表WebDriver,wde代表WebDriver Element。因此WebDriver.get变成了wdGet,WebElement.getText成了wdeGetText。每个方法返回一个整数的状态码,out参数用于表示允许函数返回值,我们不再使用像这样的方法签名:

int wdeGetAttribute(WebDriver*, WebElement*, const wchar_t*, StringWrapper**)

为了调用代码,WebDriver, WebElement 以及StringWrapper是不确定的类型,我们说明了API中的差异,使得更清楚应该使用什么值作为参数,尽管可以简单的使用void。因为我们想正确处理国际化文本,你也可以看到我们使用宽字符文本。

在JAVA端,我们通过一个接口公开了这个方法库,然后我们使它看起来像普通的面向对象的接口,例如,Java定义的getAttribute方法看起来像:

public String getAttribute(String name) {

PointerByReference wrapper = new PointerByReference();

int result = lib.wdeGetAttribute(

parent.getDriverPointer(), element, new WString(name), wrapper);

errors.verifyErrorCode(result, "get attribute of");

return wrapper.getValue() == null ? null : new StringWrapper(lib, wrapper).toString();

}

设计图如下:

所有的测试都在本地机上运行,这样子不错,但是一旦我们在远程WebDriver上使用IE driver时,就会随机锁定,我们跟踪过这个问题是因为IE 对COM自动化接口的限制。它们这么设计是用在单线程单元模式,本质上讲,归结到一个要求就是,我们每次在同一线程中调用这个接口。在本地运行时,默认情况就是这样。然而,Java 应用程序服务器,使用多个线程处理预期负载,结果呢?我们没有办法确保所有情况下是在同一线程里访问IE driver。

对于这个问题的解决方案是将IE driver在单线程执行器里运行,在应用程序服务器里通过Futures序列化所有访问,一段时间内我们是这样设计的。但是,似乎在调用代码中如此复杂并不公平,很容易想象这样的情形,人们一不小心从多个线程中使用IE driver,我们决定降低driver本身的复杂性。在一个单独的线程中使用IE实例使用PostThreadMessage Win32 API 跨线程边界通信,因此,在写此文时,IE driver的设计看起来像下图:

这不是我们会自愿选择的那种设计,但是它具有可工作性和避免麻烦的优点,我们用户可能会选择它。

这种设计的缺点是,它很难决定IE实例是否锁定它本身。当我们与DOM交互时如果一个对话框打开了,或者在线程边界的那一边发生了灾难性的失败,可能就出现了。因此我们发送每一个线程消息都会有一个timeout超时,我们设置为相对宽松的2分钟。从用户邮件反馈来看,这个假设大致如此,但并不正确,在IE driver更高版本里把超时时间做成了可配置的。

另一个缺点是内部调试可以深入问题,但需要快递完成(毕竟,你只有两分钟时间尽可能的跟踪代码),随后跨线程使用断点以及了解期望的代码路径。不用讲,在一个开源项目里,有很多有趣的问题需要解决,很少有食欲。这显著的降低了系统的“巴士因素”,作为项目的维护者,这让我很担心。

为了解决这个问题,越来越多的IE driver的内容移植到了相同的自动化原子如Firefox driver和Selenium Core。我们通过编译计划要使用的每个原子并准备将其作为C++头文件,每一个功能都公开成一个常量,在运行时,我们准备从这些常量中执行Javascript。这种方法意味着我们可以给IE driver开发测试一定比例的代码,而不需要C编译器,也不许更多人投入定位解决错误。最后,我们的目标只是保留原生代码中交互的API,并依赖进更多的原子。

我们正研究的另一个方法是重写IE driver来使用轻量级的HTTP 服务器,可以让我们把它当成远程WebDriver。如果发生这种情况,我们可以降低很多线程边界的复杂性,减少代码总量,让控制流易用性显著增强。

未完待续,敬请期待以后的文章:
本文是译文,原文请参考:http://www.aosabook.org/en/selenium.html

Selenium 2.0的由来及设计架构(三)相关推荐

  1. Selenium 2.0的由来及设计架构(一)

    上一篇文章介绍了Selenium1.0的历史及工作原理, 现在,接着上一次的内容说2.0的由来及设计架构. 就在Selenium1.0处于开发阶段的同时,另一款浏览器自动化框架WebDriver也正在 ...

  2. Selenium 2.0的由来及设计架构(二)

    布局和Javascript 浏览器自动化工具基本上由三部分构成: · 与DOM交互的方法 · 执行Javascript的机制 · 一些模拟用户输入的办法 本节重点介绍第一部分:提供与DOM交互的机制. ...

  3. Selenium 2.0的由来及设计架构

    本文转自:blog.csdn.net/zzzmmmkkk/article/details/10034213 布局和JavaScript 浏览器自动化工具基本上由三部分构成: · 与DOM交互的方法 · ...

  4. Re:从 0 开始的微服务架构--(三)微服务架构 API 的开发与治理--转

    原文来自:聊聊架构公众号 前面的文章中有说到微服务的通信方式,Martin Folwer 先生在他对微服务的定义中也提到"每个服务运行在其独立的进程中,服务与服务间采用 轻量级的通信机制 互 ...

  5. 基于BPMN2.0的工单系统架构设计(下)

    版权声明: 本文为博主原创文章,未经博主允许不得转载.关注公众号技术汇(ID: jishuhui_2015) 可联系到作者. 在上两篇文章中,介绍了BPMN2.0和工作流定义语言(以下简称WDL),以 ...

  6. 从0开始的微服务架构:(一)重识微服务架构

    2019独角兽企业重金招聘Python工程师标准>>> 导语 虽然已经红了很久,但是"微服务架构"正变得越来越重要,也将继续火下去. 各个公司与技术人员都在分享微 ...

  7. [转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码

    本文转自:http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html 〇.目录 一.前言 二.工具准备 三.T4代码生成预热 (一) 单文件生成:Hello ...

  8. WINCE5.0和WINCE6.0的内存与系统架构

    WINCE5.0和WINCE6.0的内存与系统架构 http://topic.csdn.net/u/20090410/14/75bba2cb-cefc-4ca5-b4f5-4165bbf16006.h ...

  9. Re:从0开始的微服务架构:(一)重识微服务架构--转

    原文地址:http://www.infoq.com/cn/articles/micro-service-architecture-from-zero?utm_source=infoq&utm_ ...

最新文章

  1. 国科大UCAS胡包钢教授《信息论与机器学习》课程第二讲:信息论基础一
  2. Agile Development
  3. animate 实现滑动切换效果
  4. python如何开启多线程_Python如何创建多线程
  5. 行走在消失中的五种编程语言
  6. OsharpNS轻量级.net core快速开发框架简明入门教程-多上下文配置(多个数据库的使用)...
  7. V模型、W模型、测试工具的介绍
  8. vrep外部控制器力矩控制实例——以matlab脚本控制平面两连杆为例
  9. 基于Spring Boot 技术的后台管理框架
  10. 抠图软件哪个好用又免费?快来看看这几款软件
  11. 水清冷冷:PS 2021 (Adobe Photoshop 2021) 安装教程和学习方法(附工具)
  12. ssm毕设项目鲲龙装饰公司在线管理系统的设计与开发前台模块iub6h(java+VUE+Mybatis+Maven+Mysql+sprnig)
  13. Springboot毕设项目vue酒店房间管理系统xukt9(java+VUE+Mybatis+Maven+Mysql)
  14. Java调用不同的打印机实现打印不同小票
  15. 征服统计学08|天天在用的P值到底是个啥?
  16. 使用str.split (“\\.“)分割文件前后缀
  17. 大数据——corejava学习笔记
  18. 1095:数1的个数(信奥)
  19. 对象数组根据多个属性排序
  20. 【好用工具推荐系列】跨平台剪贴板工具——快贴

热门文章

  1. HttpRequest接口测试
  2. History(历史)命令用法
  3. eclipse从svn检出项目
  4. 把一台Cisco路由器配置为帧中继交换机
  5. expect安装使用
  6. cc arm linux gcc,(80分请教):armcc 与 arm-elf-gcc的区别?
  7. php 数组值的交集,PHP 数组交集与差集
  8. eval语法报错 ie10_js eval 语法错误 急急急
  9. python 守护线程 join_Python多线程threading join和守护线程setDeamon原理详解
  10. c语言多线程转python多线程,真正的python 多线程!一个修饰符让你的多线程和C语言一样快...