selenium及webdriver的原理

主要内容转自:http://blog.csdn.net/ant_ren/article/details/7968582http://blog.csdn.net/ant_ren/article/details/7970793

selenium与webdriver整合后,形成的新的测试工具叫做selenium2.x。在selenium1时间,selenium使用javascript来达到测试自动化的目标。

1. selenium RC

早期的Selenium使用的是Javascript注入技术与浏览器打交道, 需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段 Javascript。开发过Web应用的人都知道,Javascript可以获取并调用页面的任何元素,自如的进行操作。由此才实现了Selenium 的目的:自动化Web操作。这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的 Javascript质量高低。

启动Selenium Server以及RC至今为止还保留着,应该是考虑到向前兼容吧,命令如下:

[plain] view plaincopyprint?

  1. java -jar selenium-server-standalone-2.14.0.jar -role hub
  2. java -jar selenium-server-standalone-2.14.0.jar -role node  -hub http://localhost:4444/grid/register

2. WebDriver

当Selenium2.x 提出了WebDriver的概念之后,它提供了完全另外的一种方式与浏览器交互。那就是利用浏览器原生的API,封装成一套更加面向对象的 Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)。由于使用的是浏览器原生的API, 速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学。然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有 一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。例如Firefox就有专门的FirefoxDriver,Chrome就有专门的 ChromeDriver等等。(甚至包括了AndroidDriver和iOS WebDriver)

引用一句个人赞同的原文:如果你使用的是WebDriver,你就可以直接抛弃Selenium Server。因为你根本不需要启动一个服务器来处理浏览器交互。

一个简答的使用WebDriver的例子:

    static{System.setProperty("webdriver.firefox.bin","C:/Program Files (x86)/Mozilla Firefox/firefox.exe");}
    FirefoxDriver driver = new FirefoxDriver();
    String url = "http://ap13933:8080";
    driver.manage().window().setSize(new Dimension(1440,1000));
    driver.get(url);  

    WebElement name = driver.findElement(By.id("UserName"));
    WebElement pwd = driver.findElement(By.id("OldPassword"));
    while(!name.isDisplayed() || !pwd.isDisplayed())
        sleep(100);  

    name.clear();
    pwd.clear();
    name.sendKeys(username);
    pwd.sendKeys(password);
    pwd.submit();  

WebDriver Wire协议是通用的,也就是说不管是FirefoxDriver还是ChromeDriver,启动之后都会在某一个端口启动基于这套协议的Web Service。例如FirefoxDriver初始化成功之后,默认会从http://localhost:7055开始,而ChromeDriver 则大概是http://localhost:46350之类的。接下来,我们调用WebDriver的任何API,都需要借助一个 ComandExecutor发送一个命令,实际上是一个HTTP request给监听端口上的Web Service。在我们的HTTP request的body中,会以WebDriver Wire协议规定的JSON格式的字符串来告诉Selenium我们希望浏览器接下来做社么事情。

在我们new一个WebDriver的过程中,Selenium首先会确认浏览器的native component是否存在可用而且版本匹配。接着就在目标浏览器里启动一整套Web Service,这套Web Service使用了Selenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol。这套协议非常之强大,几乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、上传文件等等等等。

这里笔者初步画了一个图来表示各种WebDriver的工作原理:

