• 0
  • 0
分享
  • 深入了解selenium及webdriver原理——软件测试圈
  • 恬恬圈 2021-07-15 09:55:38 字数 4899 阅读 937 收藏 0

       最近正在编写selenium webdriver自动化框架,经过几天的努力,目前基本已经实现了一套即能满足数据驱动、又能满足Web关键字驱动的自动化框架(主要基于 ant+jenkins+testng+selenium webdriver+jxl实现)。通过这次的自动化框架开发,我深刻的发现了webdriver的强大,甚至我们可以看到阿里巴巴的F2etest浏览器兼容性测试平台也是基于webdriver。以下特别转载了一篇关于selenium webdriver的介绍,让我们从深层次理解webdriver:

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

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

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

       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的工作原理:

1.png

       从上图中我们可以看出,不同浏览器的WebDriver子类,都需要依赖特定的浏览器原生组件,例如Firefox就需要一个add-on名字叫webdriver.xpi。而IE的话就需要用到一个dll文件来转化Web Service的命令为浏览器native的调用。另外,图中还标明了WebDriver Wire协议是一套基于RESTful的web service。

       关于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源码,继续分享的!

       关于使用Selenium WebDriver的经验小结:

       其中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的时间来追踪操作完成的进度。这里只是举个小小的例子,有机会再分享更多的细节。


作者:smooth-z

原文链接:https://blog.csdn.net/smooth00/article/details/77103090#comments_17191166

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 摘要:        随着网络攻击不断制造恐慌,我们在数字领域的应用和数据面临的威胁也越来越大。互联世界中的企业需要认识到,安全测试对于他们的web应用程序是至关重要的。他们从项目一开始就需要先进的、全面的安全测试计划,以确保安全的用户体验。下面讲讲如何开始。        近年来,支持各种服务的Web应用程序赢得了用户的信任。由于人们认为交易是受到安全监控的,所以在平台之间加载和共享了数万亿字节的数据。  &nbs...
            0 0 1150
            分享
          •   据法新社最新消息,TikTok当地时间22日向美国联邦法院提起诉讼,要求阻止蒙大拿州对这款视频共享应用程序实施禁令。  报道说,TikTok在诉讼中辩称,这项将于2024年起实施的禁令违反了宪法中有关言论自由的权利。  “我们相信,基于一系列极具说服力的先例和事实,我们的法律挑战将会获胜。”TikTok一名发言人对法新社表示。  今年5月17日,美国蒙大拿州州长格雷格·詹福尔特正式签署法案,禁止TikTok在该州运营,明年1月1日起生效。蒙大拿州成为全美首个签署彻底禁止TikTok法案的州。但媒体普遍认为,该禁令将面临法律挑战。美联社19日称,5名TikTok内容创作者提起诉讼,试图推翻蒙...
            0 0 954
            分享
          • 数据库事务事务是什么是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。事务的四大特性原子性:事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。隔离性:一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。持续性:也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就是永久性的。接下来的其它操作或故障不应该对其执行结果有任...
            12 12 1742
            分享
          •   知情人士近日向媒体透露,谷歌已开始与印度代工厂商进行早期沟通,以将其Pixel智能手机的部分生产转移到印度。消息人士表示,谷歌已经与Lava International Ltd.、Dixon Technologies India 以及富士康的印度子公司Bharat FIH进行了沟通,这三家公司都是印度市场具有影响力的手机代工厂商。  目前,谷歌母公司Alphabet和上述三家印度公司都暂未回应媒体的置评请求。 据分析,谷歌将于今年10月前后发布下一代Pixel智能手机Pixel 8和Pixel 8 Pro,该公司在上个月刚刚发布了Pixel 7a手机。  在此之前,June初,印度卡纳塔克...
            0 0 839
            分享
          • 在第三方测试机构做测试多年,后来进入做产品的公司负责测试工作,才发现在第三方测试机构做测试是多么幸福的事。简要来说,产品形公司开发和测试往往在同一个部门,没有部门间沟通时的仪式感,往往比较随意。由此,测试会面临如下困局:1.需求飘忽不定;2.版本界限模糊3.留给测试的实际时间与计划时间往往差别巨大已上任意一方面事件的发生,会使得测试焦头烂额,何况往往是已上几点的叠加。常见的场景是:在软件临近发布的时候,部门领导整天对你瞪眼,嫌你拖慢了进度,嫌你测试不够充分,殊不知,开发给你交付软件比项目计划晚了好长时间,严重压缩了你的测试时间。经过实践,提出以下几方面的措施供大家参考:第一.明确需求。这个需求...
            0 1 2357
            分享
      • 51testing软件测试圈微信