做过两年自动化测试的小伙伴说web自动化测试真的不难,无非就是一些浏览器操作,页面元素操作,常规的情况很容易处理,再学一学特殊元素的处理,基本就能应付项目的测试了。

  这个话倒没错,但是真正要学好自动化测试,深入自动化,并不是那么简单。首先你得懂原理吧,原理不懂,你就不知道怎么解决一些异常情况,也无法完成拓展。其次你得学会写自己的测试框架吧,一个项目写了100个测试类,都是零散的脚本,没有任何设计而言,都是纯粹的业务代码,那我可以说,换了项目你这些脚本就成了垃圾,因此,我们要做自动化,要成为自动化大牛,就一定要花时间去要搞清楚自动化实现的原理,并且学会自己去实现自动化测试框架,乃至于自动化测试平台。

  下面一段代码实现了一个很简单的功能:

  1.打开浏览器

  2.访问页面“http://ke.qq.com”

  3.定位到页面的搜索框

  4.输入查询数据

  5.定位搜索按钮

  6.点击搜索按钮,完成搜索

  代码如下图:

  

package web.demo;import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebElement;import org.openqa.selenium.firefox.FirefoxDriver;import org.testng.annotations.Test;public class Demo1 { @Test public void test(){ //设置可执行的驱动文件路径 System.setProperty("webdriver.gecko.driver", "src/test/resources/geckodriver.exe"); //创建火狐驱动对象 WebDriver driver = new FirefoxDriver(); //访问腾讯课堂首页 driver.get("https://ke.qq.com/"); //定位页面的搜索框 WebElement searchInputBox = driver.findElement(By.id("js_keyword")); //往搜索框输入数据 searchInputBox.sendKeys("柠檬班"); //定位到搜索按钮 WebElement searchButton = driver.findElement(By.id("js_search")); //点击搜索 searchButton.click(); }}

  驱动文件位置:

  

  

  需求很简单,代码也很简单。但是你知道代码中的这些浏览器操作,元素操作,是如何完成的吗?

  比如,浏览器启动完成后,再调用:driver.get("https://ke.qq.com/");就能在导航栏中访问到指定的这个页面,这个里面发生了什么,到底是客户端脚本直接操作浏览器还是通过某些中间件来完成??

  底层原理如下:

  1.在自动化测试过程中,存在三部分组件:客户端脚本+驱动+浏览器终端。

  2.驱动文件,以geckodriver.exe为例,这个可执行的驱动文件启动后,相当于一个暴露了一系列接口的服务器,监听某一端口,例如:89890。

  3.客户端的操作(访问页面,定位元素,输入数据,点击按钮等)都是封装成了接口请求(eg:/session/xx/yy),然后提交到驱动服务器。

  4.驱动服务器接收到客户端的请求后,再跟终端浏览器交互。

  5.终端浏览器做出相应操作。

    下图描述了整个交互过程:

  

  以定位元素为例,定位搜索框,我们来看底下这行代码在执行的时候底层到底经历了些什么:

WebElement searchInputBox = driver.findElement(By.id("js_keyword"));

  

实际,底层请求时,每个请求会被封装为一个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"));

}

  另外,可能会有人好奇,驱动服务器是何时启动的服务。其实是在执行下面这行代码的时候启动的,大家可执行去debug调试selenium的底层代码:

  

//创建火狐驱动对象
WebDriver driver = new FirefoxDriver();

  当上面这行代码执行完,可以发现eclipse的控制台显示了如下信息:

1531911173760 geckodriver INFO geckodriver 0.19.0
1531911173772 geckodriver INFO Listening on 127.0.0.1:21984

  说明此驱动服务器成功启动了,并且监听了本机的21984端口,等待客户端发起请求,并处理。

  至于驱动跟浏览器之间是如何交互的,在后面的文章中会择机介绍,请大家守候。

转载于:https://blog.51cto.com/13859884/2147043

web自动化原理揭秘相关推荐

  1. html 打开页面光标自动选中输入框_初识selenium之web自动化

    今天我们学习下如何使用python编写web自动化,谈到web自动化,那么我们需要了解下市面上做web自动化的几种方式,Robotframework工具,网红WebUI自动化测试神器 - Cypres ...

  2. airtest web 录制滑块_Airtest之web自动化(一)

    Airtest之web自动化(一) [此文档有许多涉及到gif动图的地方,请全屏观看] 了解Airtest: 简介: Airtest是由网易团队开发的一款自动化框架,前期运用与游戏测试(通过截图识别) ...

  3. 自动化测试 (三) Web自动化测试原理

    目前市面上有很多Web UI自动化测试框架,比如WatiN, Selinimu,WebDriver,还有VS2010中的Coded UI等等.  这些框架都可以操作Web中的控件,模拟用户输入,点击等 ...

  4. 聊一聊使用airtest-selenium做Web自动化的常见问题

    1. 前言 很多同学选择使用airtest-selenium来做Web自动化,是因为想使用airtest-selenium封装的一些关于图像识别的方法,像图像点击.图像断言.截图等等. 但是在实际应用 ...

  5. WEB自动化-(RFS)RobotFramework+Selenium框架介绍测试流程详解

    各个驱动下载地址: http://www.seleniumhq.org/download/ 一.RFS介绍 1.概念 RFS框架:RobotFramework+Selenium框架 2.特点 2.1通 ...

  6. web自动化解决全国教师管理系统学分自动录入

    办公室姜姐姐拉着我看了她最近在做的一个特无语的工作,那就是一个个录入教师的学分,全校两三百号人的数据就需要那样一个个重复的输入进去.她还告诉我,有同行解决了自动录入,但是不知道他们怎么自动的.我想了想 ...

  7. airtest测试网页_Airtest之web自动化(一)

    Airtest之web自动化(一) [此文档有许多涉及到gif动图的地方,请全屏观看] 了解Airtest: 简介: Airtest是由网易团队开发的一款自动化框架,前期运用与游戏测试(通过截图识别) ...

  8. Web安全原理及实践(基础部分)

    Web安全原理及实践(入门) Web安全基础 Web安全概述 Web安全基础 常见渗透测试工具 Nmap BurpSuite Sqlmap Sublime 常见的漏洞扫描工具 BurpsuiteSca ...

  9. web自动化捕捉元素基本方法

    前言:前面已经把环境搭建好了,从这篇开始,正式学习selenium的webdriver框架.我们平常说的 selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可视化工具,我们要学的是w ...

最新文章

  1. 高考计算机算分么,高考分数是怎么算出来的
  2. IntelliJ IDEA 环境常用设置整理
  3. 'telnet' 不是内部或外部命令,也不是可运行的程序
  4. 基于SVD矩阵分解的用户商品推荐(python实现)
  5. boost实用工具:创建一个禁止复制的类 noncopyable
  6. Android开发之ListView子布局item高度的问题
  7. 将进酒,如果李白也编程
  8. JS获取浏览器高度、屏幕高度、宽屏
  9. systemback Linux 系统备份、迁移
  10. html+css常用代码(前端必备)
  11. 花一分钟彻底搞懂Mac输入法/中英文/大小写切换
  12. android父布局的右侧,相对布局(RelativeLayout)的控件运用
  13. 考勤记录查询java_kaoqin 一个员工考勤软件,用java和sql写的,实现基本的签到和查询功能 Develop 238万源代码下载- www.pudn.com...
  14. unity3d/用户自由改变背景色
  15. jQuery制作手风琴
  16. Centos操作系统yum源的使用
  17. MATLAB音频信号处理(一):函数简易用法(audioread,sound函数)
  18. JEDEC79-4翻译告一段落
  19. 初学Java常见异常:NPE空指针异常怎么解决?
  20. php 开源程序_国内PHP开源建站程序一览

热门文章

  1. c语言最短延时程序,linux下写个C语言程序,要求有0.5微秒以下的延时,要怎样写...
  2. 数组c语言什么时候学的,C语言学习之数组
  3. java数据结构创建树_在java中创建树数据结构?
  4. [GO]append的扩容
  5. jQuery学习笔记(五)
  6. SWF反编神器Action Script Viewer终身免费升级!
  7. Python使用BeautifulSoup爬取网页中主体部分的内容,并导出为pdf格式
  8. Mac IDEA启动SpringBoot项目过慢
  9. 计算机电子的危害,电子垃圾焚烧炉的危害有多大,你了解过吗?
  10. VBA打开TXT类文件读写相关操作代码