webdriver源码简要分析

webdriver简介

webdriver,又称selenium 2.0,是selenium公司推出的一款自动化测试利器。它支持市场上几乎所有的浏览器,ie,firefox,chrome,safari等,还支持移动终端设备。

由于最近的工作涉及webdriver,所以就从google code上拉下了所有源代码,对firefox模块的实现进行了学习和探索。

webdriver架构

webdriver采用了典型的"C-S"结构,对firefox模块来说,client端是firefox driver,server端是webdriver自己开发的一个firefox extension。

firefox driver

FirefoxDriver是RemoteWebDriver的一个子类,它还包含了一个LazyCommandExecutor。

FirefoxDriver在启动时遵循以下步骤。

  1. 创建FirefoxBinary和FirefoxProfile对象,webdriver提供了足够的API来对新创建的FirefoxBinary和FirefoxProfile进行自定义,例如指定Firefox的路径,指定Firefox的Profile,更改Profile的preference等等。
  2. 建立NewProfileExtensionConnection,启动Firefox。
  3. 用HttpCommandExecutor对象开启一个新的session。

webdriver的架构图如下图所示:

webdriver wire protocol

webdriver实现了自己的一个协议。用来进行client和server之间的通信。http和json是主要使用的技术,在源码中可以发现协议的定义:

nameToUrl = ImmutableMap.<String, CommandInfo>builder()
        .put(NEW_SESSION, post("/session"))
        .put(QUIT, delete("/session/:sessionId"))
        .put(GET_CURRENT_WINDOW_HANDLE, get("/session/:sessionId/window_handle"))
        .put(GET_WINDOW_HANDLES, get("/session/:sessionId/window_handles"))
        .put(GET, post("/session/:sessionId/url"))
 
            // The Alert API is still experimental and should not be used.
        .put(GET_ALERT, get("/session/:sessionId/alert"))
        .put(DISMISS_ALERT, post("/session/:sessionId/dismiss_alert"))
        .put(ACCEPT_ALERT, post("/session/:sessionId/accept_alert"))
        .put(GET_ALERT_TEXT, get("/session/:sessionId/alert_text"))
        .put(SET_ALERT_VALUE, post("/session/:sessionId/alert_text"))

 webdriver server

webdriver server是一个firefox extension。它主要包含了两个部分:WebDriverServer, CommandProcessor。

在firefox启动之后,也就是browser.xul被gecko加载之后,

  1. webdriver会在每个新开的window上创建一个FirefoxDriver和一个DomMessenger,多个tab window共享同一个FirefoxDriver和DomMessenge。
  2. WebDriverServer启动,它会创建一个Server,用来接收client端的消息。

当收到client端的消息之后:

  1. WebDriverServer把消息交给Dispatcher进行分发,Dispatcher保存了一份webdriver wire protocol,与client端一样。
  2. Dispatcher对消息进行分析之后,交给CommandProcessor。
  3. CommandProcessor对消息进行分析之后执行,如果是webelement,则交给WebElement类处理,如果不是,则自己调用相应方法。

猜你喜欢

转载自lesliewu2008.iteye.com/blog/1733398