Selenium Java篇

img

Selenium的介绍

Jason Huggins在2004年发起了Selenium项目,当时身处ThoughtWorks的他,为了不想让自己的时间浪费在无聊的重复性工作中,幸运的是,所有被测试的浏览器都支持Javascript。Jason和他所在的团队采用Javascript编写一种测试工具来验证浏览器页面的行为;这个JavaScript类库就是Selenium core,同时也是seleniumRC、Selenium IDE的核心组件。Selenium由此诞生,这也是最早期的Selenium1.0。

2006年,Google的工程师Simon Stewart启动了WebDriver项目,此项目可以直接让测试用具调用浏览器和操作系统本身提供的内置方法,以此绕过JavaScript环境的沙盒限制,WebDriver项目的目的就是解决Selenium带来的痛处。随着新版本浏览器的发布,Selenium1.0被越来越多的浏览器内部安全机制所限制。2008年,Selenium项目和WebDriver项目进行了合并,于是Selenium WebDriver2(简称Selenium2)出现了。Selenium2 = Selenium1 + WebDriver。

2016年10月,Selenium WebDriver3(简称Selenium3)诞生了。这个版本有许多新特性,主要实现了核心API与客户端的Driver的分离,同时去掉了用的越来越少的SeleniumRC的功能。3.0时代所有支持的浏览器均由浏览器官方提供支持,这意味着浏览器UI测试的速度和稳定性会有较大的提升。

关于Selenium的命名比较有意思,当时QTP mercury是主流的商业自化工具,是化学元素汞(俗称水银),而Selenium是开源自动化工具,是化学元素硒,硒可以对抗汞。

Selenium1.0

组成

img

Selenium 1.0 = Selenium IDE + Selenium Grid + Selenium RC

  • Selenium IDE:Selenium IDE是嵌入到Firefox浏览器中的一个插件,实现简单的浏览器操作的录制与回放功能。

  • Selenium Grid:Selenium Grid是一种自动化的测试辅助工具,Grid通过利用现有的计算机基础设施,能加快Web-App的功能测试。利用Grid可以很方便地实现在多台机器上和异构环境中运行测试用例。

  • Selenium RC:Selenium RC(Remote Control)是Selenium家族的核心部分。Selenium RC 支持多种不同语言编写的自动化测试脚本,通过Selenium RC的服务器作为代理服务器去访问应用,从而达到测试的目的。

    • Selenium RC分为Client Libraries和Selenium Server。

      • Client Libraries库主要用于编写测试脚本,用来控制Selenium Server的库。
      • Selenium Server(Remote Server)负责控制浏览器行为,Selenium Server主要包括3个部分:Launcher,Http Proxy,Selenium Core。其中Selenium Core是被Selenium Server嵌入到浏览器页面中的。其实Selenium Core就是一堆JS函数的集合,就是通过这些JS函数,我们才可以实现用程序对浏览器进行操作。

所以,我们在学习Selenium1.0的时候,核心应该是学习RC,它的工作原理是这样的:

img

在2006年的时候,Google的工程师Simon Stewart发起了WebDriver的项目;因为长期以来Google一直是Selenium的重度用户,但却被限制在有限的操作范围内。

Selenium RC 是在浏览器中运行JavaScript应用,使用浏览器内置的JavaScript翻译器来翻译和执行selenese命令(selenese是Selenium命令集合)。

WebDriver是通过原生浏览器支持或者浏览器扩展来直接控制浏览器。WebDriver针对各个浏览器而开发,取代了嵌入到被测Web应用中的JavaScript,与浏览器紧密集成,因此支持创建更高级的测试,避免了JavaScript安全模型导致的限制。除了来自浏览器厂商的支持之外,WebDriver还利用操作系统级的调用,模拟用户输入。

Selenium与WebDriver原是属于两个不同的项目,WebDriver的创建者Simon Stewart早在2009年8月的一份邮件中解释了项目合并的原因。

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

实现原理

image-20201019180010803

自动化执行步骤如下

  1. 基于Selenium支持的编程语言编写测试脚本程序
  2. 执行测试程序
  3. 测试脚本程序发送访问网站的http请求给Remote RC
  4. Remote RC收到请求后,访问被测试网站并获取网页数据内容,并在网页中插入Selenium Core的JavaScript代码库,然后返回给测试人员执行测试的浏览器
  5. 测试脚本在浏览器内部再调用Selenium Core来执行测试代码,最后记录测试结果,完成测试。

