关于事物如何形成的思考

主要对 Selenium 开发人员感兴趣的关于项目某些部分如何以及为何被创建的详细信息

此文档之前位于 wiki

引言

这是一项正在进行的工作。欢迎添加您知道或记得的事情。

自动化原子是如何产生的?

在 2012-04-04,jimevans 在 #selenium IRC 频道上问道

“我想问你的是关于自动化原子的历史。我记得它们像是从宙斯的头脑中完全成型一样突然出现,我确信事实并非如此。你能帮我回忆一下这个概念是如何产生的吗?”

然后 simonstewart 向我们讲述了一个有趣的小故事

当然。我们坐好了吗?那么我就开始了。(英国笑话,那里)

想象一下波浪线,屏幕溶解,我们被带回到 selenium 和 webdriver 是不同项目的时候。在项目合并之前,webdriver 中有大量一致的代码。一致,但没有共享。Firefox 驱动程序是 JS 写的。IE 驱动程序主要是 C++ 写的。Chrome 驱动程序主要是 JS 写的,但与 Firefox 驱动程序中的 JS 不同。而 HtmlUnit 是独一无二的。

然后我们将 Selenium Core 添加到其中。更多的 JS 执行着基本相同的事情。

在 Google 内部,我逐渐成为浏览器自动化团队的 TL。并将我们自己的一个框架整合到其中。该框架是用 JS 编写的,并且曾经基于 Core,然后自行发展。

因此:多个代码库,大量的 JS 执行着或多或少相同的事情。并且存在大量错误。边缘情况下行为的奇怪不匹配。

*颤抖*

所以我想了一下。(很危险,我知道)想法是从所有三个框架(Core、WebDriver 和 Google 工具)中提取“最好的”代码。将它们分解成可以共享的代码。“浏览器自动化的最小、不可分割的单元”。

或者简称为“原子”。

这些可以用作一切的基础。浏览器和 API 之间的一致行为。另一个重要的点是,webdriver 和 core 中的 JS 代码是有机增长的。这是一种礼貌的说法,意思是“我宁愿再也不编辑它了”。这是一种礼貌的说法,意思是它的质量可疑。在某些地方。

因此:高质量很重要。我希望将代码分解为模块。因为编辑一个 10k LOC 的文件不是一个好主意。

在 Google 内部,我们有一个名为 Closure 的库。它不仅允许模块化,还允许通过编译将模块“反规范化”为一个文件。而且我知道它正在开源。所以我们开始在 google 代码库中构建该库。(在那里我们可以访问未发布的库、代码审查工具和我们出色的测试基础设施)。使用 Closure Library。

“dom.js”可能是我写的第一个文件。(我们可以检查)。Greg Dennis 和 Jason Leyba 也加入了进来。自那时起,原子一直在增长。

从技术上讲,我们应该将“javascript/atoms”之外的任何东西都称为分子。但是那样我们就不能说我们有原子驱动程序。并使用 50 年代的图像来描述它们。

*叹息*

jimevans 回复说:“分子驱动程序?”

simonstewart 最后说

确实 :) 这个想法是原子是最低级别的。我们在“javascript/{selenium,webdriver}-atoms”中分别组合原子以符合 WebDriver 或 RC API。然后根据需要吸入这些。

一个关于疯狂乐趣的故事

Simon Stewart

那么,让我们回到项目的最初

