rtsf-web


Namertsf-web JSON
Version 1.3.7 PyPI version JSON
download
home_pagehttps://github.com/RockFeng0/rtsf-web
Summaryonly for web ui test, base on rtsf
upload_time2024-04-24 06:28:08
maintainerNone
docs_urlNone
author罗科峰
requires_python!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4,>=2.7
licenseMIT
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"
}
        
Elapsed time: 0.27894s