为什么Selenium RC中的Selenium Server需要以这种代理服务器的形式存在?这时我们需要了解一下,浏览器的同源策略(The Same Origin Policy)

  • 什么是同源策略

    • 同源策略,它是由Netscape提出的一个著名的安全策略,现在所有的可支持JavaScript的浏览器都会使用这个策略。
      为什么需要同源策略。
    • 以实际的例子说明:
      1. 假设现在没有同源策略,会发生什么事情呢?大家知道,JavaScript可以做很多东西,比如:读取/修改网页中某个值。恩,你现在打开了浏览器,在一个tab窗口中打开了银行网站,在另外一个tab窗口中打开了一个恶意网站,而那个恶意网站挂了一个的专门修改银行信息的JavaScript,当你访问这个恶意网站并且执行它JavaScript时,你的银行页面就会被这个JavaScript修改,后果会非常严重!而同源策略就为了防止这种事情发生。
      2. 比如说,浏览器的两个tab页中分别打开了http://www.baidu.com/index.htmlhttp://www.google.com/index.html,其中,JavaScript1和JavaScript3是属于百度的脚本,而JavaScript2是属于谷歌的脚本,当浏览器的tab1要运行一个脚本时,便会进行同源检查,只有和www.baidu.com同源的脚本才能被执行,所谓同源,就是指域名、协议、端口相同。所以,tab1只能执行JavaScript1和JavaScript3脚本,而JavaScript2不能执行,从而防止其他网页对本网页的非法篡改。
      3. 所谓同源,就是指域名、协议、端口相同

Selenium1的核心部分是基于JavaScript代码库实现的,这个库默认和被测试网站是分离的,也就是说,这个JavaScript库的URL和被测试网站的域名肯定是不一致的。因为浏览器的同源策略,Selenium1的JavaScript是被禁止执行的,这样就无法实现对网站的自动化测试。为了应对浏览器的安全机制,Selenium1使用了代理方法来解决此问题。

image-20201019180730989

代理模式的实现机制具体如下:

  1. 执行测试脚本,想Selenium Server发起请求,要求和Selenium Server建立连接。
  2. Selenium Server的Launcher启动浏览器,向浏览器中插入Selenium Core的JavaScript代码库,并把浏览器代理设置为Selenium Server的Http Proxy。
  3. 测试脚本向Selenium Server发送Http请求,Selenium Server对请求进行解析,然后通过Http Proxy发送JS命令通知Selenium Core执行操作浏览器的动作。
  4. Selenium Core在接收到指令后,执行测试脚本指定的网页操作的命令。
  5. 浏览器接收到新的页面请求信息(在第四步中,Selenium Core的操作可能引发新的页面请求),发送Http请求给Selenium Server的Http Proxy,请求新的Web页面。
  6. 由于Selenium Server在启动浏览器时设定了浏览器的代理访问地址为Selenium Server的Http Proxy,所以Selenium Server会接收到所有由它启动的浏览器发送的请求。Selenium Server在接收到浏览器发送的Http请求后,自己重组Http请求,获取对应的Web页面。
  7. Selenium Server的Http Proxy把接收的Web页面返回浏览器。

通过以上步骤,实现了Selenium Core的JavaScript代码插入被测试网页的目的,然后就可以基于此代码库,在被测试网页中进行各种自动化测试操作了。此种方式是一种巧妙的“欺骗”。

Selenium2.0

Selenium和Webdriver的合并,所以,Selenium 2.0由此诞生。简单用公式表示为:Selenium 2.0 = Selenium 1.0 + WebDriver

需要强调的是,在Selenium 2.0中主推的是WebDriver,可以将其看作Selenium RC的替代品。因为Selenium为了保持向下的兼容性,所以在Selenium 2.0中并没有彻底地抛弃Selenium RC。

所以在学习Selenium2.0的时候,核心是学习WebDriver,工作原理是这样的:

img

WebDriver的实现原理

WebDriver与Selenium1的JavaScript插入方式不同,它直接利用浏览器的内部接口来操作浏览器。对于不同平台中的不同浏览器,必须依赖浏览器内部的Native Component(原生组件),将WebDriver API的调用转化为浏览器内部接口的调用。