当时只有我一个人
(即 webdriver 项目,而不是 selenium 本身)
我知道我想覆盖多种不同的语言,因此我想要一个可以与所有语言一起工作的构建工具
也就是说,该工具没有对一种语言的内置偏好,从而使使用其他语言变得痛苦
ant 偏向 Java。maven 也是如此。
nant 和 msbuild 偏向 .net
另一方面,rake 对任何语言的支持都不太好
但是,关键是,任何有效的 rake 脚本也是一个有效的 ruby 程序
可以扩展 rake 来构建任何东西
因此:选择了 rake
最初的 rake 文件非常小且易于管理
但是随着项目的增长,Rakefile 也随之增长
直到只有一个人(我)能够处理它,即使这样也很不稳定
因此,为了避免项目无法构建,我提取了一些辅助方法来完成一些繁重的工作
这使 Rakefile 再次变得易于理解
但是项目一直在。变大。
而 Rakefile 变得越来越难以理解
当时,我在 Google 工作,他们有一个很棒的构建系统
Google 的系统是声明式的,并且在多种不同的语言中都能一致地工作
而且,最重要的是,它将构建从单个文件分解为小片段
我询问了 Google 的 OSS 人员是否可以开源构建语法,他们开了绿灯
因此,我们将该构建语法分层到 selenium 代码库中
进行了一个小小的更改(我们处理字典参数)
但是那个语法位于 rake 之上
经过这么长时间仍然如此
并且存在一个问题
那就是 rake 是单线程的
因此,我们的构建被限制为串行运行
我们可以使用“multitask”类型来改进,但是当我尝试这样做时,事情很快变得非常混乱
因此,我们的下一个障碍是 crazyfun.rb 速度慢:我们需要更快
这意味着需要重写 crazyfun
我最擅长 java
因此,我用 java 试用了一个新版本,该版本可以处理 java 和 js 的编译
速度明显更快
但是,这一点也很重要,它是一个试用品
该代码被设计为可丢弃的。
既然事情已经证明了,我真的很想做一个干净的实现
但是我犹豫了
我是否应该“完成”这个新的、速度非常快的 crazyfun java,使其足以取代 ruby 版本?

关于驱动程序可执行文件的故事


jimevans
noob_einsteinsfo:好了,讲故事时间到了。我们坐好了吗?那么我们就开始了。
noob_einsteinsfo:记得我刚开始参与这个项目的时候(大约在 2010 年),所有浏览器的驱动程序都是由项目组构建和维护的。
当时,这意味着 IE、Firefox 和 Chrome。
所有这些驱动程序都打包在 Selenium 独立服务器中,并且也打包在各种语言绑定中。
这是一个有意识的决定,这样如果用户在本地运行,就不需要在机器上安装 Java 运行时环境来自动化特定的浏览器。
有两个因素导致了浏览器驱动程序作为单独的可执行文件进行开发。
顺便提一下,请记住 WebDriver 的理念是使用适用于特定浏览器的“最佳拟合”机制来自动化浏览器。
对于 IE,这意味着使用 COM 接口;对于当时的 Firefox,这意味着使用浏览器扩展;对于 Chrome,也意味着使用浏览器扩展。
因此,IE 驱动程序被开发为一个 C++ 中的 DLL,由语言绑定加载,并通过语言提供的任何本机代码机制(Java 的 JNI,.NET 的 P/Invoke,Python 的 ctypes 等)进行通信。
这也意味着 Firefox 驱动程序被开发为浏览器扩展,打包在各种语言绑定中,并被提取出来,在 Firefox 的配置文件中使用。
正如我所说,IE 驱动程序被实现为一个 DLL,使用不同的机制加载并与不同的语言绑定通信。
问题在于,每种特定于语言的机制都具有不同的加载/卸载语义。
例如,Ruby 在将 DLL 加载到内存后,永远不会调用 Windows 的 FreeLibrary API,这使得多个实例的运行变得非常具有挑战性。
然而,*进程*语义,即在操作系统上启动、停止和管理进程的生命周期,无论操作系统是什么,在所有语言中都非常相似。
因此,当 2010 年完成 IE 驱动程序重写时,开发团队(我)决定将其设为一个单独的可执行文件,以便加载/卸载语义在无论使用哪种语言绑定时都保持一致。
与此同时,Chromium 团队决定效仿 Opera,为 Chrome 提供驱动程序实现。
这个实现将由他们开发、增强和维护,从而减轻 Selenium 项目维护 Chrome 驱动程序的负担。

XgizmoX
并且这个驱动程序是浏览器的一部分吗?

