Name | rtsf-web JSON |
Version |
1.3.7
JSON |
| download |
home_page | https://github.com/RockFeng0/rtsf-web |
Summary | only for web ui test, base on rtsf |
upload_time | 2024-04-24 06:28:08 |
maintainer | None |
docs_url | None |
author | 罗科峰 |
requires_python | !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4,>=2.7 |
license | MIT |
keywords |
test
web
ui
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# rtsf-web
基于rtsf测试框架和selenium程序框架,关键字驱动Web UI层面,进行自动化的功能测试
## 环境准备
### 安装浏览器驱动和下载selenium-server.jar
1. 安装浏览器
2. 下载浏览器官方驱动
3. 设置环境变量,确保驱动可被调用
4. 下载 selenium-server
经过多年的发展WebDriver已经成为了事实上的标准,现在每种浏览器都有独立的官方驱动文件了
Browser | Component
--------|----------
Chrome |[chromedriver(.exe)](http://chromedriver.storage.googleapis.com/index.html)
Internet Explorer |[IEDriverServer.exe](http://selenium-release.storage.googleapis.com/index.html)
Edge |[MicrosoftWebDriver.msi](http://go.microsoft.com/fwlink/?LinkId=619687)
Firefox 47+ |[geckodriver(.exe)](https://github.com/mozilla/geckodriver/releases/)
PhantomJS |[phantomjs(.exe)](http://phantomjs.org/)
Opera |[operadriver(.exe)](https://github.com/operasoftware/operachromiumdriver/releases)
Safari |[SafariDriver.safariextz](http://selenium-release.storage.googleapis.com/index.html)
**selenium-server** |[selenium-server-standalone.jar](http://selenium-release.storage.googleapis.com/index.html)
### 安装rtsf-web
pip install rtsf-web
## 简单使用
使用rtsf-web简化selenium的使用
1. 本地浏览器驱动
```
import webuidriver
driver = webuidriver.Chrome() # 返回的driver 是selenium原生对象
driver.get("http://www.baidu.com")
driver.web_driver_wait(timeout=10).until(lambda dr: dr.title == "百度一下,你就知道") # WebDriverWait.until
# until_find.element_by_id(value, timeout=10, wait_displayed=False),返回selenium WebElement原生对象
driver.until_find.element_by_id("kw").send_keys("hello world.")
# until_find.elements_by_css_selector(value, index=0, timeout=10),返回selenium WebElement原生对象, 默认返回index指定元素
driver.until_find.elements_by_css_selector("input.bg.s_btn").click()
driver.close()
driver.quit()
```
2. 分布式浏览器驱动(selenium grid)
```
# PC A(192.168.1.1) 运行命令: wrhub.exe selenium-server-standalone-3.14.0.jar --port 4444
# PC B(192.168.1.2) 运行命令: wrnode.exe selenium-server-standalone-3.14.0.jar --port 5555 --hub-ip 192.168.1.1 --hub-port 4444
import webuidriver
from webuidriver.remote.SeleniumHatch import SeleniumHatch
executors = SeleniumHatch.get_remote_executors("192.168.1.1", 4444)
chrome_capabilities = SeleniumHatch.get_remote_browser_capabilities(browser="chrome")
driver = webuidriver.Remote(executors[0], desired_capabilities=chrome_capabilities)
driver.get("http://www.baidu.com")
driver.web_driver_wait(timeout=10).until(lambda dr: dr.title == "百度一下,你就知道") # WebDriverWait.until
driver.until_find.element_by_id("kw").send_keys("hello world.")
driver.until_find.elements_by_css_selector("input.bg.s_btn").click()
driver.close()
driver.quit()
```
3. 给浏览器添加参数(Options)
```
import webuidriver
from webuidriver.chrome.options import ChromeArguments
opt = webuidriver.ChromeOptions()
opt.add_argument(ChromeArguments.NO_IMAGES) # 禁用图片加载
opt.add_argument(ChromeArguments.HEADLESS) # 无界面模式
opt.add_argument(ChromeArguments.INCOGNITO) # 隐身模式
opt.add_argument(ChromeArguments.WINDOW_SIZE) # 置窗口尺寸(1024x650)
opt.add_argument(ChromeArguments.DISABLE_GPU) # 禁用gpu渲染
driver = webuidriver.Chrome(options=opt)
# driver = webuidriver.Remote(executor, desired_capabilities=opt.to_capabilities())
```
## 详细介绍
介绍如何使用rtsf-web进行YAML格式web UI的自动化测试用例编写,rtsf-web是rtsf框架的插件,所以,基本遵循rtsf的YAML格式约定。
[查看rtsf项目用法](https://github.com/RockFeng0/rtsf)
## 命令介绍
安装完成后,有两个命令用于执行yaml测试用例:
- wldriver命令,web localhost driver,一般情况下,都是用这个命令执行yaml用例
- wrdriver命令,web remote driver, 分布式部署的grid模式下,使用该命令运行yaml用例,它可以指定任意hub中的所有node机器,并在所有这些机器上运行用例。
安装完成后,有两个命令用于部署selenium grid模式:
- wrhub命令,设置运行该命令的当前pc为一个hub,允许node机器接入
- wrnode命令, 设置运行该命令的当前pc为一个node,需要接入一个hub
### 命令参数介绍
使用命令前,几个注意事项:
1. 执行前,注意下selenium的执行环境, rtsf-web限定了两中浏览器(chrome和firefox)
2. 谷歌浏览器,按照selenium的文档介绍,自行下载chromedriver.exe并配置
3. 火狐浏览器,按照selenium的文档介绍,版本高的,自行下载geckodriver.exe并配置
#### wldriver(web local driver)本地执行
wldriver直接使用selenium webdriver中各个浏览器的驱动,比如webdriver.Chrome等
查看帮助: wldriver -h
选填:
- 设置浏览器(chrome、firefox),默认是谷歌浏览器: --browser chrome
- 设置浏览器下载文件的路径,默认值是浏览器的设置: --download-path c:\downloads
- 设置火狐是否使用geckodriver.exe,默认值是False: --marionette False
![wldriver-h.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wldriver-h.png)
#### wrhub
简单理解下hub, 玩局域网游戏,我们先要建立主机,那么hub可以理解为主机的概念
查看帮助: wrhub -h
选填:
- 设置HUB监听端口,默认是4444: --port 4444
- 指定java.exe路径,默认(已配置java环境变量): --java-path java
```
# start hub A: 192.168.0.1
wrhub c:\selenium-server-standalone-3.14.0.jar --port 4444 --java-path C:\tmp\Java\jdk1.8.0_161\bin\java.exe
```
![wrhub-command.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wrhub-command.png)
#### wrnode
简单理解下node, 游戏主机创建好,玩家需要加入,那么node可以理解为加入主机的玩家
查看帮助: wrnode -h
选填:
- 设置NODE监听端口,默认是5555: --port 5555
- 执行连接hub的ip,默认是localhost: --hub-ip 127.0.0.1
- 执行连接hub的,默认是4444: --hub-port 4444
- 指定java.exe路径,默认(已配置java环境变量): --java-path java
```
# start node B: 192.168.0.1 这个node机器的ip跟hub A一样,主机也可以是玩家
wrnode c:\selenium-server-standalone-3.14.0.jar --port 5555 --hub-ip 192.168.0.1 --hub-port 4444 --java-path C:\tmp\Java\jdk1.8.0_161\bin\java.exe
# start node C: 192.168.0.2
wrnode c:\selenium-server-standalone-3.14.0.jar --port 5555 --hub-ip 192.168.0.1 --hub-port 4444 --java-path C:\tmp\Java\jdk1.8.0_161\bin\java.exe
```
![wrnode-command.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wrnode-command.png)
#### wrdriver(web remote driver)远程执行
wrdriver是指使用webdriver.Remote驱动各个selenium grid模式下的浏览器进行测试
查看帮助: wrdriver -h
选填:
- 设置浏览器(chrome、firefox),默认是谷歌浏览器: --browser chrome
- 设置浏览器下载文件的路径,默认值是浏览器的设置: --download-path c:\downloads
- 设置火狐是否使用geckodriver.exe,默认值是False: --marionette False
- 设置HUB IP,默认是localhost: --ip 127.0.0.1
- 设置HUB PORT,默认是4444: --port 4444
```
# run web remote case. 简单理解, 已连接上主机的玩家,会接收到test_case游戏
wrdriver C:\f_disk\BaiduNetdiskDownload\rtsf-web\tests\data\test_case.yaml --browser chrome --ip 192.168.0.1 --port 4444
```
简单理解下,创建了主机,玩家也上线了,wrdriver将指定的游戏异步发送给这些玩家
![wrdriver-command.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wrdriver-command.png)
## rtsf-web的约定
依据rtsf的yaml约定模板,我们在steps中,为rtsf-http约定了一个规则,以便识别为Web UI自动化测试, 如下
```
steps:
- webdriver:
by:
value:
index:
timeout:
action:
- webdriver:
action:
...
```
> action必填,其他选填; 其中by的值依据selenium为: id、xpath、link text、partial link text、name、tag name、class name、css selector
## rtsf-web常用的yaml函数
### Web methods --> 用于操作浏览器
Web functions | 参数介绍 | 描述
--------------|----------|-----
AlertAccept() | |点击alert弹窗的Accept(确定)
AlertDismiss() | |点击alert弹窗的Dismiss(取消)
AlertSendKeys(value) | |向alert弹窗中输入信息
Back() | |浏览器后退
Forward() | |浏览器前进
IESkipCertError() | |IE Skip SSL Cert Error
Js(script) | |浏览器执行js脚本
Maximize() | |浏览器最大化
NavigateTo(url) | |浏览器打开url
NewTab() | |浏览器新开标签页,并将所有焦点指向该标签页
PageSource() | |当前页面源码
Refresh() | |浏览器刷新当前页面
ScreenShoot(pic_path)| |截图当前页面,并为pic_path
ScrollTo(x,y) | |移动滚动条至(x,y),如下,X-Y-top : ScrollTo(、,"0"); X-bottom: ScrollTo("10000","0");Y-bottom: ScrollTo("0","10000")
SetWindowSize(width, height)| |设置浏览器窗口大小
SwitchToAlert() | |切换浏览器焦点至alert弹窗
SwitchToDefaultFrame() | |切换浏览器焦点至默认frame框, 比如打开的页面有多个iframe的情况
SwitchToDefaultWindow() | |切换浏览器焦点至默认window窗,比如多个标签页窗的情况
SwitchToNewFrame(frame_name)| |切换浏览器焦点至frame_name框
SwitchToNewWindow() | |切换浏览器焦点至新window窗
WebClose() | |关闭浏览器当前窗口
WebQuit() | |Quits the driver and closes every associated window.
<!-- 注释, 不建议 使用 SetControl定位元素
### 元素定位相关操作
<table>
<tr>
<th>WebElement methods</th>
<th>参数介绍</th>
<th>描述</th>
</tr>
<tr>
<td>GetControl()</td>
<td> </td>
<td>获取element controls,返回字典,如:{"by":None,"value":None,"index":0,"timeout":10}</td>
</tr>
<tr>
<td rowspan="4">SetControl(by,value,index,timeout)</td>
<td>by: 指selenium的寻找元素的方式("id", "xpath", "link text","partial link text","name", "tag name", "class name", "css selector"),默认为None</td>
<td rowspan="4">设置取element controls</td>
</tr>
<tr>
<td>value: 与by配对使用,相应by的值</td>
</tr>
<tr>
<td>index: 索引值,默认为0,即第一个, 如果by,value组合找到很多元素,通过索引index指定一个</td>
</tr>
<tr>
<td>timeout: 超时时间,默认10,即10秒,如果by,value组合寻找元素超过10秒,超时报错</td>
</tr>
</table>
-->
### WebContext methods --> 用于上下文管理
```
DyAttrData(name,attr) # -> 属性-动态存储变量,适用于,保存UI元素属性值。name-变量名称,attr为UI元素的属性名称,【UI元素】
DyJsonData(name,sequence) # -> json-动态存储变量,适用于,保存页面返回json中的指定值。 name-变量名称,sequence是指访问json的序列串
示例,页面返回 {"a":1,
"b":[1,2,3,4],
"c":{"d":5,"e":6},
"f":{"g":[7,8,9]},
"h":[{"i":10,"j":11},{"k":12}]
}
DyJsonData("var1","a") #var1值为 1
DyJsonData("var2","b.3") #var2值为 4
DyJsonData("var3","f.g.2") #var3值为 9
DyJsonData("var4","h.0.j") #var4值为 11
DyStrData(name, regx, index) # -> 字符串-动态存储变量,适用于,保存页面html中指定的值。 name-变量名称,regx已编译的正则表达式,index指定索引,默认0
GetAttribute(attr) # -> 获取元素指定属性的值, 【UI元素】
GetText() # -> 获取元素text值,【UI元素】
GetVar(name) # -> 获取指定变量的值
SetVar(name,value) # -> 设置指定变量的值
```
### WebWait methods --> 用于时间的控制
```
TimeSleep(seconds) # -> 指定等待时间(秒钟)
WaitForAppearing() # -> 等待元素出现(可能是隐藏,不可见的),【UI元素】
WaitForDisappearing() # -> 等待元素消失,【UI元素】
WaitForVisible() # -> 等待元素可见,【UI元素】
```
### WebVerify methods --> 用于验证
```
VerifyAlertText(text) # -> 验证alert弹窗,包含文本text
VerifyElemAttr(attr_name,expect_value) # -> 验证元素属性attr_name的值,包含值expect_value,【UI元素】
VerifyElemCounts(num) # -> 验证元素数量为num,【UI元素】
VerifyElemEnabled() # -> 验证元素是enabled,【UI元素】
VerifyElemInnerHtml(expect_text) # -> 验证元素innerHtml中,包含期望文本, 【UI元素】
VerifyElemNotEnabled() # -> 验证元素是Not Enabled, 【UI元素】
VerifyElemNotVisible() # -> 验证元素是不可见的,【UI元素】
VerifyElemVisible() # -> 验证元素是可见的, 【UI元素】
VerifyTitle(title) # -> 验证浏览器标题为title
VerifyURL(url) # -> 验证浏览器当前url为期望值
```
### WebActions methods --> 用于操作UI元素
```
Alt(key) # -> 在指定元素上执行alt组合事件,【UI元素】
Backspace() # -> 在指定输入框发送回退键,【UI元素】
Click() # -> 在指定元素上,左键点击 1次,【UI元素】
ClickAndHold() # -> 在指定元素上, 按压press住,【UI元素】
Ctrl(key) # -> 在指定元素上执行ctrl组合键事件,【UI元素】
DeSelectByIndex(index) # -> 通过索引,取消选择下拉框选项,【UI元素】
DeSelectByText(text) # -> 通过文本值,取消选择下拉框选项,【UI元素】
DeSelectByValue(value) # -> 通过value值,取消选择下拉框选项,【UI元素】
DoubleClick() # -> 鼠标左键点击2次,【UI元素】
Enter() # -> 在指定输入框发送回回车键,【UI元素】
Escape() # -> 在指定输入框发送回退出键,【UI元素】
Focus() # -> 在指定输入框发送 Null,用于设置焦点,【UI元素】
MouseOver() # -> 指定元素上,鼠标悬浮,【UI元素】
MoveAndDropTo() # -> 暂不支持
ReleaseClick() # -> 在指定元素上,释放按压操作,【UI元素】
RightClick() # -> 在指定元素上,鼠标右键点击1次,【UI元素】
SelectByIndex(index) # -> 通过索引,选择下拉框选项,【UI元素】
SelectByText(text) # -> 通过文本值,选择下拉框选项,【UI元素】
SelectByValue(value) # -> 通过value值,选择下拉框选项,【UI元素】
SendKeys(value) # -> 在指定元素上,输入文本,【UI元素】
Space() # -> 在指定元素上,发送空格,【UI元素】
Tab() # -> 在指定元素上,发送回制表键,【UI元素】
Upload(filename) # -> 暂不支持。非原生,需要第三方工具
UploadType(file_path) # -> 上传文件,仅原生file文件框, 如: <input type="file" ...>, 【UI元素】
```
## 自定义,yaml函数和变量
在case同级目录中,创建 preference.py, 该文件所定义的 变量、函数,可以被动态加载和引用, 具体参见rtsf的介绍
## 数据驱动与分层用例
在[rtsf](https://github.com/RockFeng0/rtsf)项目中,已经有了详细的介绍,rtsf-web也适用
## 简单实例
依据rtsf和rtsf-web的约定, 做了几个web ui测试的示例
### 常规测试项目
常规: 运行一个 yaml文件 或者 一个存放yaml文件的文件夹
1. 写一个yaml文件
```
# test_case.yaml
- project:
name: xxx系统
module: 登陆模块-功能测试
- case:
name: web_auto_test_demo
glob_var:
url1: https://www.baidu.com
url2: https://www.sina.com
pre_command:
- ${NavigateTo($url1)}
steps:
- webdriver:
action: ${NavigateTo($url2)}
- webdriver:
action: ${ScrollTo(0, 1000)}
- webdriver:
action: ${TimeSleep(1)}
- webdriver:
action: ${Refresh()}
- webdriver:
action: ${NewTab($url1)}
- webdriver:
by: css selector
value: '#kw'
index: 0
timeout: 10
action: ${SendKeys(123)}
- webdriver:
action: ${TimeSleep(1)}
- webdriver:
by: id
value: su
action: ${DyAttrData(id_su_value, value)}
- webdriver:
action: ${TimeSleep(1)}
- webdriver:
by: id
value: su
action: ${VerifyElemAttr(value, $id_su_value)}
- webdriver:
action: ${WebClose()}
post_command:
- ${WebQuit()}
```
2. 执行这个用例文件
执行有两种方式:
- run with selenium webdriver
```
wldriver test_case.yaml
```
- for selenium grid, run with selenium remote
```
# Terminal 1
wrhub c:\selenium-server-standalone-3.14.0.jar
# Terminal 2
wrnode c:\selenium-server-standalone-3.14.0.jar
# Terminal 3
wrdriver test_case.yaml
```
### 并行的测试项目
您可以选择,在多台设备上,使用wldriver运行不同模块的用例,然后,在每台机器上面,去收集报告,如果,这些设备离你很远,我想就鞭长莫及了,更加优雅的方式是:
首先,假设,所有机器,都已经安装好了环境
1. 划分模块用例,比如,我分了三个并行的测试模块用例A,B,C
2. 用一台机器作为hub,分别为这三个模块用例设置端口,比如: 192.168.1.2:6000,192.168.1.2:7000,192.168.1.2:8000
3. 另外找三台机器作为node,分别连上步骤2的hub
4. 在任意一台机器上,开启三个终端,执行下述命令,最后,您可以下达执行命令的机器上面,收集到所有报告
```
wrdriver c:\A --ip 192.168.1.2 --port 6000
wrdriver c:\B --ip 192.168.1.2 --port 7000
wrdriver c:\C --ip 192.168.1.2 --port 8000
```
## 推荐获取控件的工具
web ui控件元素的获取,遵循selenium的规则,可以通过下述方式来定位元素控件: id、xpath、link text、partial link text、name、tag name、class name、css selector
推荐常用的工具,一般是 Firefox 或者 Chrome 等浏览器的开发者工具。如下图,使用chrome开发模式,采用css和xpath两种方式定位输入框:
![chrome-deployment-tools.gif](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/chrome-deployment-tools.gif)
另一个工具,selenium IDE,官方推出的带有界面的工具
![selenium-ide.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/selenium-ide.png)
那么,我为什么不推荐使用,Selenium IDE? 从selenium1.0开始,selenium ide曾经给我惊艳,可以录制、定位、生成脚本等,很优秀,但是selenium2.0后,再也没有用了。一方面由于是基于旧技术实现,在火狐55及之后的新版本上不再支持了,虽然很好用,但是退出历史舞台了; 另一方面,firefox和chrome等浏览器,web开发工具功能强大,安装简单,对元素的定位和调试提供了非常便捷的方式。
Raw data
{
"_id": null,
"home_page": "https://github.com/RockFeng0/rtsf-web",
"name": "rtsf-web",
"maintainer": null,
"docs_url": null,
"requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4,>=2.7",
"maintainer_email": null,
"keywords": "test web ui",
"author": "\u7f57\u79d1\u5cf0",
"author_email": "lkf20031988@163.com",
"download_url": "https://files.pythonhosted.org/packages/29/88/7137ce6d2033c68cd868252943725511bada96ef0f5088a7a01e5e4064e9/rtsf-web-1.3.7.tar.gz",
"platform": null,
"description": "# rtsf-web\r\n \u57fa\u4e8ertsf\u6d4b\u8bd5\u6846\u67b6\u548cselenium\u7a0b\u5e8f\u6846\u67b6\uff0c\u5173\u952e\u5b57\u9a71\u52a8Web UI\u5c42\u9762\uff0c\u8fdb\u884c\u81ea\u52a8\u5316\u7684\u529f\u80fd\u6d4b\u8bd5\r\n\r\n## \u73af\u5883\u51c6\u5907\r\n\r\n### \u5b89\u88c5\u6d4f\u89c8\u5668\u9a71\u52a8\u548c\u4e0b\u8f7dselenium-server.jar\r\n1. \u5b89\u88c5\u6d4f\u89c8\u5668\r\n2. \u4e0b\u8f7d\u6d4f\u89c8\u5668\u5b98\u65b9\u9a71\u52a8\r\n3. \u8bbe\u7f6e\u73af\u5883\u53d8\u91cf\uff0c\u786e\u4fdd\u9a71\u52a8\u53ef\u88ab\u8c03\u7528\r\n4. \u4e0b\u8f7d selenium-server\r\n\r\n\u7ecf\u8fc7\u591a\u5e74\u7684\u53d1\u5c55WebDriver\u5df2\u7ecf\u6210\u4e3a\u4e86\u4e8b\u5b9e\u4e0a\u7684\u6807\u51c6\uff0c\u73b0\u5728\u6bcf\u79cd\u6d4f\u89c8\u5668\u90fd\u6709\u72ec\u7acb\u7684\u5b98\u65b9\u9a71\u52a8\u6587\u4ef6\u4e86 \r\n\r\nBrowser | Component\r\n--------|----------\r\nChrome |[chromedriver(.exe)](http://chromedriver.storage.googleapis.com/index.html)\r\nInternet Explorer |[IEDriverServer.exe](http://selenium-release.storage.googleapis.com/index.html)\r\nEdge |[MicrosoftWebDriver.msi](http://go.microsoft.com/fwlink/?LinkId=619687)\r\nFirefox 47+ |[geckodriver(.exe)](https://github.com/mozilla/geckodriver/releases/)\r\nPhantomJS |[phantomjs(.exe)](http://phantomjs.org/)\r\nOpera |[operadriver(.exe)](https://github.com/operasoftware/operachromiumdriver/releases)\r\nSafari |[SafariDriver.safariextz](http://selenium-release.storage.googleapis.com/index.html)\r\n**selenium-server** |[selenium-server-standalone.jar](http://selenium-release.storage.googleapis.com/index.html)\r\n\r\n\r\n### \u5b89\u88c5rtsf-web\r\npip install rtsf-web\r\n\r\n## \u7b80\u5355\u4f7f\u7528\r\n\r\n\u4f7f\u7528rtsf-web\u7b80\u5316selenium\u7684\u4f7f\u7528\r\n\r\n1. \u672c\u5730\u6d4f\u89c8\u5668\u9a71\u52a8\r\n```\r\nimport webuidriver\r\ndriver = webuidriver.Chrome() # \u8fd4\u56de\u7684driver \u662fselenium\u539f\u751f\u5bf9\u8c61\r\ndriver.get(\"http://www.baidu.com\")\r\ndriver.web_driver_wait(timeout=10).until(lambda dr: dr.title == \"\u767e\u5ea6\u4e00\u4e0b\uff0c\u4f60\u5c31\u77e5\u9053\") # WebDriverWait.until\r\n\r\n# until_find.element_by_id(value, timeout=10, wait_displayed=False),\u8fd4\u56deselenium WebElement\u539f\u751f\u5bf9\u8c61\r\ndriver.until_find.element_by_id(\"kw\").send_keys(\"hello world.\")\r\n\r\n# until_find.elements_by_css_selector(value, index=0, timeout=10),\u8fd4\u56deselenium WebElement\u539f\u751f\u5bf9\u8c61, \u9ed8\u8ba4\u8fd4\u56deindex\u6307\u5b9a\u5143\u7d20\r\ndriver.until_find.elements_by_css_selector(\"input.bg.s_btn\").click()\r\ndriver.close()\r\ndriver.quit()\r\n```\r\n\r\n2. \u5206\u5e03\u5f0f\u6d4f\u89c8\u5668\u9a71\u52a8(selenium grid)\r\n```\r\n# PC A(192.168.1.1) \u8fd0\u884c\u547d\u4ee4: wrhub.exe selenium-server-standalone-3.14.0.jar --port 4444\r\n# PC B(192.168.1.2) \u8fd0\u884c\u547d\u4ee4: wrnode.exe selenium-server-standalone-3.14.0.jar --port 5555 --hub-ip 192.168.1.1 --hub-port 4444\r\n\r\nimport webuidriver\r\nfrom webuidriver.remote.SeleniumHatch import SeleniumHatch\r\n\r\nexecutors = SeleniumHatch.get_remote_executors(\"192.168.1.1\", 4444)\r\nchrome_capabilities = SeleniumHatch.get_remote_browser_capabilities(browser=\"chrome\")\r\ndriver = webuidriver.Remote(executors[0], desired_capabilities=chrome_capabilities)\r\ndriver.get(\"http://www.baidu.com\")\r\ndriver.web_driver_wait(timeout=10).until(lambda dr: dr.title == \"\u767e\u5ea6\u4e00\u4e0b\uff0c\u4f60\u5c31\u77e5\u9053\") # WebDriverWait.until\r\n\r\ndriver.until_find.element_by_id(\"kw\").send_keys(\"hello world.\")\r\ndriver.until_find.elements_by_css_selector(\"input.bg.s_btn\").click()\r\ndriver.close()\r\ndriver.quit()\r\n\r\n```\r\n\r\n3. \u7ed9\u6d4f\u89c8\u5668\u6dfb\u52a0\u53c2\u6570\uff08Options\uff09\r\n```\r\nimport webuidriver\r\nfrom webuidriver.chrome.options import ChromeArguments\r\nopt = webuidriver.ChromeOptions()\r\nopt.add_argument(ChromeArguments.NO_IMAGES) # \u7981\u7528\u56fe\u7247\u52a0\u8f7d\r\nopt.add_argument(ChromeArguments.HEADLESS) # \u65e0\u754c\u9762\u6a21\u5f0f\r\nopt.add_argument(ChromeArguments.INCOGNITO) # \u9690\u8eab\u6a21\u5f0f\r\nopt.add_argument(ChromeArguments.WINDOW_SIZE) # \u7f6e\u7a97\u53e3\u5c3a\u5bf8(1024x650)\r\nopt.add_argument(ChromeArguments.DISABLE_GPU) # \u7981\u7528gpu\u6e32\u67d3\r\n\r\ndriver = webuidriver.Chrome(options=opt)\r\n# driver = webuidriver.Remote(executor, desired_capabilities=opt.to_capabilities())\r\n```\r\n\r\n\r\n## \u8be6\u7ec6\u4ecb\u7ecd\r\n\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528rtsf-web\u8fdb\u884cYAML\u683c\u5f0fweb UI\u7684\u81ea\u52a8\u5316\u6d4b\u8bd5\u7528\u4f8b\u7f16\u5199\uff0crtsf-web\u662frtsf\u6846\u67b6\u7684\u63d2\u4ef6\uff0c\u6240\u4ee5\uff0c\u57fa\u672c\u9075\u5faartsf\u7684YAML\u683c\u5f0f\u7ea6\u5b9a\u3002 \r\n\r\n[\u67e5\u770brtsf\u9879\u76ee\u7528\u6cd5](https://github.com/RockFeng0/rtsf)\r\n\r\n## \u547d\u4ee4\u4ecb\u7ecd\r\n\r\n\u5b89\u88c5\u5b8c\u6210\u540e\uff0c\u6709\u4e24\u4e2a\u547d\u4ee4\u7528\u4e8e\u6267\u884cyaml\u6d4b\u8bd5\u7528\u4f8b: \r\n- wldriver\u547d\u4ee4\uff0cweb localhost driver\uff0c\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u90fd\u662f\u7528\u8fd9\u4e2a\u547d\u4ee4\u6267\u884cyaml\u7528\u4f8b\r\n- wrdriver\u547d\u4ee4\uff0cweb remote driver\uff0c \u5206\u5e03\u5f0f\u90e8\u7f72\u7684grid\u6a21\u5f0f\u4e0b\uff0c\u4f7f\u7528\u8be5\u547d\u4ee4\u8fd0\u884cyaml\u7528\u4f8b\uff0c\u5b83\u53ef\u4ee5\u6307\u5b9a\u4efb\u610fhub\u4e2d\u7684\u6240\u6709node\u673a\u5668\uff0c\u5e76\u5728\u6240\u6709\u8fd9\u4e9b\u673a\u5668\u4e0a\u8fd0\u884c\u7528\u4f8b\u3002\r\n\r\n\u5b89\u88c5\u5b8c\u6210\u540e\uff0c\u6709\u4e24\u4e2a\u547d\u4ee4\u7528\u4e8e\u90e8\u7f72selenium grid\u6a21\u5f0f\uff1a\r\n- wrhub\u547d\u4ee4\uff0c\u8bbe\u7f6e\u8fd0\u884c\u8be5\u547d\u4ee4\u7684\u5f53\u524dpc\u4e3a\u4e00\u4e2ahub\uff0c\u5141\u8bb8node\u673a\u5668\u63a5\u5165\r\n- wrnode\u547d\u4ee4\uff0c \u8bbe\u7f6e\u8fd0\u884c\u8be5\u547d\u4ee4\u7684\u5f53\u524dpc\u4e3a\u4e00\u4e2anode\uff0c\u9700\u8981\u63a5\u5165\u4e00\u4e2ahub\r\n\r\n### \u547d\u4ee4\u53c2\u6570\u4ecb\u7ecd\r\n\r\n\u4f7f\u7528\u547d\u4ee4\u524d\uff0c\u51e0\u4e2a\u6ce8\u610f\u4e8b\u9879\uff1a\r\n1. \u6267\u884c\u524d\uff0c\u6ce8\u610f\u4e0bselenium\u7684\u6267\u884c\u73af\u5883\uff0c rtsf-web\u9650\u5b9a\u4e86\u4e24\u4e2d\u6d4f\u89c8\u5668(chrome\u548cfirefox)\r\n2. \u8c37\u6b4c\u6d4f\u89c8\u5668\uff0c\u6309\u7167selenium\u7684\u6587\u6863\u4ecb\u7ecd\uff0c\u81ea\u884c\u4e0b\u8f7dchromedriver.exe\u5e76\u914d\u7f6e\r\n3. \u706b\u72d0\u6d4f\u89c8\u5668\uff0c\u6309\u7167selenium\u7684\u6587\u6863\u4ecb\u7ecd\uff0c\u7248\u672c\u9ad8\u7684\uff0c\u81ea\u884c\u4e0b\u8f7dgeckodriver.exe\u5e76\u914d\u7f6e\r\n\r\n#### wldriver(web local driver)\u672c\u5730\u6267\u884c\r\nwldriver\u76f4\u63a5\u4f7f\u7528selenium webdriver\u4e2d\u5404\u4e2a\u6d4f\u89c8\u5668\u7684\u9a71\u52a8\uff0c\u6bd4\u5982webdriver.Chrome\u7b49\r\n\r\n\u67e5\u770b\u5e2e\u52a9: wldriver -h\r\n\u9009\u586b\uff1a\r\n- \u8bbe\u7f6e\u6d4f\u89c8\u5668(chrome\u3001firefox),\u9ed8\u8ba4\u662f\u8c37\u6b4c\u6d4f\u89c8\u5668: --browser chrome\r\n- \u8bbe\u7f6e\u6d4f\u89c8\u5668\u4e0b\u8f7d\u6587\u4ef6\u7684\u8def\u5f84\uff0c\u9ed8\u8ba4\u503c\u662f\u6d4f\u89c8\u5668\u7684\u8bbe\u7f6e: --download-path c:\\downloads\r\n- \u8bbe\u7f6e\u706b\u72d0\u662f\u5426\u4f7f\u7528geckodriver.exe,\u9ed8\u8ba4\u503c\u662fFalse: --marionette False\r\n\r\n![wldriver-h.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wldriver-h.png)\r\n\r\n#### wrhub\r\n\u7b80\u5355\u7406\u89e3\u4e0bhub, \u73a9\u5c40\u57df\u7f51\u6e38\u620f\uff0c\u6211\u4eec\u5148\u8981\u5efa\u7acb\u4e3b\u673a\uff0c\u90a3\u4e48hub\u53ef\u4ee5\u7406\u89e3\u4e3a\u4e3b\u673a\u7684\u6982\u5ff5\r\n\r\n\u67e5\u770b\u5e2e\u52a9: wrhub -h\r\n\u9009\u586b\uff1a\r\n- \u8bbe\u7f6eHUB\u76d1\u542c\u7aef\u53e3,\u9ed8\u8ba4\u662f4444: --port 4444\r\n- \u6307\u5b9ajava.exe\u8def\u5f84,\u9ed8\u8ba4(\u5df2\u914d\u7f6ejava\u73af\u5883\u53d8\u91cf): --java-path java\r\n\r\n```\r\n# start hub A: 192.168.0.1\r\nwrhub c:\\selenium-server-standalone-3.14.0.jar --port 4444 --java-path C:\\tmp\\Java\\jdk1.8.0_161\\bin\\java.exe\r\n```\r\n\r\n![wrhub-command.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wrhub-command.png)\r\n\r\n#### wrnode\r\n\u7b80\u5355\u7406\u89e3\u4e0bnode, \u6e38\u620f\u4e3b\u673a\u521b\u5efa\u597d\uff0c\u73a9\u5bb6\u9700\u8981\u52a0\u5165\uff0c\u90a3\u4e48node\u53ef\u4ee5\u7406\u89e3\u4e3a\u52a0\u5165\u4e3b\u673a\u7684\u73a9\u5bb6\r\n\r\n\u67e5\u770b\u5e2e\u52a9: wrnode -h\r\n\u9009\u586b\uff1a\r\n- \u8bbe\u7f6eNODE\u76d1\u542c\u7aef\u53e3,\u9ed8\u8ba4\u662f5555: --port 5555\r\n- \u6267\u884c\u8fde\u63a5hub\u7684ip,\u9ed8\u8ba4\u662flocalhost: --hub-ip 127.0.0.1\r\n- \u6267\u884c\u8fde\u63a5hub\u7684,\u9ed8\u8ba4\u662f4444: --hub-port 4444\r\n- \u6307\u5b9ajava.exe\u8def\u5f84,\u9ed8\u8ba4(\u5df2\u914d\u7f6ejava\u73af\u5883\u53d8\u91cf): --java-path java\r\n\r\n```\r\n# start node B: 192.168.0.1 \u8fd9\u4e2anode\u673a\u5668\u7684ip\u8ddfhub A\u4e00\u6837\uff0c\u4e3b\u673a\u4e5f\u53ef\u4ee5\u662f\u73a9\u5bb6\r\nwrnode c:\\selenium-server-standalone-3.14.0.jar --port 5555 --hub-ip 192.168.0.1 --hub-port 4444 --java-path C:\\tmp\\Java\\jdk1.8.0_161\\bin\\java.exe\r\n\r\n# start node C: 192.168.0.2\r\nwrnode c:\\selenium-server-standalone-3.14.0.jar --port 5555 --hub-ip 192.168.0.1 --hub-port 4444 --java-path C:\\tmp\\Java\\jdk1.8.0_161\\bin\\java.exe\r\n```\r\n\r\n![wrnode-command.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wrnode-command.png)\r\n\r\n#### wrdriver(web remote driver)\u8fdc\u7a0b\u6267\u884c\r\nwrdriver\u662f\u6307\u4f7f\u7528webdriver.Remote\u9a71\u52a8\u5404\u4e2aselenium grid\u6a21\u5f0f\u4e0b\u7684\u6d4f\u89c8\u5668\u8fdb\u884c\u6d4b\u8bd5\r\n\r\n\u67e5\u770b\u5e2e\u52a9: wrdriver -h\r\n\u9009\u586b\uff1a\r\n- \u8bbe\u7f6e\u6d4f\u89c8\u5668(chrome\u3001firefox),\u9ed8\u8ba4\u662f\u8c37\u6b4c\u6d4f\u89c8\u5668: --browser chrome\r\n- \u8bbe\u7f6e\u6d4f\u89c8\u5668\u4e0b\u8f7d\u6587\u4ef6\u7684\u8def\u5f84\uff0c\u9ed8\u8ba4\u503c\u662f\u6d4f\u89c8\u5668\u7684\u8bbe\u7f6e: --download-path c:\\downloads\r\n- \u8bbe\u7f6e\u706b\u72d0\u662f\u5426\u4f7f\u7528geckodriver.exe,\u9ed8\u8ba4\u503c\u662fFalse: --marionette False\r\n- \u8bbe\u7f6eHUB IP,\u9ed8\u8ba4\u662flocalhost: --ip 127.0.0.1\r\n- \u8bbe\u7f6eHUB PORT,\u9ed8\u8ba4\u662f4444: --port 4444\r\n\r\n```\r\n# run web remote case. \u7b80\u5355\u7406\u89e3\uff0c \u5df2\u8fde\u63a5\u4e0a\u4e3b\u673a\u7684\u73a9\u5bb6\uff0c\u4f1a\u63a5\u6536\u5230test_case\u6e38\u620f\r\nwrdriver C:\\f_disk\\BaiduNetdiskDownload\\rtsf-web\\tests\\data\\test_case.yaml --browser chrome --ip 192.168.0.1 --port 4444\r\n```\r\n\r\n\u7b80\u5355\u7406\u89e3\u4e0b\uff0c\u521b\u5efa\u4e86\u4e3b\u673a\uff0c\u73a9\u5bb6\u4e5f\u4e0a\u7ebf\u4e86\uff0cwrdriver\u5c06\u6307\u5b9a\u7684\u6e38\u620f\u5f02\u6b65\u53d1\u9001\u7ed9\u8fd9\u4e9b\u73a9\u5bb6\r\n![wrdriver-command.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/wrdriver-command.png)\r\n\r\n\r\n## rtsf-web\u7684\u7ea6\u5b9a\r\n\r\n\u4f9d\u636ertsf\u7684yaml\u7ea6\u5b9a\u6a21\u677f\uff0c\u6211\u4eec\u5728steps\u4e2d\uff0c\u4e3artsf-http\u7ea6\u5b9a\u4e86\u4e00\u4e2a\u89c4\u5219\uff0c\u4ee5\u4fbf\u8bc6\u522b\u4e3aWeb UI\u81ea\u52a8\u5316\u6d4b\u8bd5\uff0c \u5982\u4e0b\r\n\r\n```\r\nsteps:\r\n - webdriver:\r\n by: \r\n value:\r\n index:\r\n timeout:\r\n action:\r\n - webdriver:\r\n action:\r\n ...\r\n```\r\n> action\u5fc5\u586b\uff0c\u5176\u4ed6\u9009\u586b; \u5176\u4e2dby\u7684\u503c\u4f9d\u636eselenium\u4e3a: id\u3001xpath\u3001link text\u3001partial link text\u3001name\u3001tag name\u3001class name\u3001css selector\r\n\r\n## rtsf-web\u5e38\u7528\u7684yaml\u51fd\u6570\r\n\r\n### Web methods --> \u7528\u4e8e\u64cd\u4f5c\u6d4f\u89c8\u5668\r\n\r\nWeb functions | \u53c2\u6570\u4ecb\u7ecd | \u63cf\u8ff0\r\n--------------|----------|-----\r\nAlertAccept() | |\u70b9\u51fbalert\u5f39\u7a97\u7684Accept(\u786e\u5b9a)\r\nAlertDismiss() | |\u70b9\u51fbalert\u5f39\u7a97\u7684Dismiss(\u53d6\u6d88)\r\nAlertSendKeys(value) | |\u5411alert\u5f39\u7a97\u4e2d\u8f93\u5165\u4fe1\u606f\r\nBack() | |\u6d4f\u89c8\u5668\u540e\u9000\r\nForward() | |\u6d4f\u89c8\u5668\u524d\u8fdb\r\nIESkipCertError() | |IE Skip SSL Cert Error\r\nJs(script) | |\u6d4f\u89c8\u5668\u6267\u884cjs\u811a\u672c\r\nMaximize() | |\u6d4f\u89c8\u5668\u6700\u5927\u5316\r\nNavigateTo(url) | |\u6d4f\u89c8\u5668\u6253\u5f00url\r\nNewTab() | |\u6d4f\u89c8\u5668\u65b0\u5f00\u6807\u7b7e\u9875\uff0c\u5e76\u5c06\u6240\u6709\u7126\u70b9\u6307\u5411\u8be5\u6807\u7b7e\u9875\r\nPageSource() | |\u5f53\u524d\u9875\u9762\u6e90\u7801\r\nRefresh() | |\u6d4f\u89c8\u5668\u5237\u65b0\u5f53\u524d\u9875\u9762\r\nScreenShoot(pic_path)| |\u622a\u56fe\u5f53\u524d\u9875\u9762\uff0c\u5e76\u4e3apic_path\r\nScrollTo(x,y) | |\u79fb\u52a8\u6eda\u52a8\u6761\u81f3(x,y),\u5982\u4e0b\uff0cX-Y-top : ScrollTo(\u3001,\"0\"); X-bottom: ScrollTo(\"10000\",\"0\");Y-bottom: ScrollTo(\"0\",\"10000\")\r\nSetWindowSize(width, height)| |\u8bbe\u7f6e\u6d4f\u89c8\u5668\u7a97\u53e3\u5927\u5c0f\r\nSwitchToAlert() | |\u5207\u6362\u6d4f\u89c8\u5668\u7126\u70b9\u81f3alert\u5f39\u7a97\r\nSwitchToDefaultFrame() | |\u5207\u6362\u6d4f\u89c8\u5668\u7126\u70b9\u81f3\u9ed8\u8ba4frame\u6846, \u6bd4\u5982\u6253\u5f00\u7684\u9875\u9762\u6709\u591a\u4e2aiframe\u7684\u60c5\u51b5\r\nSwitchToDefaultWindow() | |\u5207\u6362\u6d4f\u89c8\u5668\u7126\u70b9\u81f3\u9ed8\u8ba4window\u7a97,\u6bd4\u5982\u591a\u4e2a\u6807\u7b7e\u9875\u7a97\u7684\u60c5\u51b5\r\nSwitchToNewFrame(frame_name)| |\u5207\u6362\u6d4f\u89c8\u5668\u7126\u70b9\u81f3frame_name\u6846\r\nSwitchToNewWindow() | |\u5207\u6362\u6d4f\u89c8\u5668\u7126\u70b9\u81f3\u65b0window\u7a97\r\nWebClose() | |\u5173\u95ed\u6d4f\u89c8\u5668\u5f53\u524d\u7a97\u53e3\r\nWebQuit() | |Quits the driver and closes every associated window.\r\n\r\n<!-- \u6ce8\u91ca\uff0c \u4e0d\u5efa\u8bae \u4f7f\u7528 SetControl\u5b9a\u4f4d\u5143\u7d20 \r\n### \u5143\u7d20\u5b9a\u4f4d\u76f8\u5173\u64cd\u4f5c\r\n\r\n<table>\r\n <tr>\r\n <th>WebElement methods</th>\r\n <th>\u53c2\u6570\u4ecb\u7ecd</th>\r\n <th>\u63cf\u8ff0</th>\r\n </tr>\r\n <tr>\r\n <td>GetControl()</td>\r\n <td> </td>\r\n <td>\u83b7\u53d6element controls,\u8fd4\u56de\u5b57\u5178\uff0c\u5982\uff1a{\"by\":None,\"value\":None,\"index\":0,\"timeout\":10}</td>\r\n </tr>\r\n <tr>\r\n <td rowspan=\"4\">SetControl(by,value,index,timeout)</td>\r\n <td>by: \u6307selenium\u7684\u5bfb\u627e\u5143\u7d20\u7684\u65b9\u5f0f(\"id\", \"xpath\", \"link text\",\"partial link text\",\"name\", \"tag name\", \"class name\", \"css selector\")\uff0c\u9ed8\u8ba4\u4e3aNone</td>\r\n <td rowspan=\"4\">\u8bbe\u7f6e\u53d6element controls</td>\r\n </tr>\r\n <tr>\r\n <td>value: \u4e0eby\u914d\u5bf9\u4f7f\u7528\uff0c\u76f8\u5e94by\u7684\u503c</td>\r\n </tr>\r\n <tr>\r\n <td>index: \u7d22\u5f15\u503c\uff0c\u9ed8\u8ba4\u4e3a0\uff0c\u5373\u7b2c\u4e00\u4e2a\uff0c \u5982\u679cby,value\u7ec4\u5408\u627e\u5230\u5f88\u591a\u5143\u7d20\uff0c\u901a\u8fc7\u7d22\u5f15index\u6307\u5b9a\u4e00\u4e2a</td>\r\n </tr>\r\n <tr>\r\n <td>timeout: \u8d85\u65f6\u65f6\u95f4\uff0c\u9ed8\u8ba410\uff0c\u537310\u79d2\uff0c\u5982\u679cby,value\u7ec4\u5408\u5bfb\u627e\u5143\u7d20\u8d85\u8fc710\u79d2\uff0c\u8d85\u65f6\u62a5\u9519</td>\r\n </tr> \r\n</table>\r\n-->\r\n\r\n### WebContext methods --> \u7528\u4e8e\u4e0a\u4e0b\u6587\u7ba1\u7406\r\n```\r\nDyAttrData(name,attr) # -> \u5c5e\u6027-\u52a8\u6001\u5b58\u50a8\u53d8\u91cf\uff0c\u9002\u7528\u4e8e\uff0c\u4fdd\u5b58UI\u5143\u7d20\u5c5e\u6027\u503c\u3002name-\u53d8\u91cf\u540d\u79f0\uff0cattr\u4e3aUI\u5143\u7d20\u7684\u5c5e\u6027\u540d\u79f0\uff0c\u3010UI\u5143\u7d20\u3011\r\nDyJsonData(name,sequence) # -> json-\u52a8\u6001\u5b58\u50a8\u53d8\u91cf\uff0c\u9002\u7528\u4e8e\uff0c\u4fdd\u5b58\u9875\u9762\u8fd4\u56dejson\u4e2d\u7684\u6307\u5b9a\u503c\u3002 name-\u53d8\u91cf\u540d\u79f0\uff0csequence\u662f\u6307\u8bbf\u95eejson\u7684\u5e8f\u5217\u4e32\r\n \u793a\u4f8b,\u9875\u9762\u8fd4\u56de {\"a\":1,\r\n \"b\":[1,2,3,4],\r\n \"c\":{\"d\":5,\"e\":6},\r\n \"f\":{\"g\":[7,8,9]},\r\n \"h\":[{\"i\":10,\"j\":11},{\"k\":12}]\r\n }\r\n DyJsonData(\"var1\",\"a\") #var1\u503c\u4e3a 1\r\n DyJsonData(\"var2\",\"b.3\") #var2\u503c\u4e3a 4\r\n DyJsonData(\"var3\",\"f.g.2\") #var3\u503c\u4e3a 9\r\n DyJsonData(\"var4\",\"h.0.j\") #var4\u503c\u4e3a 11\r\nDyStrData(name, regx, index) # -> \u5b57\u7b26\u4e32-\u52a8\u6001\u5b58\u50a8\u53d8\u91cf\uff0c\u9002\u7528\u4e8e\uff0c\u4fdd\u5b58\u9875\u9762html\u4e2d\u6307\u5b9a\u7684\u503c\u3002 name-\u53d8\u91cf\u540d\u79f0\uff0cregx\u5df2\u7f16\u8bd1\u7684\u6b63\u5219\u8868\u8fbe\u5f0f\uff0cindex\u6307\u5b9a\u7d22\u5f15\uff0c\u9ed8\u8ba40\r\nGetAttribute(attr) # -> \u83b7\u53d6\u5143\u7d20\u6307\u5b9a\u5c5e\u6027\u7684\u503c\uff0c \u3010UI\u5143\u7d20\u3011\r\nGetText() # -> \u83b7\u53d6\u5143\u7d20text\u503c\uff0c\u3010UI\u5143\u7d20\u3011\r\nGetVar(name) # -> \u83b7\u53d6\u6307\u5b9a\u53d8\u91cf\u7684\u503c\r\nSetVar(name,value) # -> \u8bbe\u7f6e\u6307\u5b9a\u53d8\u91cf\u7684\u503c\r\n```\r\n\r\n### WebWait methods --> \u7528\u4e8e\u65f6\u95f4\u7684\u63a7\u5236\r\n```\r\nTimeSleep(seconds) # -> \u6307\u5b9a\u7b49\u5f85\u65f6\u95f4(\u79d2\u949f)\r\nWaitForAppearing() # -> \u7b49\u5f85\u5143\u7d20\u51fa\u73b0(\u53ef\u80fd\u662f\u9690\u85cf\uff0c\u4e0d\u53ef\u89c1\u7684)\uff0c\u3010UI\u5143\u7d20\u3011\r\nWaitForDisappearing() # -> \u7b49\u5f85\u5143\u7d20\u6d88\u5931\uff0c\u3010UI\u5143\u7d20\u3011\r\nWaitForVisible() # -> \u7b49\u5f85\u5143\u7d20\u53ef\u89c1\uff0c\u3010UI\u5143\u7d20\u3011\r\n```\r\n\r\n### WebVerify methods --> \u7528\u4e8e\u9a8c\u8bc1\r\n```\r\nVerifyAlertText(text) # -> \u9a8c\u8bc1alert\u5f39\u7a97\uff0c\u5305\u542b\u6587\u672ctext\r\nVerifyElemAttr(attr_name,expect_value) # -> \u9a8c\u8bc1\u5143\u7d20\u5c5e\u6027attr_name\u7684\u503c\uff0c\u5305\u542b\u503cexpect_value,\u3010UI\u5143\u7d20\u3011\r\nVerifyElemCounts(num) # -> \u9a8c\u8bc1\u5143\u7d20\u6570\u91cf\u4e3anum,\u3010UI\u5143\u7d20\u3011\r\nVerifyElemEnabled() # -> \u9a8c\u8bc1\u5143\u7d20\u662fenabled\uff0c\u3010UI\u5143\u7d20\u3011\r\nVerifyElemInnerHtml(expect_text) # -> \u9a8c\u8bc1\u5143\u7d20innerHtml\u4e2d\uff0c\u5305\u542b\u671f\u671b\u6587\u672c\uff0c \u3010UI\u5143\u7d20\u3011\r\nVerifyElemNotEnabled() # -> \u9a8c\u8bc1\u5143\u7d20\u662fNot Enabled, \u3010UI\u5143\u7d20\u3011\r\nVerifyElemNotVisible() # -> \u9a8c\u8bc1\u5143\u7d20\u662f\u4e0d\u53ef\u89c1\u7684\uff0c\u3010UI\u5143\u7d20\u3011\r\nVerifyElemVisible() # -> \u9a8c\u8bc1\u5143\u7d20\u662f\u53ef\u89c1\u7684\uff0c \u3010UI\u5143\u7d20\u3011\r\nVerifyTitle(title) # -> \u9a8c\u8bc1\u6d4f\u89c8\u5668\u6807\u9898\u4e3atitle\r\nVerifyURL(url) # -> \u9a8c\u8bc1\u6d4f\u89c8\u5668\u5f53\u524durl\u4e3a\u671f\u671b\u503c\r\n```\r\n\r\n### WebActions methods --> \u7528\u4e8e\u64cd\u4f5cUI\u5143\u7d20\r\n```\r\nAlt(key) # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\u6267\u884calt\u7ec4\u5408\u4e8b\u4ef6\uff0c\u3010UI\u5143\u7d20\u3011\r\nBackspace() # -> \u5728\u6307\u5b9a\u8f93\u5165\u6846\u53d1\u9001\u56de\u9000\u952e\uff0c\u3010UI\u5143\u7d20\u3011\r\nClick() # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\uff0c\u5de6\u952e\u70b9\u51fb 1\u6b21\uff0c\u3010UI\u5143\u7d20\u3011\r\nClickAndHold() # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\uff0c \u6309\u538bpress\u4f4f\uff0c\u3010UI\u5143\u7d20\u3011\r\nCtrl(key) # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\u6267\u884cctrl\u7ec4\u5408\u952e\u4e8b\u4ef6\uff0c\u3010UI\u5143\u7d20\u3011\r\nDeSelectByIndex(index) # -> \u901a\u8fc7\u7d22\u5f15\uff0c\u53d6\u6d88\u9009\u62e9\u4e0b\u62c9\u6846\u9009\u9879\uff0c\u3010UI\u5143\u7d20\u3011\r\nDeSelectByText(text) # -> \u901a\u8fc7\u6587\u672c\u503c\uff0c\u53d6\u6d88\u9009\u62e9\u4e0b\u62c9\u6846\u9009\u9879\uff0c\u3010UI\u5143\u7d20\u3011\r\nDeSelectByValue(value) # -> \u901a\u8fc7value\u503c\uff0c\u53d6\u6d88\u9009\u62e9\u4e0b\u62c9\u6846\u9009\u9879\uff0c\u3010UI\u5143\u7d20\u3011\r\nDoubleClick() # -> \u9f20\u6807\u5de6\u952e\u70b9\u51fb2\u6b21\uff0c\u3010UI\u5143\u7d20\u3011\r\nEnter() # -> \u5728\u6307\u5b9a\u8f93\u5165\u6846\u53d1\u9001\u56de\u56de\u8f66\u952e,\u3010UI\u5143\u7d20\u3011\r\nEscape() # -> \u5728\u6307\u5b9a\u8f93\u5165\u6846\u53d1\u9001\u56de\u9000\u51fa\u952e,\u3010UI\u5143\u7d20\u3011\r\nFocus() # -> \u5728\u6307\u5b9a\u8f93\u5165\u6846\u53d1\u9001 Null,\u7528\u4e8e\u8bbe\u7f6e\u7126\u70b9\uff0c\u3010UI\u5143\u7d20\u3011\r\nMouseOver() # -> \u6307\u5b9a\u5143\u7d20\u4e0a\uff0c\u9f20\u6807\u60ac\u6d6e\uff0c\u3010UI\u5143\u7d20\u3011\r\nMoveAndDropTo() # -> \u6682\u4e0d\u652f\u6301\r\nReleaseClick() # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\uff0c\u91ca\u653e\u6309\u538b\u64cd\u4f5c\uff0c\u3010UI\u5143\u7d20\u3011\r\nRightClick() # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\uff0c\u9f20\u6807\u53f3\u952e\u70b9\u51fb1\u6b21\uff0c\u3010UI\u5143\u7d20\u3011\r\nSelectByIndex(index) # -> \u901a\u8fc7\u7d22\u5f15\uff0c\u9009\u62e9\u4e0b\u62c9\u6846\u9009\u9879\uff0c\u3010UI\u5143\u7d20\u3011\r\nSelectByText(text) # -> \u901a\u8fc7\u6587\u672c\u503c\uff0c\u9009\u62e9\u4e0b\u62c9\u6846\u9009\u9879\uff0c\u3010UI\u5143\u7d20\u3011\r\nSelectByValue(value) # -> \u901a\u8fc7value\u503c\uff0c\u9009\u62e9\u4e0b\u62c9\u6846\u9009\u9879\uff0c\u3010UI\u5143\u7d20\u3011\r\nSendKeys(value) # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a\uff0c\u8f93\u5165\u6587\u672c\uff0c\u3010UI\u5143\u7d20\u3011\r\nSpace() # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a,\u53d1\u9001\u7a7a\u683c\uff0c\u3010UI\u5143\u7d20\u3011\r\nTab() # -> \u5728\u6307\u5b9a\u5143\u7d20\u4e0a,\u53d1\u9001\u56de\u5236\u8868\u952e\uff0c\u3010UI\u5143\u7d20\u3011\r\nUpload(filename) # -> \u6682\u4e0d\u652f\u6301\u3002\u975e\u539f\u751f\uff0c\u9700\u8981\u7b2c\u4e09\u65b9\u5de5\u5177\r\nUploadType(file_path) # -> \u4e0a\u4f20\u6587\u4ef6\uff0c\u4ec5\u539f\u751ffile\u6587\u4ef6\u6846, \u5982\uff1a <input type=\"file\" ...>, \u3010UI\u5143\u7d20\u3011\r\n```\r\n\r\n\r\n## \u81ea\u5b9a\u4e49\uff0cyaml\u51fd\u6570\u548c\u53d8\u91cf\r\n\r\n\u5728case\u540c\u7ea7\u76ee\u5f55\u4e2d\uff0c\u521b\u5efa preference.py, \u8be5\u6587\u4ef6\u6240\u5b9a\u4e49\u7684 \u53d8\u91cf\u3001\u51fd\u6570\uff0c\u53ef\u4ee5\u88ab\u52a8\u6001\u52a0\u8f7d\u548c\u5f15\u7528\uff0c \u5177\u4f53\u53c2\u89c1rtsf\u7684\u4ecb\u7ecd\r\n\r\n## \u6570\u636e\u9a71\u52a8\u4e0e\u5206\u5c42\u7528\u4f8b\r\n\r\n\u5728[rtsf](https://github.com/RockFeng0/rtsf)\u9879\u76ee\u4e2d\uff0c\u5df2\u7ecf\u6709\u4e86\u8be6\u7ec6\u7684\u4ecb\u7ecd\uff0crtsf-web\u4e5f\u9002\u7528\r\n\r\n\r\n## \u7b80\u5355\u5b9e\u4f8b\r\n\r\n\u4f9d\u636ertsf\u548crtsf-web\u7684\u7ea6\u5b9a\uff0c \u505a\u4e86\u51e0\u4e2aweb ui\u6d4b\u8bd5\u7684\u793a\u4f8b\r\n\r\n### \u5e38\u89c4\u6d4b\u8bd5\u9879\u76ee\r\n\r\n\u5e38\u89c4\uff1a \u8fd0\u884c\u4e00\u4e2a yaml\u6587\u4ef6 \u6216\u8005 \u4e00\u4e2a\u5b58\u653eyaml\u6587\u4ef6\u7684\u6587\u4ef6\u5939\r\n\r\n1. \u5199\u4e00\u4e2ayaml\u6587\u4ef6\r\n\r\n```\r\n# test_case.yaml\r\n- project:\r\n name: xxx\u7cfb\u7edf\r\n module: \u767b\u9646\u6a21\u5757-\u529f\u80fd\u6d4b\u8bd5\r\n\r\n- case:\r\n name: web_auto_test_demo\r\n\r\n glob_var:\r\n url1: https://www.baidu.com\r\n url2: https://www.sina.com\r\n\r\n pre_command:\r\n - ${NavigateTo($url1)}\r\n\r\n steps: \r\n - webdriver:\r\n action: ${NavigateTo($url2)}\r\n\r\n - webdriver:\r\n action: ${ScrollTo(0, 1000)}\r\n\r\n - webdriver:\r\n action: ${TimeSleep(1)}\r\n\r\n - webdriver:\r\n action: ${Refresh()}\r\n\r\n - webdriver:\r\n action: ${NewTab($url1)}\r\n\r\n - webdriver:\r\n by: css selector\r\n value: '#kw'\r\n index: 0\r\n timeout: 10\r\n action: ${SendKeys(123)}\r\n\r\n - webdriver:\r\n action: ${TimeSleep(1)}\r\n\r\n - webdriver:\r\n by: id\r\n value: su\r\n action: ${DyAttrData(id_su_value, value)}\r\n\r\n - webdriver:\r\n action: ${TimeSleep(1)}\r\n\r\n - webdriver:\r\n by: id\r\n value: su\r\n action: ${VerifyElemAttr(value, $id_su_value)}\r\n\r\n - webdriver:\r\n action: ${WebClose()}\r\n post_command:\r\n - ${WebQuit()}\r\n\r\n```\r\n\r\n2. \u6267\u884c\u8fd9\u4e2a\u7528\u4f8b\u6587\u4ef6\r\n\r\n\u6267\u884c\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\r\n\r\n- run with selenium webdriver\r\n\r\n```\r\nwldriver test_case.yaml\r\n```\r\n\r\n- for selenium grid, run with selenium remote \r\n\r\n```\r\n# Terminal 1\r\nwrhub c:\\selenium-server-standalone-3.14.0.jar \r\n\r\n# Terminal 2\r\nwrnode c:\\selenium-server-standalone-3.14.0.jar\r\n\r\n# Terminal 3\r\nwrdriver test_case.yaml\r\n```\r\n\r\n### \u5e76\u884c\u7684\u6d4b\u8bd5\u9879\u76ee\r\n\r\n\u60a8\u53ef\u4ee5\u9009\u62e9\uff0c\u5728\u591a\u53f0\u8bbe\u5907\u4e0a\uff0c\u4f7f\u7528wldriver\u8fd0\u884c\u4e0d\u540c\u6a21\u5757\u7684\u7528\u4f8b\uff0c\u7136\u540e\uff0c\u5728\u6bcf\u53f0\u673a\u5668\u4e0a\u9762\uff0c\u53bb\u6536\u96c6\u62a5\u544a\uff0c\u5982\u679c\uff0c\u8fd9\u4e9b\u8bbe\u5907\u79bb\u4f60\u5f88\u8fdc\uff0c\u6211\u60f3\u5c31\u97ad\u957f\u83ab\u53ca\u4e86\uff0c\u66f4\u52a0\u4f18\u96c5\u7684\u65b9\u5f0f\u662f\uff1a\r\n\r\n\u9996\u5148\uff0c\u5047\u8bbe\uff0c\u6240\u6709\u673a\u5668\uff0c\u90fd\u5df2\u7ecf\u5b89\u88c5\u597d\u4e86\u73af\u5883\r\n1. \u5212\u5206\u6a21\u5757\u7528\u4f8b\uff0c\u6bd4\u5982\uff0c\u6211\u5206\u4e86\u4e09\u4e2a\u5e76\u884c\u7684\u6d4b\u8bd5\u6a21\u5757\u7528\u4f8bA,B,C\r\n2. \u7528\u4e00\u53f0\u673a\u5668\u4f5c\u4e3ahub\uff0c\u5206\u522b\u4e3a\u8fd9\u4e09\u4e2a\u6a21\u5757\u7528\u4f8b\u8bbe\u7f6e\u7aef\u53e3,\u6bd4\u5982: 192.168.1.2:6000,192.168.1.2:7000,192.168.1.2:8000\r\n3. \u53e6\u5916\u627e\u4e09\u53f0\u673a\u5668\u4f5c\u4e3anode\uff0c\u5206\u522b\u8fde\u4e0a\u6b65\u9aa42\u7684hub\r\n4. \u5728\u4efb\u610f\u4e00\u53f0\u673a\u5668\u4e0a\uff0c\u5f00\u542f\u4e09\u4e2a\u7ec8\u7aef\uff0c\u6267\u884c\u4e0b\u8ff0\u547d\u4ee4\uff0c\u6700\u540e\uff0c\u60a8\u53ef\u4ee5\u4e0b\u8fbe\u6267\u884c\u547d\u4ee4\u7684\u673a\u5668\u4e0a\u9762\uff0c\u6536\u96c6\u5230\u6240\u6709\u62a5\u544a\r\n\r\n```\r\nwrdriver c:\\A --ip 192.168.1.2 --port 6000\r\nwrdriver c:\\B --ip 192.168.1.2 --port 7000\r\nwrdriver c:\\C --ip 192.168.1.2 --port 8000\r\n```\r\n\r\n\r\n\r\n## \u63a8\u8350\u83b7\u53d6\u63a7\u4ef6\u7684\u5de5\u5177\r\nweb ui\u63a7\u4ef6\u5143\u7d20\u7684\u83b7\u53d6\uff0c\u9075\u5faaselenium\u7684\u89c4\u5219\uff0c\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8ff0\u65b9\u5f0f\u6765\u5b9a\u4f4d\u5143\u7d20\u63a7\u4ef6: id\u3001xpath\u3001link text\u3001partial link text\u3001name\u3001tag name\u3001class name\u3001css selector\r\n\r\n\u63a8\u8350\u5e38\u7528\u7684\u5de5\u5177\uff0c\u4e00\u822c\u662f Firefox \u6216\u8005 Chrome \u7b49\u6d4f\u89c8\u5668\u7684\u5f00\u53d1\u8005\u5de5\u5177\u3002\u5982\u4e0b\u56fe\uff0c\u4f7f\u7528chrome\u5f00\u53d1\u6a21\u5f0f\uff0c\u91c7\u7528css\u548cxpath\u4e24\u79cd\u65b9\u5f0f\u5b9a\u4f4d\u8f93\u5165\u6846:\r\n![chrome-deployment-tools.gif](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/chrome-deployment-tools.gif)\r\n\r\n\u53e6\u4e00\u4e2a\u5de5\u5177\uff0cselenium IDE\uff0c\u5b98\u65b9\u63a8\u51fa\u7684\u5e26\u6709\u754c\u9762\u7684\u5de5\u5177\r\n![selenium-ide.png](https://github.com/RockFeng0/img-folder/blob/master/rtsf-web-img/selenium-ide.png)\r\n\r\n\u90a3\u4e48\uff0c\u6211\u4e3a\u4ec0\u4e48\u4e0d\u63a8\u8350\u4f7f\u7528\uff0cSelenium IDE? \u4eceselenium1.0\u5f00\u59cb\uff0cselenium ide\u66fe\u7ecf\u7ed9\u6211\u60ca\u8273\uff0c\u53ef\u4ee5\u5f55\u5236\u3001\u5b9a\u4f4d\u3001\u751f\u6210\u811a\u672c\u7b49\uff0c\u5f88\u4f18\u79c0\uff0c\u4f46\u662fselenium2.0\u540e\uff0c\u518d\u4e5f\u6ca1\u6709\u7528\u4e86\u3002\u4e00\u65b9\u9762\u7531\u4e8e\u662f\u57fa\u4e8e\u65e7\u6280\u672f\u5b9e\u73b0\uff0c\u5728\u706b\u72d055\u53ca\u4e4b\u540e\u7684\u65b0\u7248\u672c\u4e0a\u4e0d\u518d\u652f\u6301\u4e86\uff0c\u867d\u7136\u5f88\u597d\u7528\uff0c\u4f46\u662f\u9000\u51fa\u5386\u53f2\u821e\u53f0\u4e86\uff1b \u53e6\u4e00\u65b9\u9762\uff0cfirefox\u548cchrome\u7b49\u6d4f\u89c8\u5668\uff0cweb\u5f00\u53d1\u5de5\u5177\u529f\u80fd\u5f3a\u5927\uff0c\u5b89\u88c5\u7b80\u5355\uff0c\u5bf9\u5143\u7d20\u7684\u5b9a\u4f4d\u548c\u8c03\u8bd5\u63d0\u4f9b\u4e86\u975e\u5e38\u4fbf\u6377\u7684\u65b9\u5f0f\u3002\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "only for web ui test, base on rtsf",
"version": "1.3.7",
"project_urls": {
"Homepage": "https://github.com/RockFeng0/rtsf-web"
},
"split_keywords": [
"test",
"web",
"ui"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9db6af56e1cd7f16152f74797c9e7f849c219e61f62dfbdd27adb1ca2840c53b",
"md5": "6840f4ab8f429e4a4ddf8e4940e4c651",
"sha256": "93d67b62243e40d1164378115812010282d7c1e13f7bde8260b704533985e2eb"
},
"downloads": -1,
"filename": "rtsf_web-1.3.7-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "6840f4ab8f429e4a4ddf8e4940e4c651",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4,>=2.7",
"size": 29009,
"upload_time": "2024-04-24T06:28:06",
"upload_time_iso_8601": "2024-04-24T06:28:06.168451Z",
"url": "https://files.pythonhosted.org/packages/9d/b6/af56e1cd7f16152f74797c9e7f849c219e61f62dfbdd27adb1ca2840c53b/rtsf_web-1.3.7-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "29887137ce6d2033c68cd868252943725511bada96ef0f5088a7a01e5e4064e9",
"md5": "9c427f1ce9b89e7fc049be99c2c55bc9",
"sha256": "fcd4fbce9b467b51de6580d12ef198b79980870919164b506448137cabcd5056"
},
"downloads": -1,
"filename": "rtsf-web-1.3.7.tar.gz",
"has_sig": false,
"md5_digest": "9c427f1ce9b89e7fc049be99c2c55bc9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4,>=2.7",
"size": 26461,
"upload_time": "2024-04-24T06:28:08",
"upload_time_iso_8601": "2024-04-24T06:28:08.345374Z",
"url": "https://files.pythonhosted.org/packages/29/88/7137ce6d2033c68cd868252943725511bada96ef0f5088a7a01e5e4064e9/rtsf-web-1.3.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-24 06:28:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "RockFeng0",
"github_project": "rtsf-web",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "rtsf-web"
}