WebDriver与Selenium1.0的差别

  • Selenium1采用JavaScript的合成事件来处理页面元素的操作,例如,要单击某个页面的元素,先使用JavaScript定位这个元素,然后触发单击事件。
  • WebDriver使用的是系统的内部接口或函数,找到这个元素的坐标位置,并在这个坐标点触发一个鼠标左键的点击操作。
  • 由此看出,WebDriver能更好地模拟真实的环境,但仅能测试那些可见的页面元素,也正因为如此,有些隐藏的页面元素可以使用Selenium1进行操作,而WebDriver却无法实现。

WebDriver的工作流程

以FireFox浏览器为例

image-20201022165040849

  1. 当客户端测试脚本启动Firefox时,Selenium WebDriver会首先在新线程中启动Firefox浏览器。如果在测试脚本中指定了Firefox的profile,那么就以此profile启动,否则,以新的profile启动Firefox;
  2. Firefox一般以“-no-remote”的方法启动,启动后,Selenium WebDriver会将Firefox绑定到特定的端口,绑定完成后,此Firefox实例编作为WebDriver的Remote Server存在;
  3. 客户端(测试脚本)创建一个session,在改session中通过http请求向Remote Server发送RESTful请求,Remoter Server通过驱动程序来解析请求,完成相应的操作并返回response;
  4. 客户端接收response,并分析其返回值以决定是转到第三步还是结束脚本。

Selenium3.0

Selenium3以开发一款聚焦Web端和移动端的自动化测试工具为目标,WebDriver API是Selenium2的主要插件,Selenium3依然沿用,并基于W3C标准。Selenium会不断的扩充WebDriver API,提供移动端的测试套件,以提高不同项目件的相互操作性。同时,Selenium3更关注系统的稳定性,移除了Selenium RC API。

  1. Selenium3.0只去掉了Selenium RC,这是Selenium3最大的变化。
  2. Selenium3.0只支持Java8及以上版本。
  3. Selenium3.0不在提供默认浏览器支持,所有支持的浏览器均由浏览器官方提供支持,即由官方提供相应的驱动程序,由此提升了自动化测试的稳定性。
  4. Selenium3.0通过Apple自己的SafariDriver支持MacOS上的Safari浏览器。Safari浏览器的驱动直接集成到Selenium Server上。也就是说,想在Safari浏览器上执行自动化测试脚本,必须使用Selenium Server。
  5. Selenium3.0通过Microsoft官方提供的Microsoft WebDriver支持Edge,在Windows 10系统中就可以实现Edge浏览器的自动化测试。
  6. Selenium3.0只支持IE9.0及以上版本,早期版本也许还能工作,但不在提供支持。

Selenium3.0让Web自动化运行更稳定,性能更好,支持浏览器更多、更新。

Selenium 1、Selenium 2和Selenium 3之间的关系

image-20201022173042831

Selenium架构图

image-20201018213344645

Driver的配置

  • Driver的介绍

  • Driver的下载

  • Driver的安装与使用

    • Chrome与Firefox浏览器使用

      • 找到与自己本机浏览器适配的driver版本http://chromedriver.chromium.org/downloads/version-selection

      • 导入环境变量中

        1
        2
        3
        4
        5
        6
        # 1. 下载好chromedriver
        # 2. mac路径, /usr/local/bin/
        # 3. 将chromedriver拖到/usr/local/bin/路径下
        # 4. 验证chromedriver,注意:Mac提供提示软件不安全,需要在安全设置里面进行确认
        bogon:IdeaProjects jinglv$ chromedriver --version
        ChromeDriver 87.0.4280.88 (89e2380a3e36c3464b5dd1302349b1382549290d-refs/branch-heads/4280@{#1761})
    • 代码中使用

        
      1
      System.setProperty("webdriver.chrome.driver", "chromedriver存放的绝对路径/chromedriver");
  • Safari浏览器

    • Safari浏览器不需要引入Driver驱动,可以直接使用,但需要在浏览器配置

        
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      public class TestBaidu {

      static WebDriver driver;

      @BeforeAll
      public static void before() {
      driver = new SafariDriver();
      }

      @Test
      public void test() {
      driver.get("http://www.baidu.com/");
      }

      @AfterAll
      public static void after() {
      driver.quit();
      }
      }
  • 未进行浏览器配置,在启动Driver的时候报错,错误信息:”You must enable the ‘Allow Remote Automation’ option in Safari’s Develop me”

  • 解决方案,需要勾选Safari-开发-允许远程自动化

  • image-20201019170036463

  • image-20201019170108948

    • image-20201019170150424