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

上一篇 / 下一篇  2013-07-14 18:51:26 / 个人分类:功能自动化

上一篇文章介绍了Selenium1.0的历史及工作原理, 现在,接着上一次的内容说2.0的由来及设计架构

就在Selenium1.0处于开发阶段的同时,另一款浏览器自动化框架WebDriver也正在ThoughtWorks公司的酝酿之中。WebDriver项目的初衷是把端对端测试与底层测试工具隔离开。通常情况下,这种隔离手段通过适配器(Adapter)模式完成。WebDriver正是来源于该方法在许多项目上的不断实践应用,最初是HtmlUnit的封装,工具发布后很快开始支持Internet ExplorerFirefoxWebDriver的最初代码在2007年初发布。

WebDriver最初发布时,与Selenium RC存在显著差异,尽管它们都属于浏览器自动化的API工具。对于用户来说,最明显的区别在于Selenium RC提供基于字典的API,所有方法都在一个类中开放,而WebDriverAPI更面向对象。此外,WebDriver仅支持Java,而Selenium RC提供广泛的语言支持。技术差异也很明显:Selenium CoreRC的基础)基本上是JavaScript应用,运行在浏览器的安全沙箱之内。WebDriver则尝试原生绑定到浏览器中,绕开了浏览器的安全模型,代价就是框架自身的开发投入显著增加。

20098月,两个项目宣布合并,Selenium WebDriver就是合并的成果。

WebDriver的创建者Simon Stewart早在20098月的一份邮件中解释了项目合并的原因:

为何把两个项目合并?部分原因是WebDriver解决了Selenium存在的缺点(比如,能够绕过JS沙箱。我们有出色的API),部分原因是Selenium解决了WebDriver存在的问题(例如支持广泛的浏览器),部分原因是因为Selenium的主要贡献者和我都觉得合并项目是为用户提供最优秀框架的最佳途径。

目前,WebDriver支持的语言绑定包括JavaC#PythonRuby。它支持ChromeFirefoxOpera移动AndroidiPhone浏览器。此外,还有其他关联项目,不在同一源代码库中维护,但是和主项目(Selenium WebDriver)紧密合作,例如提供Perl绑定支持、BlackBerry浏览器支持,以及“无头”WebKit——用于持续集成的测试其无法正常显示的情况。最初的Selenium RC机制仍然维持,帮助WebDriver在浏览器不受支持的情况下提供支持。

在两个项目合并中出现了哪些架构方面的问题?学到了哪些经验和教训?Simon Stewart在《The Architecture of Open Source Applications》一文中做了详细的描述,本文参考了以下内容:

http://www.aosabook.org/en/selenium.html

http://www.infoq.com/cn/news/2011/07/selenium-arch-2

处理复杂性

软件是模块构造起来的。这些模块很复杂,作为API的设计人员们,可以选择如何处理这种复杂性。极端情况下,可能会传播这种复杂性,这意味着API的每一位用户都需要牵涉其中。另一个极端情况是承担尽可能多的复杂性并将其隔离在某个地方。这个地方对于许多想一探究竟的API用户来说黑暗而恐怖。折中方案则是API的用户,如果无须深入了解实现细节,那么只需面对当前所遇到的复杂性即可。

WebDriver的开发人员更倾向于发现并在少数地方隔离这些复杂性,而不是传播它。这么做的原因之一是为用户着想。看看bug列表就会知道,他们特别善于发现问题和缺陷,但是因为许多用户不是开发人员,复杂的API不会受欢迎。开发人员试图让API正确地引导大家。例如,考虑下面来自早期Selenium API的方法,每一个都用于设置输入元素的值:

       type

       typeKeys

       typeKeysNative

       keydown

       keypress

       keyup

       keydownNative

       keypressNative

       keyupNative

       attachFile

下面是WebDriver API中的等价方法:

       sendKeys

