# simlpe_automation_framework
### 介绍
simple_automation_framework(简称:SAF)
使用最简单的模式就可以实现需要功能和测试效果,也是xiaobaiauto2的简化版
SAF继承了selenium、requests/httpx、appium、loguru、xiaobaiauto2、飞书机器人、钉钉机器人、企业微信机器人(暂时不支持)、禅道提单API
### 软件架构
xiaobaiauto2的简化版
### 版本注意
建议使用Python 3.9.* 版本
建议selenium >=4.16.0 支持代码自动执行无需关注浏览器驱动问题,可以自行下载
防止某些库出现不兼容问题,导致功能不可使用
### 安装教程
```commandline
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 注:将pip源修改为国内源
pip install xiaobaisaf
```
### 使用说明
- 优先修改saf/data/config.py中飞书/钉钉的webhook
```python
# filename=config.py
class feishu(object):
@staticmethod
def webhook():
return 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxx'
class dingding(object):
@staticmethod
def webhook():
return 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxx'
```
- conftest.py(保持此文件与用例文件在同目录下)
```python
# filename = conftest.py
from saf.utils.SendMsgUtils import robotSendMessage
import pytest
@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
:param item:
"""
outcome = yield
report = outcome.get_result()
if report.outcome == 'failed':
# 调用机器人发送执行结果
robotSendMessage(robot_name='feishu', msg=f'测试脚本:{report.nodeid.split("::")[0]}\n测试用例:{report.nodeid.split("::")[1]}\n测试结果:{report.outcome}')
# robotSendMessage(robot_name='dingding', msg=f'测试脚本:{report.nodeid.split("::")[0]}\n测试用例:{report.nodeid.split("::")[1]}\n测试结果:{report.outcome}')
# robotSendMessage(robot_name='feishu,dingding', msg=f'测试脚本:{report.nodeid.split("::")[0]}\n测试用例:{report.nodeid.split("::")[1]}\n测试结果:{report.outcome}')
```
- 用例文件
```python
# fielname = test_xiaobai_testcase.py
def setup_module():
''' 用例脚本执行之前需要准备的信息 '''
...
def teardown_module():
''' 用例脚本执行之后需要清除的信息 '''
def setup_function():
''' 初始化测试用例执行之前状态信息 '''
...
def teardown_function():
''' 清除测试用例执行之后所产生的信息 '''
...
def test_yewu_name_a():
''' 用例函数
需要针对业务场景的测试步骤的实现
1、UI测试就是定位需要操作的界面节点然后执行操作
2、API测试就是执行相关接口实现接口的功能
需要针对每次的结果添加断言进行判断处理
'''
def test_yewu_name_b():
''' 用例函数
需要针对业务场景的测试步骤的实现
1、UI测试就是定位需要操作的界面节点然后执行操作
2、API测试就是执行相关接口实现接口的功能
需要针对每次的结果添加断言进行判断处理
'''
```
```python
# filename = test_xiaobai_allure.py
# JDK与Allure已安装且配置好环境变量(若不知道可以查看公众号:小白科技之窗)
import pytest
import allure
@allure.feature('下单')
class Test_order():
@allure.story('登录')
def test_login(self):
''' 登录 '''
with allure.step('输入账户'):
assert True
with allure.step('输入密码'):
assert True
with allure.step('点击登录'):
assert True
@allure.story('搜索商品')
def test_search(self):
''' 搜索商品 '''
with allure.step('搜索框输入:苹果'):
assert True
with allure.step('点击搜索按钮'):
assert False
'''
# 执行脚本
pytest test_xiaobai_allure.py --alluredir=../data
# 打开报告
allure serve ../data
或者
allure generate -c -o ../report ../data
allure open ../report
'''
```
### saf>1.1 使用禅道API,测试失败自动提单
- 需要在禅道后台>>二次开发>>应用>>添加应用>>创建开启免密的应用
- 需要将上一步所生成数据【代号】与【密钥】写入到`saf/data/config.py`中zenTao相关的参数位置
```python
# filename = saf/data/config.py
import hashlib
import time
class zenTao(object):
'''
参考禅道接口文档:
https://www.zentao.net/book/zentaopmshelp/integration-287.html
'''
@staticmethod
def baseURL():
''' 禅道的根路径 '''
return 'http://192.168.0.240/zentao'
@staticmethod
def account():
''' 后台-》二次开发-》应用-》免密登录的账户名 '''
return '开启密钥的账户名称,例如管理员:admin'
@staticmethod
def getCode():
''' 后台-》二次开发-》应用-》创建-》代号 '''
return '复制生成应用的代号字符串'
@staticmethod
def getKey():
''' 后台-》二次开发-》应用-》创建-》密钥 '''
return '复制生成应用的密钥字符串'
@staticmethod
def getTime():
''' 获取时间戳 ,默认即可,无需修改'''
return int(time.time())
@staticmethod
def getToken():
''' 获取token: md5($code + $key + $time) ,默认即可,无需修改'''
_md5 = hashlib.md5(f'{zenTao.getCode()}{zenTao.getKey()}{zenTao.getTime()}'.encode('utf-8'))
return _md5.hexdigest()
```
- 用例同目录下创建`conftest.py`pytest的配置文件
```python
# filename = conftest.py
from saf.utils.BugUtils import addZenTaoBUG
import pytest
@pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
"""
:param item:
"""
outcome = yield
report = outcome.get_result()
if report.outcome == 'failed':
doc = item.function.__doc__
doc = str(doc).replace('\n', '<br>')
addZenTaoBUG(title=item.function.__name__,
steps=f'{doc}预期结果:passed<br>测试结果:{report.outcome}')
```
- 用例文件正常编写,正常运行即可
### saf>1.0 拷贝web自动化模板到D:\autoProject目录下
```bat
xiaobaicmd -t web -d D:\autoProject
xiaobaicmd --template web --dirname D:\autoProject
xiaobaicmd -t api -d D:\autoProject
xiaobaicmd --template api --dirname D:\autoProject
xiaobaicmd -t app -d D:\autoProject[暂时不支持]
```
### saf>1.3 新增pytest参数多种样例,`web`中包含
```python
# filename = test_xiaobai_case_v2.py
import pytest
from saf import full_load
''' 参数化 '''
data2 = {
'test_login': {
'keys': 'username, password, _assert',
'values': [('xiaobai', '12345', 200), ('xiaohui', '1234567', 200)]
}
}
data3 = full_load(open('..\\data\\testCase.yaml', 'r').read())
# 内部数据
@pytest.mark.parametrize('username, password, _assert', [('xiaobai', '12345', 200), ('xiaohui', '1234567', 200)])
def test_xiaobai_login1(username, password, _assert):
# 业务实现代码
assert _assert == 200
# 外部数据
@pytest.mark.parametrize(data2['test_login']['keys'], data2['test_login']['values'])
def test_xiaobai_login2(username, password, _assert):
# 业务实现代码
assert _assert == 200
# 外部文件数据
@pytest.mark.parametrize(data3['test_login']['keys'], [eval(v) for v in data3['test_login']['values']])
def test_xiaobai_login3(username, password, _assert):
# 业务实现代码
assert _assert == 200
```
```yaml
# filename = ..\\data\\testCase.yaml
---
test_login:
keys: username,password,_assert
values:
- ('xiaobai', '12346', 200)
- ('xiaohui', '123456', 200)
```
### saf>1.8 工具会自动在当前目录下生成target文件夹,target目录内容与web模板保持一致,页面对象代码在PageObjects目录下
```cmd
xiaobaicmd -u https://www.baidu.com
xiaobaicmd --url https://www.baidu.com
```
### saf>1.9 基于adb实现监控Android设备中APP操作时实时生成XPath表达式及坐标等数据
```cmd
xiaobaicmd -m gui # 基于界面实时获取APP数据
xiaobaicmd --monitor gui # 基于界面实时获取APP数据
xiaobaicmd -m cli # 基于命令实时获取APP数据
xiaobaicmd --monitor cli # 基于命令实时获取APP数据
```
### saf>2.0 基础adb实现Android设备的界面监控功能
```cmd
xiaobaicmd -e [1] # 默认值为1,可省略;表示打开界面监控第一个设备的实时界面
xiaobaicmd --device 1
```
### saf>2.2 基础adb实现Android设备的电量监控功能
```cmd
xiaobaicmd -m power # 界面监控设备的电量与内存使用率的实时界面
xiaobaicmd -m memory # 界面监控设备的电量与内存使用率的实时界面
```
### saf>2.3.5 新增实时监控Android当前APP的CPU使用率及FPS数据
```cmd
xiaobaicmd -m gui
```
### saf>2.3.7 新增识别滑块验证码破解
```python
from saf.utils.CaptchaUtils import checkSlider
from saf import selenium_webdriver, By
driver = selenium_webdriver.Chrome()
driver.get("https://www.xiaobaisoftware.com")
# 其它操作...
# 定位目标图(小图)
target_element = driver.find_element(By.XPATH, value='')
# 定位背景图(大图)
background_element = driver.find_element(By.XPATH, value='')
# 定位滑块按钮
button_element = driver.find_element(By.XPATH, value='')
# 参数:浏览器驱动、目标元素、背景元素、滑块元素、失败重试(非必须,默认:False)、重试次数(非必须,默认:3)
checkSlider(driver, target_element, background_element, button_element, True, 5)
```
### saf>2.3.8 新增解析DNS并刷新DNS缓存,数据保存HOSTS
```cmd
# 执行脚本之前请修改系统hosts文件在当前用户下有可读可写的权限!
# windows的hosts文件路径:C:\Windows\System32\drivers\etc\hosts
# Mac OS的hosts文件路径 :/private/etc/hosts
# Linux的hosts文件路径 :/etc/hosts
# --domains 后面的域名使用逗号分离即可
xiaobaicmd --domains github.com,raw.githubusercontent.com,github.global.ssl.fastly.net,assets-cdn.github.com
```
### saf>=2.5.0 新增小白软件管理工具,目前支持(安装、卸载、替换不同版本的)JMeter
```cmd
#命令行输入命令运行即可
xiaobaimanager
```
### 环境检测[还未实现]
```bat
xiaobaicmd --init
检测内容:
1、python版本及第三方库
2、第三方工具及环境
```
### 参与贡献
[selenium官网文档](https://www.selenium.dev/documentation/, "selenium官网文档")
[requests官网文档](https://requests.readthedocs.io/en/latest/, "requests官网文档")
[appium官网](http://appium.io/, "appium官网")
[loguru官方文档](https://loguru.readthedocs.io/en/stable/overview.html, "loguru官方文档")
[xiaobaiauto2帮助文档](https://pypi.org/project/xiaobaiauto2/, "xiaobaiauto2帮助文档")
[Allure帮助文档](https://docs.qameta.io/allure, "Allure帮助文档")
[飞书机器人获取WebHook](https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN?lang=zh-CN, "飞书机器人获取WebHook")
[钉钉机器人获取WebHook](https://open.dingtalk.com/document/group/custom-robot-access, "钉钉机器人获取WebHook")
[163邮箱配置](http://help.163.com/09/1223/14/5R7P3QI100753VB8.html, "163邮箱配置")
[QQ邮箱配置](https://service.mail.qq.com/cgi-bin/help?subtype=1&id=28&no=369, "QQ邮箱配置")
### 更新日志
| version | info |
|---------|---------------------------------|
| 1.0 | 基本实现web自动化模板功能 |
| 1.1 | 修复已知BUG |
| 1.2 | 新增allure报告库及封装禅道提单接口 |
| 1.3 | 新增jira提单接口 |
| 1.4 | 新增pytest参数化样例 |
| 1.5 | 优化pytest样例内容 |
| 1.6 | 修复已知BUG |
| 1.7 | 新增基础环境检测功能 |
| 1.8 | 新增API自动化模板 |
| 1.9 | 新增xiaobaicmd -u命令 |
| 2.0 | 新增xiaobaicmd -m命令 |
| 2.1 | 新增xiaobaicmd --device命令 |
| 2.2 | 修复已知BUG |
| 2.3 | 新增实时监控Android设备耗电量 |
| 2.3.1 | 修复已知BUG |
| 2.3.2 | 修复已知BUG |
| 2.3.3 | 新增实时监控Android当前APP的内存使用率 |
| 2.3.4 | 新增xiaobaicmd -m gui效果展示 |
| 2.3.5 | 新增xiaobaicmd -u 转PO代码时xpath的表达式 |
| 2.3.6 | 新增实时监控Android当前APP的CPU使用率及FPS数据 |
| 2.3.7 | 新增识别滑块验证码破解 |
| 2.3.8 | 优化识别滑块验证码破解 |
| 2.3.9 | 新增解析DNS并刷新DNS缓存,数据保存HOSTS |
| 2.4 | 修复已知BUG |
| 2.4.1 | 优化DNS解析效果 |
| 2.4.2 | 优化自动生成代码 |
| 2.4.3 | 优化 |
| 2.4.3.1 | 优化 |
| 2.4.3.2 | 优化 |
| 2.5.0 | 添加xiaobaimanager命令 |
Raw data
{
"_id": null,
"home_page": "https://gitee.com/xiaobaikeji/simlpe_automation_framework",
"name": "xiaobaisaf",
"maintainer": "",
"docs_url": null,
"requires_python": ">3.8, <3.10",
"maintainer_email": "",
"keywords": "saf automation xiaobai xiaobaiauto2 test framework",
"author": "xiaobaiTser",
"author_email": "807447312@qq.com",
"download_url": "https://files.pythonhosted.org/packages/73/54/a96dc29b2b71954d7e821d843f0924921965bdff12894ee004ee46257f25/xiaobaisaf-2.5.0.tar.gz",
"platform": null,
"description": "# simlpe_automation_framework\n\n### \u4ecb\u7ecd\n simple_automation_framework(\u7b80\u79f0\uff1aSAF)\n \u4f7f\u7528\u6700\u7b80\u5355\u7684\u6a21\u5f0f\u5c31\u53ef\u4ee5\u5b9e\u73b0\u9700\u8981\u529f\u80fd\u548c\u6d4b\u8bd5\u6548\u679c\uff0c\u4e5f\u662fxiaobaiauto2\u7684\u7b80\u5316\u7248\n SAF\u7ee7\u627f\u4e86selenium\u3001requests/httpx\u3001appium\u3001loguru\u3001xiaobaiauto2\u3001\u98de\u4e66\u673a\u5668\u4eba\u3001\u9489\u9489\u673a\u5668\u4eba\u3001\u4f01\u4e1a\u5fae\u4fe1\u673a\u5668\u4eba\uff08\u6682\u65f6\u4e0d\u652f\u6301\uff09\u3001\u7985\u9053\u63d0\u5355API\n \n\n### \u8f6f\u4ef6\u67b6\u6784\n xiaobaiauto2\u7684\u7b80\u5316\u7248\n\n### \u7248\u672c\u6ce8\u610f\n \u5efa\u8bae\u4f7f\u7528Python 3.9.* \u7248\u672c\n \u5efa\u8baeselenium >=4.16.0 \u652f\u6301\u4ee3\u7801\u81ea\u52a8\u6267\u884c\u65e0\u9700\u5173\u6ce8\u6d4f\u89c8\u5668\u9a71\u52a8\u95ee\u9898\uff0c\u53ef\u4ee5\u81ea\u884c\u4e0b\u8f7d\n \u9632\u6b62\u67d0\u4e9b\u5e93\u51fa\u73b0\u4e0d\u517c\u5bb9\u95ee\u9898\uff0c\u5bfc\u81f4\u529f\u80fd\u4e0d\u53ef\u4f7f\u7528\n\n### \u5b89\u88c5\u6559\u7a0b\n```commandline\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \u6ce8\uff1a\u5c06pip\u6e90\u4fee\u6539\u4e3a\u56fd\u5185\u6e90\npip install xiaobaisaf\n```\n\n### \u4f7f\u7528\u8bf4\u660e\n- \u4f18\u5148\u4fee\u6539saf/data/config.py\u4e2d\u98de\u4e66/\u9489\u9489\u7684webhook\n```python\n# filename=config.py\n\nclass feishu(object):\n @staticmethod\n def webhook():\n return 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxx'\n\nclass dingding(object):\n @staticmethod\n def webhook():\n return 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxx'\n```\n\n- conftest.py\uff08\u4fdd\u6301\u6b64\u6587\u4ef6\u4e0e\u7528\u4f8b\u6587\u4ef6\u5728\u540c\u76ee\u5f55\u4e0b\uff09\n```python\n# filename = conftest.py\nfrom saf.utils.SendMsgUtils import robotSendMessage\nimport pytest\n\n@pytest.mark.hookwrapper\ndef pytest_runtest_makereport(item):\n \"\"\"\n :param item:\n \"\"\"\n outcome = yield\n report = outcome.get_result()\n if report.outcome == 'failed':\n # \u8c03\u7528\u673a\u5668\u4eba\u53d1\u9001\u6267\u884c\u7ed3\u679c\n robotSendMessage(robot_name='feishu', msg=f'\u6d4b\u8bd5\u811a\u672c\uff1a{report.nodeid.split(\"::\")[0]}\\n\u6d4b\u8bd5\u7528\u4f8b\uff1a{report.nodeid.split(\"::\")[1]}\\n\u6d4b\u8bd5\u7ed3\u679c\uff1a{report.outcome}')\n # robotSendMessage(robot_name='dingding', msg=f'\u6d4b\u8bd5\u811a\u672c\uff1a{report.nodeid.split(\"::\")[0]}\\n\u6d4b\u8bd5\u7528\u4f8b\uff1a{report.nodeid.split(\"::\")[1]}\\n\u6d4b\u8bd5\u7ed3\u679c\uff1a{report.outcome}')\n # robotSendMessage(robot_name='feishu,dingding', msg=f'\u6d4b\u8bd5\u811a\u672c\uff1a{report.nodeid.split(\"::\")[0]}\\n\u6d4b\u8bd5\u7528\u4f8b\uff1a{report.nodeid.split(\"::\")[1]}\\n\u6d4b\u8bd5\u7ed3\u679c\uff1a{report.outcome}')\n```\n\n- \u7528\u4f8b\u6587\u4ef6\n```python\n# fielname = test_xiaobai_testcase.py\n\ndef setup_module():\n ''' \u7528\u4f8b\u811a\u672c\u6267\u884c\u4e4b\u524d\u9700\u8981\u51c6\u5907\u7684\u4fe1\u606f '''\n ...\n\ndef teardown_module():\n ''' \u7528\u4f8b\u811a\u672c\u6267\u884c\u4e4b\u540e\u9700\u8981\u6e05\u9664\u7684\u4fe1\u606f '''\n\ndef setup_function():\n ''' \u521d\u59cb\u5316\u6d4b\u8bd5\u7528\u4f8b\u6267\u884c\u4e4b\u524d\u72b6\u6001\u4fe1\u606f '''\n ...\n\ndef teardown_function():\n ''' \u6e05\u9664\u6d4b\u8bd5\u7528\u4f8b\u6267\u884c\u4e4b\u540e\u6240\u4ea7\u751f\u7684\u4fe1\u606f '''\n ...\n\ndef test_yewu_name_a():\n ''' \u7528\u4f8b\u51fd\u6570\n \u9700\u8981\u9488\u5bf9\u4e1a\u52a1\u573a\u666f\u7684\u6d4b\u8bd5\u6b65\u9aa4\u7684\u5b9e\u73b0\n 1\u3001UI\u6d4b\u8bd5\u5c31\u662f\u5b9a\u4f4d\u9700\u8981\u64cd\u4f5c\u7684\u754c\u9762\u8282\u70b9\u7136\u540e\u6267\u884c\u64cd\u4f5c\n 2\u3001API\u6d4b\u8bd5\u5c31\u662f\u6267\u884c\u76f8\u5173\u63a5\u53e3\u5b9e\u73b0\u63a5\u53e3\u7684\u529f\u80fd\n \u9700\u8981\u9488\u5bf9\u6bcf\u6b21\u7684\u7ed3\u679c\u6dfb\u52a0\u65ad\u8a00\u8fdb\u884c\u5224\u65ad\u5904\u7406\n '''\n\ndef test_yewu_name_b():\n ''' \u7528\u4f8b\u51fd\u6570\n \u9700\u8981\u9488\u5bf9\u4e1a\u52a1\u573a\u666f\u7684\u6d4b\u8bd5\u6b65\u9aa4\u7684\u5b9e\u73b0\n 1\u3001UI\u6d4b\u8bd5\u5c31\u662f\u5b9a\u4f4d\u9700\u8981\u64cd\u4f5c\u7684\u754c\u9762\u8282\u70b9\u7136\u540e\u6267\u884c\u64cd\u4f5c\n 2\u3001API\u6d4b\u8bd5\u5c31\u662f\u6267\u884c\u76f8\u5173\u63a5\u53e3\u5b9e\u73b0\u63a5\u53e3\u7684\u529f\u80fd\n \u9700\u8981\u9488\u5bf9\u6bcf\u6b21\u7684\u7ed3\u679c\u6dfb\u52a0\u65ad\u8a00\u8fdb\u884c\u5224\u65ad\u5904\u7406\n '''\n```\n\n```python\n# filename = test_xiaobai_allure.py\n# JDK\u4e0eAllure\u5df2\u5b89\u88c5\u4e14\u914d\u7f6e\u597d\u73af\u5883\u53d8\u91cf\uff08\u82e5\u4e0d\u77e5\u9053\u53ef\u4ee5\u67e5\u770b\u516c\u4f17\u53f7\uff1a\u5c0f\u767d\u79d1\u6280\u4e4b\u7a97\uff09\nimport pytest\nimport allure\n\n@allure.feature('\u4e0b\u5355')\nclass Test_order():\n @allure.story('\u767b\u5f55')\n def test_login(self):\n ''' \u767b\u5f55 '''\n with allure.step('\u8f93\u5165\u8d26\u6237'):\n assert True\n with allure.step('\u8f93\u5165\u5bc6\u7801'):\n assert True\n with allure.step('\u70b9\u51fb\u767b\u5f55'):\n assert True\n\n @allure.story('\u641c\u7d22\u5546\u54c1')\n def test_search(self):\n ''' \u641c\u7d22\u5546\u54c1 '''\n with allure.step('\u641c\u7d22\u6846\u8f93\u5165\uff1a\u82f9\u679c'):\n assert True\n with allure.step('\u70b9\u51fb\u641c\u7d22\u6309\u94ae'):\n assert False\n'''\n# \u6267\u884c\u811a\u672c\npytest test_xiaobai_allure.py --alluredir=../data\n\n# \u6253\u5f00\u62a5\u544a\nallure serve ../data\n\u6216\u8005\nallure generate -c -o ../report ../data\nallure open ../report\n'''\n```\n\n### saf>1.1 \u4f7f\u7528\u7985\u9053API\uff0c\u6d4b\u8bd5\u5931\u8d25\u81ea\u52a8\u63d0\u5355\n- \u9700\u8981\u5728\u7985\u9053\u540e\u53f0>>\u4e8c\u6b21\u5f00\u53d1>>\u5e94\u7528>>\u6dfb\u52a0\u5e94\u7528>>\u521b\u5efa\u5f00\u542f\u514d\u5bc6\u7684\u5e94\u7528 \n- \u9700\u8981\u5c06\u4e0a\u4e00\u6b65\u6240\u751f\u6210\u6570\u636e\u3010\u4ee3\u53f7\u3011\u4e0e\u3010\u5bc6\u94a5\u3011\u5199\u5165\u5230`saf/data/config.py`\u4e2dzenTao\u76f8\u5173\u7684\u53c2\u6570\u4f4d\u7f6e\n\n```python\n# filename = saf/data/config.py\n\nimport hashlib\nimport time\nclass zenTao(object):\n '''\n \u53c2\u8003\u7985\u9053\u63a5\u53e3\u6587\u6863\uff1a\n https://www.zentao.net/book/zentaopmshelp/integration-287.html\n '''\n @staticmethod\n def baseURL():\n ''' \u7985\u9053\u7684\u6839\u8def\u5f84 '''\n return 'http://192.168.0.240/zentao'\n \n @staticmethod\n def account():\n ''' \u540e\u53f0-\u300b\u4e8c\u6b21\u5f00\u53d1-\u300b\u5e94\u7528-\u300b\u514d\u5bc6\u767b\u5f55\u7684\u8d26\u6237\u540d '''\n return '\u5f00\u542f\u5bc6\u94a5\u7684\u8d26\u6237\u540d\u79f0\uff0c\u4f8b\u5982\u7ba1\u7406\u5458\uff1aadmin'\n \n @staticmethod\n def getCode():\n ''' \u540e\u53f0-\u300b\u4e8c\u6b21\u5f00\u53d1-\u300b\u5e94\u7528-\u300b\u521b\u5efa-\u300b\u4ee3\u53f7 '''\n return '\u590d\u5236\u751f\u6210\u5e94\u7528\u7684\u4ee3\u53f7\u5b57\u7b26\u4e32'\n \n @staticmethod\n def getKey():\n ''' \u540e\u53f0-\u300b\u4e8c\u6b21\u5f00\u53d1-\u300b\u5e94\u7528-\u300b\u521b\u5efa-\u300b\u5bc6\u94a5 '''\n return '\u590d\u5236\u751f\u6210\u5e94\u7528\u7684\u5bc6\u94a5\u5b57\u7b26\u4e32'\n \n @staticmethod\n def getTime():\n ''' \u83b7\u53d6\u65f6\u95f4\u6233 \uff0c\u9ed8\u8ba4\u5373\u53ef\uff0c\u65e0\u9700\u4fee\u6539'''\n return int(time.time())\n \n @staticmethod\n def getToken():\n ''' \u83b7\u53d6token\uff1a md5($code + $key + $time) \uff0c\u9ed8\u8ba4\u5373\u53ef\uff0c\u65e0\u9700\u4fee\u6539'''\n _md5 = hashlib.md5(f'{zenTao.getCode()}{zenTao.getKey()}{zenTao.getTime()}'.encode('utf-8'))\n return _md5.hexdigest()\n```\n\n- \u7528\u4f8b\u540c\u76ee\u5f55\u4e0b\u521b\u5efa`conftest.py`pytest\u7684\u914d\u7f6e\u6587\u4ef6\n```python\n# filename = conftest.py\n\nfrom saf.utils.BugUtils import addZenTaoBUG\nimport pytest\n \n@pytest.mark.hookwrapper\ndef pytest_runtest_makereport(item, call):\n \"\"\"\n :param item:\n \"\"\"\n outcome = yield\n report = outcome.get_result()\n if report.outcome == 'failed':\n doc = item.function.__doc__\n doc = str(doc).replace('\\n', '<br>')\n addZenTaoBUG(title=item.function.__name__,\n steps=f'{doc}\u9884\u671f\u7ed3\u679c\uff1apassed<br>\u6d4b\u8bd5\u7ed3\u679c\uff1a{report.outcome}')\n \n ```\n- \u7528\u4f8b\u6587\u4ef6\u6b63\u5e38\u7f16\u5199\uff0c\u6b63\u5e38\u8fd0\u884c\u5373\u53ef\n\n### saf>1.0 \u62f7\u8d1dweb\u81ea\u52a8\u5316\u6a21\u677f\u5230D:\\autoProject\u76ee\u5f55\u4e0b\n```bat\nxiaobaicmd -t web -d D:\\autoProject\nxiaobaicmd --template web --dirname D:\\autoProject\nxiaobaicmd -t api -d D:\\autoProject\nxiaobaicmd --template api --dirname D:\\autoProject\nxiaobaicmd -t app -d D:\\autoProject[\u6682\u65f6\u4e0d\u652f\u6301]\n```\n\n### saf>1.3 \u65b0\u589epytest\u53c2\u6570\u591a\u79cd\u6837\u4f8b\uff0c`web`\u4e2d\u5305\u542b\n```python\n# filename = test_xiaobai_case_v2.py\nimport pytest\nfrom saf import full_load\n\n''' \u53c2\u6570\u5316 '''\n\ndata2 = {\n 'test_login': {\n 'keys': 'username, password, _assert',\n 'values': [('xiaobai', '12345', 200), ('xiaohui', '1234567', 200)]\n }\n}\n\ndata3 = full_load(open('..\\\\data\\\\testCase.yaml', 'r').read())\n\n# \u5185\u90e8\u6570\u636e\n@pytest.mark.parametrize('username, password, _assert', [('xiaobai', '12345', 200), ('xiaohui', '1234567', 200)])\ndef test_xiaobai_login1(username, password, _assert):\n # \u4e1a\u52a1\u5b9e\u73b0\u4ee3\u7801\n assert _assert == 200\n\n# \u5916\u90e8\u6570\u636e\n@pytest.mark.parametrize(data2['test_login']['keys'], data2['test_login']['values'])\ndef test_xiaobai_login2(username, password, _assert):\n # \u4e1a\u52a1\u5b9e\u73b0\u4ee3\u7801\n assert _assert == 200\n\n\n# \u5916\u90e8\u6587\u4ef6\u6570\u636e\n@pytest.mark.parametrize(data3['test_login']['keys'], [eval(v) for v in data3['test_login']['values']])\ndef test_xiaobai_login3(username, password, _assert):\n # \u4e1a\u52a1\u5b9e\u73b0\u4ee3\u7801\n assert _assert == 200\n```\n```yaml\n# filename = ..\\\\data\\\\testCase.yaml\n---\ntest_login:\n keys: username,password,_assert\n values:\n - ('xiaobai', '12346', 200)\n - ('xiaohui', '123456', 200)\n```\n\n### saf>1.8 \u5de5\u5177\u4f1a\u81ea\u52a8\u5728\u5f53\u524d\u76ee\u5f55\u4e0b\u751f\u6210target\u6587\u4ef6\u5939\uff0ctarget\u76ee\u5f55\u5185\u5bb9\u4e0eweb\u6a21\u677f\u4fdd\u6301\u4e00\u81f4\uff0c\u9875\u9762\u5bf9\u8c61\u4ee3\u7801\u5728PageObjects\u76ee\u5f55\u4e0b\n```cmd\nxiaobaicmd -u https://www.baidu.com \nxiaobaicmd --url https://www.baidu.com \n```\n\n### saf>1.9 \u57fa\u4e8eadb\u5b9e\u73b0\u76d1\u63a7Android\u8bbe\u5907\u4e2dAPP\u64cd\u4f5c\u65f6\u5b9e\u65f6\u751f\u6210XPath\u8868\u8fbe\u5f0f\u53ca\u5750\u6807\u7b49\u6570\u636e\n```cmd\nxiaobaicmd -m gui # \u57fa\u4e8e\u754c\u9762\u5b9e\u65f6\u83b7\u53d6APP\u6570\u636e\nxiaobaicmd --monitor gui # \u57fa\u4e8e\u754c\u9762\u5b9e\u65f6\u83b7\u53d6APP\u6570\u636e\nxiaobaicmd -m cli # \u57fa\u4e8e\u547d\u4ee4\u5b9e\u65f6\u83b7\u53d6APP\u6570\u636e\nxiaobaicmd --monitor cli # \u57fa\u4e8e\u547d\u4ee4\u5b9e\u65f6\u83b7\u53d6APP\u6570\u636e\n```\n\n### saf>2.0 \u57fa\u7840adb\u5b9e\u73b0Android\u8bbe\u5907\u7684\u754c\u9762\u76d1\u63a7\u529f\u80fd\n```cmd\nxiaobaicmd -e [1] # \u9ed8\u8ba4\u503c\u4e3a1\uff0c\u53ef\u7701\u7565\uff1b\u8868\u793a\u6253\u5f00\u754c\u9762\u76d1\u63a7\u7b2c\u4e00\u4e2a\u8bbe\u5907\u7684\u5b9e\u65f6\u754c\u9762\nxiaobaicmd --device 1\n```\n\n### saf>2.2 \u57fa\u7840adb\u5b9e\u73b0Android\u8bbe\u5907\u7684\u7535\u91cf\u76d1\u63a7\u529f\u80fd\n```cmd\nxiaobaicmd -m power # \u754c\u9762\u76d1\u63a7\u8bbe\u5907\u7684\u7535\u91cf\u4e0e\u5185\u5b58\u4f7f\u7528\u7387\u7684\u5b9e\u65f6\u754c\u9762\nxiaobaicmd -m memory # \u754c\u9762\u76d1\u63a7\u8bbe\u5907\u7684\u7535\u91cf\u4e0e\u5185\u5b58\u4f7f\u7528\u7387\u7684\u5b9e\u65f6\u754c\u9762\n```\n\n### saf>2.3.5 \u65b0\u589e\u5b9e\u65f6\u76d1\u63a7Android\u5f53\u524dAPP\u7684CPU\u4f7f\u7528\u7387\u53caFPS\u6570\u636e\n```cmd\nxiaobaicmd -m gui\n```\n\n### saf>2.3.7 \u65b0\u589e\u8bc6\u522b\u6ed1\u5757\u9a8c\u8bc1\u7801\u7834\u89e3\n```python\nfrom saf.utils.CaptchaUtils import checkSlider\nfrom saf import selenium_webdriver, By\n\ndriver = selenium_webdriver.Chrome()\n\ndriver.get(\"https://www.xiaobaisoftware.com\")\n\n# \u5176\u5b83\u64cd\u4f5c...\n\n# \u5b9a\u4f4d\u76ee\u6807\u56fe\uff08\u5c0f\u56fe\uff09\ntarget_element = driver.find_element(By.XPATH, value='')\n\n# \u5b9a\u4f4d\u80cc\u666f\u56fe\uff08\u5927\u56fe\uff09\nbackground_element = driver.find_element(By.XPATH, value='')\n\n# \u5b9a\u4f4d\u6ed1\u5757\u6309\u94ae\nbutton_element = driver.find_element(By.XPATH, value='')\n\n# \u53c2\u6570\uff1a\u6d4f\u89c8\u5668\u9a71\u52a8\u3001\u76ee\u6807\u5143\u7d20\u3001\u80cc\u666f\u5143\u7d20\u3001\u6ed1\u5757\u5143\u7d20\u3001\u5931\u8d25\u91cd\u8bd5\uff08\u975e\u5fc5\u987b\uff0c\u9ed8\u8ba4\uff1aFalse\uff09\u3001\u91cd\u8bd5\u6b21\u6570\uff08\u975e\u5fc5\u987b\uff0c\u9ed8\u8ba4\uff1a3\uff09\ncheckSlider(driver, target_element, background_element, button_element, True, 5)\n```\n\n### saf>2.3.8 \u65b0\u589e\u89e3\u6790DNS\u5e76\u5237\u65b0DNS\u7f13\u5b58\uff0c\u6570\u636e\u4fdd\u5b58HOSTS\n```cmd\n# \u6267\u884c\u811a\u672c\u4e4b\u524d\u8bf7\u4fee\u6539\u7cfb\u7edfhosts\u6587\u4ef6\u5728\u5f53\u524d\u7528\u6237\u4e0b\u6709\u53ef\u8bfb\u53ef\u5199\u7684\u6743\u9650\uff01\n# windows\u7684hosts\u6587\u4ef6\u8def\u5f84\uff1aC:\\Windows\\System32\\drivers\\etc\\hosts\n# Mac OS\u7684hosts\u6587\u4ef6\u8def\u5f84 \uff1a/private/etc/hosts\n# Linux\u7684hosts\u6587\u4ef6\u8def\u5f84 \uff1a/etc/hosts\n\n# --domains \u540e\u9762\u7684\u57df\u540d\u4f7f\u7528\u9017\u53f7\u5206\u79bb\u5373\u53ef\nxiaobaicmd --domains github.com,raw.githubusercontent.com,github.global.ssl.fastly.net,assets-cdn.github.com\n```\n\n### saf>=2.5.0 \u65b0\u589e\u5c0f\u767d\u8f6f\u4ef6\u7ba1\u7406\u5de5\u5177\uff0c\u76ee\u524d\u652f\u6301\uff08\u5b89\u88c5\u3001\u5378\u8f7d\u3001\u66ff\u6362\u4e0d\u540c\u7248\u672c\u7684\uff09JMeter\n```cmd\n#\u547d\u4ee4\u884c\u8f93\u5165\u547d\u4ee4\u8fd0\u884c\u5373\u53ef\nxiaobaimanager\n```\n\n\n### \u73af\u5883\u68c0\u6d4b[\u8fd8\u672a\u5b9e\u73b0]\n```bat\nxiaobaicmd --init\n\n\u68c0\u6d4b\u5185\u5bb9: \n1\u3001python\u7248\u672c\u53ca\u7b2c\u4e09\u65b9\u5e93\n2\u3001\u7b2c\u4e09\u65b9\u5de5\u5177\u53ca\u73af\u5883\n```\n\n### \u53c2\u4e0e\u8d21\u732e\n[selenium\u5b98\u7f51\u6587\u6863](https://www.selenium.dev/documentation/, \"selenium\u5b98\u7f51\u6587\u6863\")\n\n[requests\u5b98\u7f51\u6587\u6863](https://requests.readthedocs.io/en/latest/, \"requests\u5b98\u7f51\u6587\u6863\")\n\n[appium\u5b98\u7f51](http://appium.io/, \"appium\u5b98\u7f51\")\n\n[loguru\u5b98\u65b9\u6587\u6863](https://loguru.readthedocs.io/en/stable/overview.html, \"loguru\u5b98\u65b9\u6587\u6863\")\n\n[xiaobaiauto2\u5e2e\u52a9\u6587\u6863](https://pypi.org/project/xiaobaiauto2/, \"xiaobaiauto2\u5e2e\u52a9\u6587\u6863\")\n\n[Allure\u5e2e\u52a9\u6587\u6863](https://docs.qameta.io/allure, \"Allure\u5e2e\u52a9\u6587\u6863\")\n\n[\u98de\u4e66\u673a\u5668\u4eba\u83b7\u53d6WebHook](https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN?lang=zh-CN, \"\u98de\u4e66\u673a\u5668\u4eba\u83b7\u53d6WebHook\")\n\n[\u9489\u9489\u673a\u5668\u4eba\u83b7\u53d6WebHook](https://open.dingtalk.com/document/group/custom-robot-access, \"\u9489\u9489\u673a\u5668\u4eba\u83b7\u53d6WebHook\")\n\n[163\u90ae\u7bb1\u914d\u7f6e](http://help.163.com/09/1223/14/5R7P3QI100753VB8.html, \"163\u90ae\u7bb1\u914d\u7f6e\")\n\n[QQ\u90ae\u7bb1\u914d\u7f6e](https://service.mail.qq.com/cgi-bin/help?subtype=1&id=28&no=369, \"QQ\u90ae\u7bb1\u914d\u7f6e\")\n\n### \u66f4\u65b0\u65e5\u5fd7\n\n| version | info |\n|---------|---------------------------------|\n| 1.0 | \u57fa\u672c\u5b9e\u73b0web\u81ea\u52a8\u5316\u6a21\u677f\u529f\u80fd |\n| 1.1 | \u4fee\u590d\u5df2\u77e5BUG |\n| 1.2 | \u65b0\u589eallure\u62a5\u544a\u5e93\u53ca\u5c01\u88c5\u7985\u9053\u63d0\u5355\u63a5\u53e3 |\n| 1.3 | \u65b0\u589ejira\u63d0\u5355\u63a5\u53e3 |\n| 1.4 | \u65b0\u589epytest\u53c2\u6570\u5316\u6837\u4f8b |\n| 1.5 | \u4f18\u5316pytest\u6837\u4f8b\u5185\u5bb9 |\n| 1.6 | \u4fee\u590d\u5df2\u77e5BUG |\n| 1.7 | \u65b0\u589e\u57fa\u7840\u73af\u5883\u68c0\u6d4b\u529f\u80fd |\n| 1.8 | \u65b0\u589eAPI\u81ea\u52a8\u5316\u6a21\u677f |\n| 1.9 | \u65b0\u589exiaobaicmd -u\u547d\u4ee4 |\n| 2.0 | \u65b0\u589exiaobaicmd -m\u547d\u4ee4 |\n| 2.1 | \u65b0\u589exiaobaicmd --device\u547d\u4ee4 |\n| 2.2 | \u4fee\u590d\u5df2\u77e5BUG |\n| 2.3 | \u65b0\u589e\u5b9e\u65f6\u76d1\u63a7Android\u8bbe\u5907\u8017\u7535\u91cf |\n| 2.3.1 | \u4fee\u590d\u5df2\u77e5BUG |\n| 2.3.2 | \u4fee\u590d\u5df2\u77e5BUG |\n| 2.3.3 | \u65b0\u589e\u5b9e\u65f6\u76d1\u63a7Android\u5f53\u524dAPP\u7684\u5185\u5b58\u4f7f\u7528\u7387 |\n| 2.3.4 | \u65b0\u589exiaobaicmd -m gui\u6548\u679c\u5c55\u793a |\n| 2.3.5 | \u65b0\u589exiaobaicmd -u \u8f6cPO\u4ee3\u7801\u65f6xpath\u7684\u8868\u8fbe\u5f0f |\n| 2.3.6 | \u65b0\u589e\u5b9e\u65f6\u76d1\u63a7Android\u5f53\u524dAPP\u7684CPU\u4f7f\u7528\u7387\u53caFPS\u6570\u636e |\n| 2.3.7 | \u65b0\u589e\u8bc6\u522b\u6ed1\u5757\u9a8c\u8bc1\u7801\u7834\u89e3 |\n| 2.3.8 | \u4f18\u5316\u8bc6\u522b\u6ed1\u5757\u9a8c\u8bc1\u7801\u7834\u89e3 |\n| 2.3.9 | \u65b0\u589e\u89e3\u6790DNS\u5e76\u5237\u65b0DNS\u7f13\u5b58\uff0c\u6570\u636e\u4fdd\u5b58HOSTS |\n| 2.4 | \u4fee\u590d\u5df2\u77e5BUG |\n| 2.4.1 | \u4f18\u5316DNS\u89e3\u6790\u6548\u679c |\n| 2.4.2 | \u4f18\u5316\u81ea\u52a8\u751f\u6210\u4ee3\u7801 |\n| 2.4.3 | \u4f18\u5316 |\n| 2.4.3.1 | \u4f18\u5316 |\n| 2.4.3.2 | \u4f18\u5316 |\n| 2.5.0 | \u6dfb\u52a0xiaobaimanager\u547d\u4ee4 |\n\n\n",
"bugtrack_url": null,
"license": "",
"summary": "simple_automation_framework(\u7b80\u79f0\uff1aSAF)\u4f7f\u7528\u6700\u7b80\u5355\u7684\u6a21\u5f0f\u5c31\u53ef\u4ee5\u5b9e\u73b0\u9700\u8981\u529f\u80fd\u548c\u6d4b\u8bd5\u6548\u679c\uff0c\u4e5f\u662fxiaobaiauto2\u7684\u7b80\u5316\u7248SAF\u7ee7\u627f\u4e86selenium\u3001requests/httpx\u3001appium\u3001loguru\u3001xiaobaiauto2\u3001\u98de\u4e66\u673a\u5668\u4eba\u3001\u9489\u9489\u673a\u5668\u4eba\u3001\u4f01\u4e1a\u5fae\u4fe1\u673a\u5668\u4eba\uff08\u6682\u65f6\u4e0d\u652f\u6301\uff09\u3001\u7985\u9053\u63d0\u5355API",
"version": "2.5.0",
"project_urls": {
"Homepage": "https://gitee.com/xiaobaikeji/simlpe_automation_framework"
},
"split_keywords": [
"saf",
"automation",
"xiaobai",
"xiaobaiauto2",
"test",
"framework"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6719f11a64228b8a62e4c29962d79c4646bbe6ffe6297c930e16cae300f79e10",
"md5": "3e4c8f9f4624a8da72c0f5f3d96d0c54",
"sha256": "1d395cb94e10890c7cb77e62c99e311095067bd0ccbb54dc4cd560e17a728386"
},
"downloads": -1,
"filename": "xiaobaisaf-2.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3e4c8f9f4624a8da72c0f5f3d96d0c54",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">3.8, <3.10",
"size": 93130,
"upload_time": "2024-01-18T08:42:00",
"upload_time_iso_8601": "2024-01-18T08:42:00.330687Z",
"url": "https://files.pythonhosted.org/packages/67/19/f11a64228b8a62e4c29962d79c4646bbe6ffe6297c930e16cae300f79e10/xiaobaisaf-2.5.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7354a96dc29b2b71954d7e821d843f0924921965bdff12894ee004ee46257f25",
"md5": "e30e20fa061c78e526b5a30382e89903",
"sha256": "71e77dda3e4a7665a71474dcaba6ee7139361086594a8f9a5472b71c72b7e9bc"
},
"downloads": -1,
"filename": "xiaobaisaf-2.5.0.tar.gz",
"has_sig": false,
"md5_digest": "e30e20fa061c78e526b5a30382e89903",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">3.8, <3.10",
"size": 73304,
"upload_time": "2024-01-18T08:42:06",
"upload_time_iso_8601": "2024-01-18T08:42:06.366738Z",
"url": "https://files.pythonhosted.org/packages/73/54/a96dc29b2b71954d7e821d843f0924921965bdff12894ee004ee46257f25/xiaobaisaf-2.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-18 08:42:06",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "xiaobaisaf"
}