浅析自动化测试中的WebDriver

   在日常自动化测试中,使用频率最高的工具应该就是Selenium(Web端的自动化)和Appium(App端的自动化)。每天与它们形影相随,但是你真的了解它们吗?

一、认识

在了解他们之前,先来看看两个故事:

(1) Selenium的故事

  • 2004年:Jason Huggins发起了Selenium项目,发布了Selenium 1.0,该版本包含Selenium RC模块

  • 2006年:SimonStewart发起了WebDriver的项目,竞争者是Selenium RC

  • 2011年:合并了Selenium1.0和WebDriver,发布了Selenium 2.0

  • 2016年:发布了Selenium3.0,该版本彻底移出了Selenium RC

(2) Appium的故事

  • 2011年:Dan Cuellar发起了IOSAuto项目

  • 2012年:Jason Huggins接触到了IOSAuto项目并给Dan Cuellar一些建议,此后IOSAuto更名为Appium

  • 2014年:Appium发布了1.0版本,在Appium中扩展了Webdriver协议

    在上面的两个故事中我们发现了存在同一个人,即Selenium的创始人Jason Huggins。得益于他的影响和推动,所以Appium和Selenium两个项目也产生联系,即都使用WebDriver操作页面。

    WebDriver操作页面时使用的是浏览器原生API,因此速度和调用稳定性大大提高。然而不同浏览器对Web元素的操作和呈现多少会有一些差异,这就直接导致了WebDriver要分浏览器厂商不同而提供不同的实现。如Firefox有专门的FirefoxDriver,Chrome有专门的ChromeDriver。

二、理解

WebDriver Wire Protocol是W3C的标准(由Selenium主持)。各种浏览器的对应WebDriver均是基于该协议的具体实现,各种WebDriver启动之后都会在某一个端口启动基于这套协议的Web Service。Selenium和Appium与WebDriver通信协议是WebDriver Wire Protocol中定义的JSONWP。

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。

JSONWP(JSON wire protocol)是一种通信协议。这个通信协议是个预定义的特殊设置,通过RESTful API暴露标准端口。WebDriver接收到JSONWP格式的信息后执行网站自动化测试。

MJSONWP(Mobile JSON Wire Protocol)是一种通信协议。该协议不单基于JSONWP,而且扩展实现了移动端的控制行为。 从这一点可以推出Appium扩展了WebDriver Wire Protocol。

Selenium和Appium都是基于WebDriver进行操作的,因此这里Selenium为例进行说明。

2.1 架构

执行是通过WebDriver执行的,其可以总结为有两类功能(也是通常service的功能):接送和执行

   1>Service接收请求翻译为命令和返回命令结果

   2>Service将翻译后的命令对浏览器进行执行

请求是通过HttpClient执行的,在请求的body中存放以协议规定的JSON字符串命令,以便于来告诉浏览器接下来做什么事情。Client中会使用一个WebElement(代表页面上的一个DOM元素)对象进行操作。

CommandExecutor里面维护了一个Map,它负责将代表命令的简单字符串key转化为相应的URL(因为REST的理念是将所有的操作视作一个个状态,每一个状态对应一个URI)。所以当以特定的URL发送给Service之后,它就能解析出需要执行的操作。这里摘出来一段代码:

nameToUrl = ImmutableMap.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”))

2.2 流程

WebDriver driver = newChromeDriver();

driver.get(“http://www.google.com”);

三者(Client\Service\Browser)之间身份认证是通过sessionid来确认。session产生在Client,由Service进行维护(在请求和响应中包含了sessionid),使用于Browser。

在new一个WebDriver的过程中会在新线程中启动Service。

1.Client执行get函数会发送如下请求数据:POSTsession/285b12e4-2b8a-4fe6-90e1-c35cba245956/url和post_data{“url”:“http://google.com”}

2.Server收到请求后翻译给Browser处理,然后将响应后翻译给Client处理

3.Client会接收到如下响应{“sessionId”:“285b12e4-2b8a-4fe6-90e1-c35cba245956”,“name”:“get”,“status”:0,“value”:“”}

4.sessionId:当前session的id

5.name:Server端的实现的方法的名称,这里get表示跳转到指定url

6.status:请求执行的状态码,非0表示未正确执行

7.value:请求的返回值。不同的Client调用函数返回形式不一样


Q



本文转载自 360质量效能