一、自动化实现原理

  1.创建驱动对象

    (1) 首先加载浏览器安装目录下的exe文件

(2) 其次是加载可执行驱动的exe文件,监听等待客户端发送的web service请求.

底层原理如下:
  1.在自动化测试过程中,存在三部分组件:客户端脚本+驱动+浏览器终端。
  2.驱动文件,以geckodriver.exe为例,这个可执行的驱动文件启动后,相当于一个暴露了一系列接口的服务器,监听某一端口,例如:89890。
  3.客户端的操作(访问页面,定位元素,输入数据,点击按钮等)都是封装成了接口请求(eg:/session/xx/yy),然后提交到驱动服务器。
  4.驱动服务器接收到客户端的请求后,再跟终端浏览器交互。
  5.终端浏览器做出相应操作。

二、driver调用方法小结

三、Selenium 1.0 的工作原理

  Selenium 1.0,又称Selenium RC ,RC是Remote Control的缩写。Selenium RC利用的原理:JavaScript代码可以方便的获取页面上的任意元素并执行各种操作。

  但是因为“同源政策(Same-origin policy)”(只有来自相同域名、端口和协议的javaScript代码才能被浏览器执行),所以,要想在测试用例运行中的浏览器中,注入javascript代码,从而实现自动化web操作,Selenium RC必须“欺骗”被测站点,让它误以为被注入的代码是同源的。

  那如何实现“欺骗”呢?这就是需要引入 Selenium RC Server 的原因了。其中的 Http Proxy 模块就是来「欺骗」浏览器的。除了 Selenium RC Server,Selenium RC 方案的另一部分就是 Client Libraries。他们的具体关系如下图1所示:

图1 Selenium RC 的基本模块

Selenium RC Server,主要包括Selenium Core,Http Proxy 和Launcher 三部分:

  • Selenium Core,是被注入到浏览器页面中的JavaScript 函数集合,用来实现界面元素的识别和操作;

  • Http Proxy,作为代理服务器修改JavaScrip的源,以达到“欺骗”被测站点的目的;

  • Launcher,用来在启动测试浏览器时完成,Selenium Core 的注入和浏览器代理的设置。

Client Libraries,是测试用例代码向Selenium RC Server发送 Http 请求的接口,支持多种语言,包括 Java、C# 和 Ruby 等。

  Selenium执行流程图,如图2:

图2 Selenium RC 的执行流程

  1. 测试用例通过基于不同语言的 Client Libraries向 Selenium RC Server 发送Http请求,要求与其建立连接。

  2. 连接建立后,Selenium RC Server 的Launcher 就会启动浏览器或者重用之前已经打开的浏览器,把 Selenium Core(JavaScript 函数的集合)加载到浏览器页面当中,并同时把浏览器的代理设置为Http Proxy。

  3. 测试用例通过 Client Libraries,向 Selenium RC Server 发送 Http请求,Selenium RC Server 解析请求,然后通过 Http Proxy 发送 JavaScript命令通知 Selenium Core 执行浏览器上控件的具体操作。

  4. Selenium Core 接收到指令后,执行操作。
  5. 如果浏览器收到新的页面请求信息,则会发送 Http 请求来请求新的 Web 页面。由于 Launcher 在启动浏览器时把 Http Proxy 设置成为了浏览器的代理,所以 Selenium RC Server 会接收到所有由它启动的浏览器发送的请求。

  6. Selenium RC Server 接收到浏览器发送的 Http 请求后,重组 Http 请求以规避“同源策略”,然后获取对应的 Web 页面。

  7. Http Proxy 把接收的 Web 页面返回给浏览器,浏览器对接收的页面进行渲染。

四、Selenium 2.0 的工作原理

  Selenium 2.0,又称 Selenium WebDriver,其原理是:使用浏览器原生的 WebDriver 实现页面操作。实现方式完全不同于 Selenium 1.0。Selenium WebDriver 是典型的 Server-Client 模式,Server 端就是 Remote Server。以下是 Selenium 2.0 工作原理:

图3 Selenium WebDriver 的执行流程

  1. 当使用 Selenium 2.0 启动浏览器时,后台会同时启动基于 WebDriver Wire 协议的 Web Service 作为 Selenium 的 Remote Server,并与浏览器绑定。之后,Remote Server 就开始监听 Client 端的操作请求;
  2. 执行测试时,测试用例会作为 Client 端,每个请求都会被封装成为一个command命令,每一个command命令都会对应一个web service服务地址,根据不同的command,获取到请求地址,并封装成httpRequest对象,以 Http Request 的方式发送给 Remote Server 。该 Http Request 的 body,是以 WebDriver Wire 协议规定的 JSON 格式来描述需要浏览器执行的具体操作;
  3. Remote Server 接收到请求后,通过java客户端完成接口的调用:client.execute(httpRequest)获得响应,,并将结果发给 WebDriver,由WebDriver 实际执行浏览器的操作;
  4. WebDriver 可以看做是直接操作浏览器的原生组件(Native Component),所以搭建测试环境时,通常都需要先下载浏览器对应的 WebDriver。

 五、以findElement为例Debug方式代码走读:

driver.get("https://www.baidu.com");
WebElement element = driver.findElement(By.id("kw"));
element.sendKeys("自动化测试");

实际,底层请求时,每个请求会被封装为一个command,然后根据不同的commannd封装得到不同的HttpRequest对象:

根据此命令,得到接口地址:

拿到此接口地址封装为一个HttpRequest请求。

client.execute(httpRequest,true),执行接口调用:

至于其他操作:往输入框输入数据,点击按钮等,都是对应一个接口地址,通过调用接口,请求驱动来处理,最后驱动同浏览器进行交互,浏览器按照指示做出对应操作。

Selenium有一个类AbstractHttpCommandCodec,此类中维护了众多自动化操作对应的接口地址:

public AbstractHttpCommandCodec() {
defineCommand(STATUS, get("/status")); defineCommand(GET_ALL_SESSIONS, get("/sessions"));
defineCommand(NEW_SESSION, post("/session"));
defineCommand(GET_CAPABILITIES, get("/session/:sessionId"));
defineCommand(QUIT, delete("/session/:sessionId")); defineCommand(GET_SESSION_LOGS, post("/logs"));
defineCommand(GET_LOG, post("/session/:sessionId/log"));
defineCommand(GET_AVAILABLE_LOG_TYPES, get("/session/:sessionId/log/types")); defineCommand(SWITCH_TO_FRAME, post("/session/:sessionId/frame"));
defineCommand(SWITCH_TO_PARENT_FRAME, post("/session/:sessionId/frame/parent")); defineCommand(CLOSE, delete("/session/:sessionId/window"));
defineCommand(SWITCH_TO_WINDOW, post("/session/:sessionId/window")); defineCommand(FULLSCREEN_CURRENT_WINDOW, post("/session/:sessionId/window/fullscreen")); defineCommand(GET_CURRENT_URL, get("/session/:sessionId/url"));
defineCommand(GET, post("/session/:sessionId/url"));
defineCommand(GO_BACK, post("/session/:sessionId/back"));
defineCommand(GO_FORWARD, post("/session/:sessionId/forward"));
defineCommand(REFRESH, post("/session/:sessionId/refresh")); defineCommand(SET_ALERT_CREDENTIALS, post("/session/:sessionId/alert/credentials")); defineCommand(UPLOAD_FILE, post("/session/:sessionId/file"));
defineCommand(SCREENSHOT, get("/session/:sessionId/screenshot"));
defineCommand(ELEMENT_SCREENSHOT, get("/session/:sessionId/screenshot/:id"));
defineCommand(GET_TITLE, get("/session/:sessionId/title")); defineCommand(FIND_ELEMENT, post("/session/:sessionId/element"));
defineCommand(FIND_ELEMENTS, post("/session/:sessionId/elements"));
defineCommand(GET_ELEMENT_PROPERTY, get("/session/:sessionId/element/:id/property/:name"));
defineCommand(CLICK_ELEMENT, post("/session/:sessionId/element/:id/click"));
defineCommand(CLEAR_ELEMENT, post("/session/:sessionId/element/:id/clear"));
defineCommand(
GET_ELEMENT_VALUE_OF_CSS_PROPERTY,
get("/session/:sessionId/element/:id/css/:propertyName"));
defineCommand(FIND_CHILD_ELEMENT, post("/session/:sessionId/element/:id/element"));
defineCommand(FIND_CHILD_ELEMENTS, post("/session/:sessionId/element/:id/elements"));
defineCommand(IS_ELEMENT_ENABLED, get("/session/:sessionId/element/:id/enabled"));
defineCommand(ELEMENT_EQUALS, get("/session/:sessionId/element/:id/equals/:other"));
defineCommand(GET_ELEMENT_RECT, get("/session/:sessionId/element/:id/rect"));
defineCommand(GET_ELEMENT_LOCATION, get("/session/:sessionId/element/:id/location"));
defineCommand(GET_ELEMENT_TAG_NAME, get("/session/:sessionId/element/:id/name"));
defineCommand(IS_ELEMENT_SELECTED, get("/session/:sessionId/element/:id/selected"));
defineCommand(GET_ELEMENT_SIZE, get("/session/:sessionId/element/:id/size"));
defineCommand(GET_ELEMENT_TEXT, get("/session/:sessionId/element/:id/text"));
defineCommand(SEND_KEYS_TO_ELEMENT, post("/session/:sessionId/element/:id/value")); defineCommand(GET_ALL_COOKIES, get("/session/:sessionId/cookie"));
defineCommand(GET_COOKIE, get("/session/:sessionId/cookie/:name"));
defineCommand(ADD_COOKIE, post("/session/:sessionId/cookie"));
defineCommand(DELETE_ALL_COOKIES, delete("/session/:sessionId/cookie"));
defineCommand(DELETE_COOKIE, delete("/session/:sessionId/cookie/:name")); defineCommand(SET_TIMEOUT, post("/session/:sessionId/timeouts"));
defineCommand(SET_SCRIPT_TIMEOUT, post("/session/:sessionId/timeouts/async_script"));
defineCommand(IMPLICITLY_WAIT, post("/session/:sessionId/timeouts/implicit_wait")); defineCommand(GET_APP_CACHE_STATUS, get("/session/:sessionId/application_cache/status"));
defineCommand(IS_BROWSER_ONLINE, get("/session/:sessionId/browser_connection"));
defineCommand(SET_BROWSER_ONLINE, post("/session/:sessionId/browser_connection"));
defineCommand(GET_LOCATION, get("/session/:sessionId/location"));
defineCommand(SET_LOCATION, post("/session/:sessionId/location")); defineCommand(GET_SCREEN_ORIENTATION, get("/session/:sessionId/orientation"));
defineCommand(SET_SCREEN_ORIENTATION, post("/session/:sessionId/orientation"));
defineCommand(GET_SCREEN_ROTATION, get("/session/:sessionId/rotation"));
defineCommand(SET_SCREEN_ROTATION, post("/session/:sessionId/rotation")); defineCommand(IME_GET_AVAILABLE_ENGINES, get("/session/:sessionId/ime/available_engines"));
defineCommand(IME_GET_ACTIVE_ENGINE, get("/session/:sessionId/ime/active_engine"));
defineCommand(IME_IS_ACTIVATED, get("/session/:sessionId/ime/activated"));
defineCommand(IME_DEACTIVATE, post("/session/:sessionId/ime/deactivate"));
defineCommand(IME_ACTIVATE_ENGINE, post("/session/:sessionId/ime/activate")); // Mobile Spec
defineCommand(GET_NETWORK_CONNECTION, get("/session/:sessionId/network_connection"));
defineCommand(SET_NETWORK_CONNECTION, post("/session/:sessionId/network_connection"));
defineCommand(SWITCH_TO_CONTEXT, post("/session/:sessionId/context"));
defineCommand(GET_CURRENT_CONTEXT_HANDLE, get("/session/:sessionId/context"));
defineCommand(GET_CONTEXT_HANDLES, get("/session/:sessionId/contexts"));
}

参考博客原地址:https://www.cnblogs.com/miaojjblog/p/10563058.html

参考博客原地址:https://www.cnblogs.com/nickjiang/p/9332480.html

学习参考博客总结,以备后面复习,分享给需要的人,不足之处后续修正!

