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模式可以大大提高测试用例的维护效率. 传 ...
随机推荐
- How to remove unwant Explorer Context Menu
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell
- SVG辅助标签
前面的话 本文将详细介绍SVG辅助标签 超链接 在SVG中,可以使用超链接<a>.超链接可以添加到任意的图形上,类比于热区<area> SVG中的超链接有如下3个常用属性 xl ...
- 2.docker的网络模式
本篇文章使用nginx:apline 镜像进行编辑. docker 版本基于 [root@master song]# docker version Client: Version: API vers ...
- 工厂类,配置文件,静态方法,反射构成编译器解耦;ioc的一个概念 ;通过xml创建容器里面存储对象
工厂类,配置文件,静态,反射方法构成编译器解耦;ioc的一个概念
- CABAC总结与补充讨论
在之前的一篇文章CABAC中我们已经对算法中的大部分细节部分做了详细分析,这里做一个总结与拾遗. 总结 CABAC的编码可以分为以下四个部分: 上下文变量的初始化 待编码语法元素二值化 上下文建模(确 ...
- Django restframe 视图函数以及ModelSerializer的使用
建立model数据库 from django.db import models __all__ = ['Book', 'Publisher', 'Author'] # Create your mode ...
- Python介绍及环境配置
Python 简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有 ...
- Kafka消费时报错:Producer connection to xxx:9092 unsuccessful
使用kafka消费数据时报Producer错误,具体错误如下: kafka.producer.SyncProducer:103 Producer connection to xxx:9092 unsu ...
- [Codeforces757G]Can Bash Save the Day?——动态点分治(可持久化点分树)
题目链接: Codeforces757G 题目大意:给出一棵n个点的树及一个1~n的排列pi,边有边权,有q次操作: 1 l r x 求 $\sum\limits_{i=l}^{r}dis(p_{i} ...
- win10安装MySql 5.7.23
下载安装 因为Django2.1不再支持MySQL5.5,这里需要重新安装一下MySQL 首先去官网下载 这里使用的是msi版本 https://dev.mysql.com/downloads/win ...