如前所述,这凸显了RCWebDriver之间的主要思想差异——WebDriver在努力模拟用户,而RC在较低层次提供的API让用户难以或者无法使用。typeKeystypeKeysNative之间的区别在于前者总是使用合成事件(synthetic event),而后者则尝试利用AWT Robot输入键值。令人失望的是,AWT Robot发送按键事件给具有焦点的任意窗口,也就是说可能不是浏览器。相比之下,WebDriver的原生事件,直接把事件发送给窗口处理函数,避免了浏览器窗口必须具有焦点的要求。

WebDriver设计

WebDriverAPI被定位为“基于对象的”。接口被明确定义并努力坚持只包含一个角色或者责任,而不是将每一个可能的HTML标记模块化为单独的类,只有一个WebElement接口。通过这种方式,开发人员使用支持自动补全的IDE即可被提示下一步工作。其结果类似于下面的代码片段(Java语言):

WebDriver driver = new FirefoxDriver();

driver.<user hits space>

此时,包含13个方法的短列表显示出来,用户选择其中一个:

driver.findElement(<user hits space>)

大多数IDE现在显示预期参数的类型提示,在这个例子中是“By”。By包含许多预定义的静态工厂方法,用户可以快速地完成刚才的代码:

driver.findElement(By.id("some_id"));

基于角色的接口

WebDriver广泛使用了基于角色的接口。例如,有一个JavascriptExecutor接口提供了在当前页面环境中执行任意Javascript语句块的功能。WebDriver实例对该接口的成功映射可以提示你利用该方法完成自己的工作。

处理大量的组合

假设X种浏览器和Y种语言,我们很容易就会掉进X×Y种实现中,将会面临维护成本的大量攀升。

减少WebDriver支持的编程语言种类是降低成本的途径之一,但是基于两种原因不想这样做。首先,从一种语言切换到另一种时人们会承受认知负荷,因此对用户来说如果测试框架(WebDriver)能够允许他们采用在日常开发中使用的编程语言来编写测试,那么这是巨大的优势。其次,在单一项目中混合多种语言可能会让团队很不方便,而且公司的编码规范和需求通常要求技术单一纯正性,因此,减少支持语言的种类不是可选项。

减少支持浏览器的数量也不是一种选择——当项目组决定在WebDriver中淘汰对Firefox 2的支持时,就遇到了强烈的抗议,而事实上当时,Firefox 2只占了浏览器市场份额不到1%

唯一的选择是努力使所有浏览器对语言的绑定看起来相同:它们应该提供统一的接口,可以轻松地通过各种语言解决。更重要的是,希望语言绑定本身尽可能的易于编写,这意味着需要尽可能的使它们保持简洁。在底层driver中放入了尽可能多的逻辑来支持这种设计:放弃放入dirver的每一块功能都意味着需要通过支持的每一种语言实现,而这代表了大量的工作量。

WebDriver设计中的缺陷

通过这种方式发布功能的缺陷在于除非有人知道某个特定的接口存在,否则他们可能不会意识到WebDriver支持这种功能,在API的可发掘性上存在缺憾。当然在WebDriver刚发布的时候,我们会投入大量时间来指导人们找到合适的接口。现在我们已经花费大量精力来编写文档,随着API获得广泛应用,用户会越来越容易的找到所需的文档。

从实现者的观点来看,紧密绑定浏览器也是一种设计缺陷,虽然无法避免。支持新浏览器时需要投入巨大的努力,经常需要数次尝试才能找到正确方法。具体的例子就是,Chrome驱动经过了四次完全重写,IE驱动也有三种关键重写。紧密绑定浏览器的优点在于它提供了更多控制权。

 下面几篇文章我会把WebDriver的创建者Simon Stewart介绍的余下内容翻译完,包括以下内容:

1.布局及JavaScript

2.特别介绍RemoteFirefox driver

3. IE driver

4. Selenium RC

5.回顾

6.展望未来

请阅读后面的:

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

Selenium 2.0的由来及设计架构(三)

Selenium 2.0的由来及设计架构(四)

本文是译文,原文请参考:http://www.aosabook.org/en/selenium.html

===========================

关注微信zzzmmmkkk,不定期吐槽有关测试技术,测试经验,测试思考和生活感悟等。


TAG: 设计架构 Selenium selenium webdriver WebDriver

 

评分:0

我来说两句

Open Toolbar