jimevans
XgizmoX:不完全是,但我相信 Chrome 本身可能内置了一些智能,可以知道它何时通过 ChromeDriver 进行自动化。关于这个问题,问谷歌的人会更好。
无论如何,考虑到共享库(.dll/.so/.dynlib)加载语义的不同,Chromium 团队(在我的鼓励下)决定将其 ChromeDriver 实现作为单独的可执行文件发布。
快进几年,你开始看到将 WebDriver 标准化的努力,成为 W3C 标准。
W3C 的一个工作组创建了一个规范(仍在进行中,但第一版即将完成),该规范编纂了 WebDriver 的行为,以及浏览器应该如何对其方法做出反应。此外,它还标准化了用于在语言绑定和特定浏览器的驱动程序之间进行通信的协议。
我无法强调这有多么重要和具有开创性。
因为 W3C 和其内部的 WebDriver 工作组由浏览器供应商本身的代表组成,这确保了解决方案将直接得到浏览器供应商的支持。
Mozilla 为 Firefox 创建了他们的 WebDriver 实现(GeckoDriver)。
在保持语言绑定的正确语义的同时,分发该浏览器驱动程序的最有效机制是作为单独的可执行文件发布。
请注意,这只是对 GeckoDriver 架构的粗略简化;实际的可执行文件充当一个相对较薄的垫片,将规范的线路协议转换为其内部的 Marionette 协议
但重点仍然存在。
无论如何,目前浏览器供应商提供的驱动程序实现格局正在不断演变。微软为 Edge 提供了一个,苹果为 Safari(10 及以上版本)提供了一个,Chromium 团队(主要由谷歌员工组成)为 Chrome 提供了一个,现在 Mozilla 为 Firefox 提供了一个。
考虑到旧版 Firefox 驱动程序未来的有限用途,将其分解为单独的可执行文件将是浪费精力。
尤其是,通常由可执行文件处理的所有通信部分(侦听和响应来自语言绑定的 HTTP 请求)都完全由浏览器扩展处理。\
实际上,旧版 Firefox 驱动程序没有必要成为一个单独的可执行文件。
此外,使其独立于语言运行时环境将需要大量的工作
(因为 .NET 公司可能会合理地反对仅仅为了自动化 Firefox 而需要安装 Java 运行时环境)
所以从历史上看,noob-einsteinsfo,这就是为什么单独的可执行文件已成为常态的普遍原因,以及为什么这种模式没有扩展到包括旧版 Firefox 驱动程序的原因。
这能理解吗?
好的。
现在。
关于 GeckoDriver。
GeckoDriver 的故事与上述 W3C WebDriver 规范的状态密切相关。
规范的第 1 级大部分已完成,尽管花了数年的努力才达到这一点。
一些非常聪明的人(其中包括 AutomatedTester)付出了巨大的努力,将 WebDriver 开源软件 (OSS) 项目的初始文档转化为适当的规范语言,以便浏览器供应商或其他实现者可以解释并将其转化为可操作的东西。
在开始 GeckoDriver(以前的 Marionette)项目时,Mozilla 决定将其实现基于规范,并且仅基于规范,而不遵循 OSS 实现。
这造成了一个鸡生蛋蛋生鸡的问题,因为在规范语言未完成时,它无法实现。
仅仅在过去的六个月左右,关于高级用户交互 API(Java 和 .NET 中的 Actions 类)的语言才变得足够健壮,足以实际实现。
因此,这是目前 GeckoDriver 中最大的缺失功能。它无法通过规范实现,因此尚未实现。
我知道 AutomatedTester 和他的团队非常重视完成该实现并使其可用。
至于为什么 GeckoDriver 是强制性的,并且是 3.x 中自动化 Firefox 的默认实现,这也归结为 Mozilla 做出的一些决定。

TheSchaf
所以我猜,只要缺少所需的功能,就只能使用旧版 FF
WhereIsMySpoon
TheSchaf:如果你需要这些功能,是的
或者使用其他浏览器
TheSchaf
嗯,moveTo 和 sendKeys 应该是非常基础的功能 :p

jimevans
TheSchaf:element.sendKeys 工作正常。只有 Actions.sendKeys 会中断。
在 Firefox 的四十多个版本(我记不清确切的版本)中,添加了一个功能,该功能阻止了未经过 Mozilla 安全团队签名的浏览器扩展。
还记得旧版 Firefox 驱动程序是作为浏览器扩展构建的吗?嗯,启用浏览器的该功能后,浏览器无法加载旧版驱动程序。
现在,对于 Firefox 的几个版本,可以禁用浏览器的此功能,并允许继续加载未签名的扩展。
而 Selenium 通过在启动 Firefox 时创建的匿名配置文件中使用的设置做到了这一点。
直到 Firefox 48,此时不再可能禁用加载未签名的扩展。
那时,GeckoDriver 是唯一的出路。
现在,还有两个小问题,然后我就讲完故事了。
首先,由于旧版驱动程序扩展的本质,它不可能通过 Mozilla 安全团队的认证流程。
我们问了,被拒绝了,并被告知永远不会发生,彻底没戏。
这是完全合理的,因为该扩展所做的事情是一个足够大的安全漏洞,可以容纳整个卡车车队通过。
其次,事实证明,可能实际上有一种方法可以私下签署旧版扩展,以便 Firefox 48 及更高版本可以加载和私下使用它。
但这仍然不是一个理想的方法,因为我们这群快乐的开源开发人员无法知道如何比 Mozilla 的开发团队(他们首先创建了浏览器)更好地自动化 Firefox。
我完全理解 GeckoDriver 不具备旧版实现的完整功能对等性所带来的挫败感,尤其是在感觉被强迫迁移到它时。
因为这个决定而对 Selenium 项目大发雷霆是完全找错了方向。
但是,在开始说 Mozilla 的决定有多么糟糕之前,请知道 Mozilla 有几个人不断参与该项目,其中一些人就在这个频道中(AutomatedTester,davehunt,仅举两个)。
我确信我遗漏或误述了这些事情的一些历史细节,我很乐意被纠正。毕竟我老了,记忆力不如以前了。
但是,我的朋友们,这就是(不太)简短的历史,解释了为什么我们有单独的驱动程序可执行文件,以及为什么 GeckoDriver 是未来的方向,以及为什么在做出迁移时,即使缺少某些功能,也必须迁移到它。