从上图中我们可以看出,不同浏览器的WebDriver子类,都需要依赖特定的浏览器原生组件,例如Firefox就需要一个add- on名字叫webdriver.xpi。而IE的话就需要用到一个dll文件来转化Web Service的命令为浏览器native的调用。另外,图中还标明了WebDriver Wire协议是一套基于RESTful的web service。如果不明白什么是RESTful的,可以参见笔者之前另外一篇介绍REST的blog(http://blog.csdn.net/ant_yan/article/details/7963517)

关于WebDriver Wire协议的细节,比如希望了解这套Web Service能够做哪些事情,可以阅读Selenium官方的协议文档, 在Selenium的源码中,我们可以找到一个HttpCommandExecutor这个类,里面维护了一个Map<String, CommandInfo>,它负责将一个个代表命令的简单字符串key,转化为相应的URL,因为REST的理念是将所有的操作视作一个个状态,每 一个状态对应一个URI。所以当我们以特定的URL发送HTTP request给这个RESTful web service之后,它就能解析出需要执行的操作。截取一段源码如下:

    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"))  

可以看到实际发送的URL都是相对路径,后缀多以/session/:sessionId开头,这也意味着WebDriver每次启动 浏览器都会分配一个独立的sessionId,多线程并行的时候彼此之间不会有冲突和干扰。例如我们最常用的一个WebDriver的 API,getWebElement在这里就会转化为/session/:sessionId/element这个URL,然后在发出的HTTP request body内再附上具体的参数比如by ID还是CSS还是Xpath,各自的值又是什么。收到并执行了这个操作之后,也会回复一个HTTP response。内容也是JSON,会返回找到的WebElement的各种细节,比如text、CSS selector、tag name、class name等等。以下是解析我们说的HTTP response的代码片段:

    try {
            response = new JsonToBeanConverter().convert(Response.class, responseAsText);
          } catch (ClassCastException e) {
            if (responseAsText != null && "".equals(responseAsText)) {
              // The remote server has died, but has already set some headers.
              // Normally this occurs when the final window of the firefox driver
              // is closed on OS X. Return null, as the return value _should_ be
              // being ignored. This is not an elegant solution.
              return null;
            }
            throw new WebDriverException("Cannot convert text to response: " + responseAsText, e);
          } //...  

相信总结道这里,应该对WebDriver的运行原理应该清楚了!其实挺佩服这一套RESTful web service的设计。感觉封装WebDriver暴露出来的public API还可以更加友好跟强大一点,这次就先总结道这里,会继续分析Selenium源码,继续分享的!

3. 使用selenium2.x的经验总结

其中WebDriver的更加面向对象的方式大大降低了Selenium的入门门槛,对Web元素的操作也非常之简单易 学。实际项目用起来,工作量最大的部分就是你如何解析定位到你的目标项目页面中的各种元素。好比你要定位一个Button,你可以用ID,可以用CSS, 可以用XPATH,你为了点击这个Button,写了一个函数调用Selenium里的API,即WebElement里的click()或者 submit(),那么另外一个Button怎么办?成百上千个Button又怎么办?

所以,你需要有一套自己实现的算法或者封装,来根据项目页面的特点提供一套通用的元素定位方式。当你的通用定位逻辑能准确 的找到任何一个元素的时候,剩下的事情就顺理成章了,交给Selenium WebElement的API就可以了。这一套定位逻辑笔者觉得才是使用Selenium做Web自动化工作量最大的部分。当然有的公司Web项目使用了 自己开发的UI框架,例如笔者所在的公司,这样Web元素的定位规则和算法就比较容易设计。如果Web项目开发出来的页面代码比较杂乱无章,那么你就需要 更加高明和严谨的逻辑去寻找你想要操作和查看的元素了!

在笔者的项目里,笔者自己设计并封装了一套通用的API,去智能的定位页面中的各种类型的元素。比如项目里的页面有大量的 dialog和wizard,都是用div+css实现的。我就提供了一个dialog组件,带有 next(),save(),finish(),click(String buttonName),cancel()等方法,然后根据遮罩层和loading Icon的时间来追踪操作完成的进度。这里只是举个小小的例子,有机会再分享更多的细节。

时间: 2024-08-14 19:59:42

selenium及webdriver的原理的相关文章

selenium工作的大概原理

selenium的原理是什么? selenium的原理涉及到3个部分,分别是 浏览器 driver: 一般我们都会下载driver client: 也就是我们写的代码 client其实并不知道浏览器是怎么工作的,但是driver知道,在selenium启动以后,driver其实充当了服务器的角色,跟client和浏览器通信,client根据webdriver协议发送请求给driver,driver解析请求,并在浏览器上执行相应的操作,并把执行结果返回给client.这就是selenium工作的大

selenium之WebDriver API

自动化只要掌握四步操作:获取元素,操作元素,获取返回结果,断言(返回结果与期望结果是否一致),最后自动出测试报告,元素定位在这四个环节中是至关重要的,如果说按学习精力分配的话,元素定位占70%:操作元素10%,获取返回结果10%:断言10%.如果一个页面上的元素不能被定位到,那后面的操作就无法继续了.而WebDriver 属于Selenium体系设计出来操作浏览器的一套API,它支持多种语言,Selenium WebDriver只是python的一个第三方框架,也就是说是一个实现web自动化的第

软件测试之Selenium Java WebDriver

编写Selenium Java WebDriver程序,测试inputgit.csv表格中的学号和git地址的对应关系 package selenium2; import java.util.regex.Pattern; import java.util.concurrent.TimeUnit; import org.junit.*; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import o

Selenium Java WebDriver 使用

一. Firefox安装Selenium插件 在FireFox的菜单中的附加组件中搜索Selenium IDE 然后安装 二. 使用Selenium IDE录制脚本/导出脚本 点击图中标志打开Selenium IDE 红色按钮按下表示正在录制,这时候只用将界面切换到Firefox,网址中输入www.baidu.com,然后再搜索框中输入文字,点击搜索,所有的控件的访问都会被记录下来,然后切换回seleniumIDE就可以看到已经录制完毕 然后在图中红色选中的区域可以调整重新执行的速度,蓝色选中区

How to set Selenium Python WebDriver default timeout?

Trying to find a good way to set a maximum time limit for command execution latency in Selenium Python WebDriver. Ideally, something like: ff = webdriver.Firefox() ff.implicitly_wait(10) # seconds ff.get("http://somedomain/url_that_delays_loading&quo

第一篇——selenium之webdriver的认识

什么是 selenium?selenium 自动化测试浏览器,它主要是用于 Web 应用程序的自动化测试,但肯定不只局限于此,同时支持所有基于 web 的管理任务自动化. 什么是WebDriver? WebDriver通过原生浏览器支持或者浏览器扩展直接控制浏览器.WebDriver 针对各个浏览器而开发,取代了嵌入到被测 Web 应用中的 JavaScript.与浏览器的紧密集成支持创建更高级的测试,避免了JavaScript 安全模型导致的限制.除了来自浏览器厂商的支持,WebDriver

Selenium Webdriver 学习总结-Selenium Grid &amp; Webdriver(九)

QQ群: 136924235 论坛 : http://bbs.shareku.com Google教程:https://code.google.com/p/selenium/wiki/Grid2 Hub / Node 系统要求:JDK.firefox.chrome.internetExplorer 所需工具:selenium-server-standalone-xxx.jar 下载地址:http://code.google.com/p/selenium/downloads/list Start

自动化测试selenium模块webdriver的使用

一.webdriver基本使用命令 from selenium import webdriver   # 导入webdriver模块 >>> chrome_obj = webdriver.Chrome()              # 打开Google浏览器 >>> chrome_obj.get("https://www.baidu.com")      # 打开 网址 >>> chrome_obj.get(r"C:\de

【关于selenium自动化中,Webdriver的原理以及工作流程】

原文地址:https://www.cnblogs.com/imyalost/p/7242747.html#4109245 作者:老 张 1.关于Webdriver 设计模式:按照Server-Client的经典设计模式设计: Server端:即Remote Server(远程服务器),可以是任意的浏览器,当脚本启动浏览器时,该浏览器就是Remote Server,它的职责是等待Client发送请求并做出响应: Client端:我们的测试代码中的一些行为是以HTTP请求的方式发送给被测试浏览器--