selenium自动化测试原理和设计的分享
昨天参加了公司的一个自动化测试的分享,有一些收获,记录一下。
1.主流的web端的UI自动化测试工具
基于浏览器API: selenium2.0,Watir(IE Driver)
基于JS 进行驱动:selenium1.0,sahi(ruby)
基于Windows GUI :QTP,AutoIt
2.实现原理(这里只列举第一种,第二种我没有实践,暂不研究)
基于浏览器API:

这里我在网上看了一下selenium2的实现原理,跟这个差不多。
参考:https://blog.csdn.net/ant_ren/article/details/7970793
selenium的工作原理:
1.用CS设计方式,将浏览器看作是remote server,有它自己的端口,将selenium的脚本执行端看作client。
2.client发送http request(操作放在json里面)发送给web server端,转化为浏览器的API,再封装成执行命令CommandExecutor ,发给浏览器去用native的操作执行
3.浏览器执行后,再返回给client
简化为:webdriver把浏览器的原生API包装了一下,通过conmmandExecutor来给浏览器发送http request请求(操作写在json里面),通过设置的端口,去请求浏览器,将发送的请求转化成浏览器的原生的命令,再将浏览器的返回,装进httpResponse里面,发回给客户端。
画了一张图

其他博客里面,引用的开发者的图

