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模式可以大大提高测试用例的维护效率. 传 ...
随机推荐
- MyBatis基础:MyBatis入门(1)
1. MyBatis简介 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. MyBatis ...
- Fabric运维从入门到精通
1. fabric的安装 在windows下的python3中安装fabric: 在python安装根目录下使用pip install fabric 安装 如图: fabric只支持python2不支 ...
- bash中的pasue
#!/bin/bash echo 按任意键继续 read -n
- java静态工厂
本文摘自:https://www.jianshu.com/p/ceb5ec8f1174 本文略长,所以先来个内容提要 序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器 ...
- Bootstrap之图片展示界面Demo
代码:(使用模板引擎freemarker) <!DOCTYPE html> <html> <head> <title>图片</title> ...
- CABAC总结与补充讨论
在之前的一篇文章CABAC中我们已经对算法中的大部分细节部分做了详细分析,这里做一个总结与拾遗. 总结 CABAC的编码可以分为以下四个部分: 上下文变量的初始化 待编码语法元素二值化 上下文建模(确 ...
- iptables防火墙的原理及应用
简介 (netfilter, 位于Linux内核中的包过滤功能体系 ,称为Linux防火墙的“内核态”) iptables防火墙工作在网络层,针对TCP/IP数据包实施过滤和限制,iptables防 ...
- P1427 小鱼念数字
P1427 题目描述 小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字(长度不一定,以0结束,最多不超过100个,数字不超过2^32-1),记住了然后反着念出来(表示结束的数字0就不要念出来了) ...
- 【AGC002E】Candy Piles 博弈论
题目大意 有\(n\)堆糖果,第\(i\)堆有\(a_i\)个. 两个人轮流决策,决策分为两种: 1.选择糖果数最多的一堆糖果,并把这堆糖全吃了. 2.在每堆非空的糖果堆里拿一颗糖吃掉. 吃掉最后一颗 ...
- 【BZOJ5020】【THUWC2017】在美妙的数学王国中畅游 LCT 泰勒展开
题目大意 给你一棵树,每个点有一个函数\(f(x)\) 正弦函数 \(\sin(ax+b) (a\in[0,1],b\in[0,\pi],a+b\in[0,\pi])\) 指数函数 \(e^{ax+b ...