【java+selenium3】自动化基础小结+selenium原理揭秘 (十七)的更多相关文章

  1. java接口自动化基础知识(二)

    二.HttpClient+testNG实现对接口的测试及校验 在上面第一篇中已经实现了基础配置和测试用例数据准备,本篇文章将以登录举例进行测试执行. 这是之前login接口的代码 @Test(grou ...

  2. java多线程--多线程基础小结

    什么是线程? 在同一个进程中可以执行多个任务,每一个任务可以看做一个线程. 线程是程序的执行单元,执行路径,使程序使用cpu的最基本单位 一个进程如果只有一条执行路径,那么就是单线程的 一个进程如果有 ...

  3. java接口自动化基础知识(一)

    一.TestNG+MySQL+MyBatis实现对测试用例数据的读取 本篇文章讲解TestNG+MySQL+MyBatis+ExtentReports实现对测试用例数据的读取,下面放出所有配置文件的目 ...

  4. Selenium原理初步--Android自动化测试学习历程

    章节:自动化基础篇——Selenium原理初步(第五讲) 注:其实所有的东西都是应该先去用,但是工具基本都一样,底层都是用的最基础的内容实现的,测试应该做的是: (1)熟练使用工具,了解各个工具的利弊 ...

  5. 测试自动化:java+selenium3 UI自动化(1) - 环境搭建

    1.前言 我大概是在2012年第一次正式接触到自动化测试,那个时候跟随我的团队一起,就当时项目的UI自动化尝试做出了探索. 在我离开那家公司的时候,我们的自动化测试体系仍然难言完美,但是也已经达到了非 ...

  6. 【Selenium01篇】python+selenium实现Web自动化:搭建环境,Selenium原理,定位元素以及浏览器常规操作!

    一.前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新! 二.话不多说,直接开干,开始搭建自动化测试环境 这里以前在 ...

  7. JVM 内部原理(七)— Java 字节码基础之二

    JVM 内部原理(七)- Java 字节码基础之二 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...

  8. JVM 内部原理(六)— Java 字节码基础之一

    JVM 内部原理(六)- Java 字节码基础之一 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...

  9. Java 基础--小结

    Java  基础--小结 java基础 Java源程序(.java文件)——>java字节码文件(.class文件)——>由解释执行器(java.exe)将字节码文件加载到java虚拟机( ...

随机推荐

  1. Docker系列(7)- 常用命令(3) | 容器命令

    容器命令 说明: 有了镜像才可以创建容器:下载一个centos镜像进行练习,相当于在Linux里面再见一个Linux虚拟机 [root@localhost ~]# docker pull centos ...

  2. 腾讯云与 Grafana Labs 达成深度合作, 推出全新 Grafana 托管服务

    9 月 23 日,腾讯云宣布与业界领先的开源数据可视化公司 Grafana Labs 达成深度合作协议,共同开发和验证全新的 Grafana 托管服务,通过 Grafana Labs 开源软件与腾讯云 ...

  3. Tidb使用

    一.为什么使用Tidb 最近发现tidb在互联网圈大火,新生代的一个NewSql数据库 具体链接可以访问pincap的官网  https://www.pingcap.com/docs-cn/v3.0/ ...

  4. 踩坑系列《三》 java -version 报错出现Error occurred during initialization of VM java/lang/NoClassDefFoundError:

    之前导入一个项目,因为该项目Spring版本过低,只能适用于1.7版本,装了jdk1.7版本.安装配置好后,打开cmd窗口,执行 java -version 指令发现没像正常一样显示版本信息,而是报了 ...

  5. 11204备库升级PSU

    某系统PSU为11.2.0.4.190115,备库打补丁20年10月份(31537677)由readme可知:1.要求OPatch要求为11.2.0.3.23或之后的版本.2.非rac环境打补丁需要关 ...

  6. 第十二章 Net 5.0 快速开发框架 YC.Boilerplate --千万级数据处理解决方案

    在线文档:http://doc.yc-l.com/#/README 在线演示地址:http://yc.yc-l.com/#/login 源码github:https://github.com/linb ...

  7. IO之字符流

    什么是字符流 对于文本文件(.txt .java .c .cpp) 使用字符流处理 注意点 读入的文件一定要存在 否则就会报FileNotFoundException 异常的处理 为了保证流资源 一定 ...

  8. 设计模式如何提升 vivo 营销自动化业务扩展性 | 引擎篇01

    在<vivo 营销自动化技术解密 |开篇>中,我们从整体上介绍了vivo营销自动化平台的业务架构.核心业务模块功能.系统架构和几大核心技术设计. 本次带来的是系列文章的第2篇,本文详细解析 ...

  9. canvas 实现简单的画板功能添加手机端效果 1.01

    在上次的基础上,加了一些代码,手机端可操作 访问网址:https://chandler712.github.io/Item/ <!-- 简单版画板 --> <!DOCTYPE htm ...

  10. MC-BE基岩版服务器搭建与日常维护

    有部分内容被csdn和谐,强烈建议移步我的个人博客以获得更好的排版和阅读体验: xzajyjs.cn. 目录 环境搭建 开始部署 日常维护 服务器的白名单机制 定时备份 服务器升级 服务器模组安装 搭 ...