jimevans 感觉自己已经成为 WebDriver 项目的非官方历史学家


文字记录:https://botbot.me/freenode/selenium/2016-12-21/?msg=78265715&page=6

我们发布的非正式命名(按 IRC 中的频道主题)

  • Selenium 2 beta 3 '下一代浏览器版本' 现已推出 - http://bit.ly/i9bkC2

  • Selenium 2 RC1 '网格版本' 现已推出 - http://bit.ly/jgZxW8

  • Selenium 2 RC2 '运行更好版本' 现已推出 - http://bit.ly/mJJX1z

  • Selenium RC3 - “下一个是‘大’版本” - http://bit.ly/kpiACx

  • Selenium 2.0 最终版发布到毫无戒心的群众中

  • Selenium 2.1.0 现已推出(是的,现在甚至适用于 Maven 用户)

  • Selenium 2.2.0 现已推出(在 NuGet 中 .. 是的,甚至适用于 Maven)

  • Selenium 2.3.0 现已推出。新传统!

  • Selenium 2.4.0 已发布 - 内容已更改,但尚无博客文章

  • Selenium 2.5.0。嗯。培根。

  • Selenium 2.6.0 现已推出。切换并节省 15% 或更多的汽车保险

  • Selenium 2.7.0 的 Ruby 绑定率先推出(无论如何都在 Twitter 上)。Jari 简直是台机器……

  • Selenium 2.8.0 现已推出 - 一天的培根仍然是培根

  • 遗憾的是,我们缺少 IRC 日志…

  • Selenium 2.22:历时一个月的每周发布终于来了!

  • Selenium 2.23:“现在太棒了!”等等。什么?现在?!

  • Selenium 2.24:现在有了更多,嗯,东西?

  • Selenium 2.25:进展顺利

  • 2.26 发布了!

  • Selenium 2.27 已发布,修复了 Firefox 17 的问题。趁热获取!

  • (没有 2.28 的主题更新)code.google.com/p/selenium 镜像到了 github.com/seleniumHQ/selenium - 我们现在使用 git 了!

  • 2.29.0 现在发布了!首个支持 FF18 的 git 版本!

  • 轰!2.31 发布了,甚至支持 Firefox 19 的原生事件。

  • “相关性并不意味着因果关系” 2.32.0 发布,支持 Firefox 20。

  • 美国政府重新开放了!让我们用新发布的 2.36 来庆祝,它支持 FF24

  • 2.40 哇,好多自动化,修复了很多问题,真是太棒了

  • 2.41 - 最后一个“支持”IE6 的版本

  • 2.45.0 - 发布,支持 FF36

  • 2.46.0 - 发布,支持 FF38

  • 2.47.0 - 发布,支持 Edge

  • 2.48.0 - 发布,所有语言都支持 Marionette

  • 2.49.0 发布 - 支持 FF 43

  • 2.50.0 发布 - “全是该死的边缘情况!” - D.W-H

  • 2.51.0 发布 - “全是该死的边缘情况!” - D.W-H

  • 2.52.0 发布 - 现在你可以禁用“所有该死的边缘情况”了!

  • 2.53.0 最终 RC 版本

  • 3.0 圣诞节发布!FF48 现在需要 GeckoDriver

  • 3.6 “不是在周五发布”的版本

最后修改于 2022 年 1 月 10 日:更多 wiki (#907) [部署站点] (adcf706a1ad)