3.UI自动化的原则
- 不依赖环境,不改变环境
- 隔离变量和不变量
- 代码尽可能复用
4.使用的设计模式
三层:
- 界面表示层:一个页面封装到一个类中,一个方法对应一个控件,主要是查找控件,复杂控件操作,比如表格,需要再界面表示层实现
- 业务逻辑层:调用界面表示层的控件操作,完成业务逻辑,一般一个函数封装一个简单的业务操作。
- 测试用例层:调用业务层的函数完成测试,并验证结果,尽量不依赖环境,不破坏环境,不要直接调用界面层函数
5.源码解读,我用的是appium,不过appium和selenium是同源的,可以用来参考。
findElements代码
Response response = execute(DriverCommand.FIND_ELEMENTS,
ImmutableMap.of("using", by, "value", using));
@SuppressWarnings("unchecked")
protected List<WebElement> findElements(String by, String using) {
if (using == null) {
throw new IllegalArgumentException("Cannot find elements when the selector is null.");
}
Response response = execute(DriverCommand.FIND_ELEMENTS,
ImmutableMap.of("using", by, "value", using));
Object value = response.getValue();
List<WebElement> allElements;
try {
allElements = (List<WebElement>) value;
} catch (ClassCastException ex) {
throw new WebDriverException("Returned value cannot be converted to List<WebElement>: " + value, ex);
}
for (WebElement element : allElements) {
setFoundBy(this, element, by, using);
}
return allElements;
}
findElement 返回的是执行语句的 response,执行语句如下,返回值是response
protected Response execute(String driverCommand, Map<String, ?> parameters) {
Command command = new Command(sessionId, driverCommand, parameters);
Response response;
long start = System.currentTimeMillis();
String currentName = Thread.currentThread().getName();
Thread.currentThread().setName(
String.format("Forwarding %s on session %s to remote", driverCommand, sessionId));
try {
log(sessionId, command.getName(), command, When.BEFORE);
response = executor.execute(command);
log(sessionId, command.getName(), command, When.AFTER);
if (response == null) {
return null;
}
// Unwrap the response value by converting any JSON objects of the form
// {"ELEMENT": id} to RemoteWebElements.
Object value = converter.apply(response.getValue());
response.setValue(value);
} catch (SessionNotFoundException e){
throw e;
} catch (Exception e) {
log(sessionId, command.getName(), command, When.EXCEPTION);
String errorMessage = "Error communicating with the remote browser. " +
"It may have died.";
if (driverCommand.equals(DriverCommand.NEW_SESSION)) {
errorMessage = "Could not start a new session. Possible causes are " +
"invalid address of the remote server or browser start-up failure.";
}
UnreachableBrowserException ube = new UnreachableBrowserException(errorMessage, e);
if (getSessionId() != null) {
ube.addInfo(WebDriverException.SESSION_ID, getSessionId().toString());
}
if (getCapabilities() != null) {
ube.addInfo("Capabilities", getCapabilities().toString());
}
throw ube;
} finally {
Thread.currentThread().setName(currentName);
}
try {
errorHandler.throwIfResponseFailed(response, System.currentTimeMillis() - start);
} catch (WebDriverException ex) {
if (parameters != null && parameters.containsKey("using") && parameters.containsKey("value")) {
ex.addInfo(
"*** Element info",
String.format(
"{Using=%s, value=%s}",
parameters.get("using"),
parameters.get("value")));
}
ex.addInfo(WebDriverException.DRIVER_INFO, this.getClass().getName());
if (getSessionId() != null) {
ex.addInfo(WebDriverException.SESSION_ID, getSessionId().toString());
}
if (getCapabilities() != null) {
ex.addInfo("Capabilities", getCapabilities().toString());
}
Throwables.propagate(ex);
}
return response;
}
response的核心代码如下:执行command,然后用转化器将response的value转化成语句使用的代码
response = executor.execute(command);
……
Object value = converter.apply(response.getValue());
response.setValue(value);
这里的converter.apply,是JsonToWebElementConverter的方法,就是用来把返回的json串转化为element的转化器
public Object apply(Object result) {
if (result instanceof Collection<?>) {
Collection<?> results = (Collection<?>) result;
return Lists.newArrayList(Iterables.transform(results, this));
}
if (result instanceof Map<?, ?>) {
Map<?, ?> resultAsMap = (Map<?, ?>) result;
if (resultAsMap.containsKey("ELEMENT")) {
RemoteWebElement element = newRemoteWebElement();
element.setId(String.valueOf(resultAsMap.get("ELEMENT")));
element.setFileDetector(driver.getFileDetector());
return element;
} else if (resultAsMap.containsKey("element-6066-11e4-a52e-4f735466cecf")) {
RemoteWebElement element = newRemoteWebElement();
element.setId(String.valueOf(resultAsMap.get("element-6066-11e4-a52e-4f735466cecf")));
element.setFileDetector(driver.getFileDetector());
return element;
} else {
return Maps.transformValues(resultAsMap, this);
}
}
if (result instanceof Number) {
if (result instanceof Float || result instanceof Double) {
return ((Number) result).doubleValue();
}
return ((Number) result).longValue();
}
return result;
}
appium原理参考https://www.cnblogs.com/csj2018/p/9937511.html
selenium自动化测试原理和设计的分享的更多相关文章
- 《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)
1.简介 从这一篇开始介绍和分享Java+Selenium+POM的简单自动化测试框架设计.第一个设计点,就是支持跨浏览器测试. 宏哥自己认为的支持跨浏览器测试就是:同一个测试用例,支持用不同浏览器去 ...
- 《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)
1.简介 前面宏哥一连几篇介绍如何通过开源jar包Log4j.jar.log4j2.jar和logback实现日志文件输出,Log4j和logback确实很强大,能生成三种日志文件,一种是保存到磁盘的 ...
- 《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程)
1.简介 jmeter系列的文章结束,本来想趁热打铁顺别将Jmeter和接口测试介绍一下,但是感觉Jmeter时间太长了怕大家吃腻了,还有一个原因就是许多小伙伴们或者童鞋们私信问宏哥什么时候可以有ja ...
- Eclipse+Selenium自动化测试脚本设计V1.0
Eclipse+Selenium自动化测试脚本设计V1.0 http://www.docin.com/p-803032251.html
- 《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
1.简介 上一篇宏哥介绍了如何设计支持不同浏览器测试,宏哥的方法就是通过来切换配置文件设置的浏览器名称的值,来确定启动什么浏览器进行脚本测试.宏哥将这个叫做浏览器引擎类.这个类负责获取浏览器类型和启动 ...
- 从UI Automation看Windows平台自动化测试原理
前言 楼主在2013年初研究Android自动化测试的时候,就分享了几篇文章 Android ViewTree and DecorView Android自动化追本溯源系列(1): 获取页面元素 An ...
- Selenium自动化测试,接口自动化测试开发,性能测试从入门到精通
Selenium自动化测试,接口自动化测试开发,性能测试从入门到精通Selenium接口性能自动化测试基础部分:分层自动化思想Slenium介绍Selenium1.0/2.0/3.0Slenium R ...
- Selenium自动化测试Python五:WebDriver设计模式
WebDriver 设计模式 欢迎阅读WebDriver进阶讲义.本篇讲义将会重点介绍Selenium WebDriver 自动化框架的设计,着重使用Page Object设计模式,以及使用HTML测 ...
- selenium自动化测试框架之PO设计模式
面向对象的特性:封装.继承.多态.在自动化中一样适用,Selenium自动化测试中有一个名字常常被提及PageObject(思想与面向对象的特性相同),通过PO模式可以大大提高测试用例的维护效率. 传 ...
随机推荐
- 开机自动获取spark用户名和服务器
import os.path import getpass import platform import time username = getpass.getuser() #获取当前用户名 home ...
- web跨域请求
第一种情况: 1. sina.com=====>baidu.com/xxx.jsp 也就是前面的域名不相同,(url第三根斜杠之前的内容,也就是主机) 2:localhost =====> ...
- How to sign app
codesign --display --verbose=4 /applications/qq.app codesign --display --entitlements - /application ...
- c++ 怎么输出保留2位小数的浮点数
//添加头文件 #include<iomanip> //定义变量 folat a=9.1; cout<<setiosflags(ios::fixed)<<setpr ...
- hdu-4763(kmp+拓展kmp)
题意:给你一个串,问你满足最大字串既是前后缀,也在字符串除去前后缀的位置中出现过: 思路:我用的是拓展kmp求的前后缀,只用kmp也能解,在字符串2/3的位置后开始遍历,如果用一个maxx保存前2/3 ...
- Nginx 如何处理上游响应的数据
陶辉93 一个非常重要的指令 proxy_buffer_size 指令限制头部响应header最大值 proxy_buffering 指令主要是指 上游服务器是否接受完完整包体在处理 默认是on 也就 ...
- 接口由40秒到200ms优化记录
场景还原 一个业务逻辑较为复杂的业务,涉及到n次遍历,其中有循环查询/更新数据库,事务的管理,加上一些业务逻辑的计算.最初的接口,纯粹按照产品提供的相关业务逻辑,单纯的编码,耗时较长,近40秒的处理时 ...
- nginx反向代理时配置访问密码
在有些情况下,我们需要对服务器上的某些资源进行限流或者禁止陌生人访问,我们可以通过nginx配置来对url添加访问密码. 效果如下 nginx 开启访问验证在 nginx 下,提供了 ngx_http ...
- windows查看进程占用并强制结束进程
打开命令提示符(CMD) 查看8080端口被哪个进程占用了,命令:netstat -ano|findstr 8080 上面的8080端口的PID是30160,可以根据PID可以杀死这个进程,用下面 ...
- 百度分享不支持https的解决方案(单独部署静态文件)
首先是参考了博客,下载百度分享的静态代码 static 链接为:https://www.cnblogs.com/mmzuo-798/p/6434576.html 后来在nginx的 nginx.con ...