'2.0版本更新'
|
@ -0,0 +1 @@
|
||||||
|
75326e83b55ea4a745898a117ce7ef34b5e1
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Time : 2021/11/18 23:05
|
# @Time : 2022/3/29 17:31
|
||||||
# @Author : 余少琪
|
# @Author : 余少琪
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/30 13:32
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class AllureAttachmentType(Enum):
|
||||||
|
"""
|
||||||
|
allure 报告的文件类型枚举
|
||||||
|
"""
|
||||||
|
TEXT = "txt"
|
||||||
|
CSV = "csv"
|
||||||
|
TSV = "tsv"
|
||||||
|
URI_LIST = "uri"
|
||||||
|
|
||||||
|
HTML = "html"
|
||||||
|
XML = "xml"
|
||||||
|
JSON = "json"
|
||||||
|
YAML = "yaml"
|
||||||
|
PCAP = "pcap"
|
||||||
|
|
||||||
|
PNG = "png"
|
||||||
|
JPG = "jpg"
|
||||||
|
SVG = "svg"
|
||||||
|
GIF = "gif"
|
||||||
|
BMP = "bmp"
|
||||||
|
TIFF = "tiff"
|
||||||
|
|
||||||
|
MP4 = "mp4"
|
||||||
|
OGG = "ogg"
|
||||||
|
WEBM = "webm"
|
||||||
|
|
||||||
|
PDF = "pdf"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def attachment_types():
|
||||||
|
return list(map(lambda c: c.value, AllureAttachmentType))
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/29 18:03
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class AssertType(Enum):
|
||||||
|
EQUAL = "=="
|
||||||
|
NOTEQUAL = "!="
|
||||||
|
IN = "IN"
|
||||||
|
NO_TIN = "NOTIN"
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/29 17:32
|
||||||
|
# @Author : 余少琪
|
||||||
|
from enum import Enum, unique
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class DependentType(Enum):
|
||||||
|
"""
|
||||||
|
数据依赖相关枚举
|
||||||
|
"""
|
||||||
|
# 依赖响应中数据
|
||||||
|
RESPONSE = 'response'
|
||||||
|
# 依赖请求中的数据
|
||||||
|
REQUEST = 'request'
|
||||||
|
# 依赖sql中的数据
|
||||||
|
SQL_DATA = 'sqlData'
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/30 23:06
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationType(Enum):
|
||||||
|
""" 自动化通知方式 """
|
||||||
|
# 默认通知: 不发送
|
||||||
|
DEFAULT = 0
|
||||||
|
# 钉钉通知
|
||||||
|
DING_TALK = 1
|
||||||
|
# 微信通知
|
||||||
|
WECHAT = 2
|
||||||
|
# 邮箱通知
|
||||||
|
EMAIL = 3
|
||||||
|
# 飞书通知
|
||||||
|
FEI_SHU = 4
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/29 17:42
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class RequestType(Enum):
|
||||||
|
"""
|
||||||
|
request请求发送,请求参数的数据类型
|
||||||
|
"""
|
||||||
|
# json 类型
|
||||||
|
JSON = "JSON"
|
||||||
|
# PARAMS 类型
|
||||||
|
PARAMS = "PARAMS"
|
||||||
|
# data 类型
|
||||||
|
DATE = "DATE"
|
||||||
|
# 文件类型
|
||||||
|
FILE = 'FILE'
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/29 17:51
|
||||||
|
# @Author : 余少琪
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class YAMLDate(Enum):
|
||||||
|
"""
|
||||||
|
测试用例相关字段
|
||||||
|
"""
|
||||||
|
# host 配置
|
||||||
|
HOST = 'host'
|
||||||
|
# 接口请求的url
|
||||||
|
URL = 'url'
|
||||||
|
# 请求方式
|
||||||
|
METHOD = 'method'
|
||||||
|
# 请求头
|
||||||
|
HEADER = 'headers'
|
||||||
|
# 请求类型
|
||||||
|
REQUEST_TYPE = 'requestType'
|
||||||
|
# 是否执行
|
||||||
|
IS_RUN = 'is_run'
|
||||||
|
# 请求参数
|
||||||
|
DATA = 'data'
|
||||||
|
# 是否依赖用例
|
||||||
|
DEPENDENCE_CASE = 'dependence_case'
|
||||||
|
# 依赖用例参数
|
||||||
|
DEPENDENCE_CASE_DATA = 'dependence_case_data'
|
||||||
|
# 断言内容
|
||||||
|
ASSERT = 'assert'
|
||||||
|
# sql内容
|
||||||
|
SQL = 'sql'
|
||||||
|
# 用例ID
|
||||||
|
CASE_ID = 'case_id'
|
||||||
|
# jsonpath提取
|
||||||
|
JSONPATH = 'jsonpath'
|
||||||
|
# 替换的内容
|
||||||
|
REPLACE_KEY = 'replace_key'
|
||||||
|
# 依赖数据类型
|
||||||
|
DEPENDENT_TYPE = 'dependent_type'
|
||||||
|
# 用例描述
|
||||||
|
DETAIL = 'detail'
|
||||||
|
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 187 KiB |
After Width: | Height: | Size: 2.1 KiB |
604
README.md
|
@ -1,6 +1,6 @@
|
||||||
## 框架介绍
|
## 框架介绍
|
||||||
|
|
||||||
本框架主要是基于 Python + pytest + allure + log + yaml + mysql + 钉钉通知 + Jenkins 实现的接口自动化框架。
|
本框架主要是基于 Python + pytest + allure + log + yaml + mysql + redis + 钉钉通知 + Jenkins 实现的接口自动化框架。
|
||||||
|
|
||||||
* git地址: [https://gitee.com/yu_xiao_qi/pytest-auto-api](https://gitee.com/yu_xiao_qi/pytest-auto-api)
|
* git地址: [https://gitee.com/yu_xiao_qi/pytest-auto-api](https://gitee.com/yu_xiao_qi/pytest-auto-api)
|
||||||
* 项目参与者: 余少琪
|
* 项目参与者: 余少琪
|
||||||
|
@ -9,11 +9,18 @@
|
||||||
|
|
||||||
如果对您有帮助,请点亮 小星星 以表支持,谢谢
|
如果对您有帮助,请点亮 小星星 以表支持,谢谢
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 框架优势
|
## 前言
|
||||||
|
公司突然要求你做自动化,但是没有代码基础不知道怎么做?或者有自动化基础,但是不知道如何系统性的做自动化,
|
||||||
|
放在yaml文件中维护,不知道如何处理多业务依赖的逻辑?
|
||||||
|
|
||||||
本框架不收取任何费用, 其优势在于测试人员直接编写测试用例,运行框架可自动生成测试代码。
|
那么这里 Gitte 中开源的自动化框架,将为你解决这些问题。
|
||||||
框架支持多环境、多角色任意切换,支持接口响应断言以及数据库断言。
|
框架主要使用 python 语言编写,结合 pytest 进行二次开发,用户仅需要在 yaml 文件中编写测试用例,
|
||||||
|
编写成功之后,会自动生成 pytest 的代码,零基础代码小白,也可以操作。
|
||||||
|
|
||||||
|
本框架支持多业务接口依赖,多进程执行,mysql 数据库断言和 接口响应断言,并且用例直接在yaml文件中维护,无需编写业务代码,
|
||||||
|
接口pytest框架生成allure报告,并且发送 企业微信通知/ 钉钉通知/ 邮箱通知/ 飞书通知,灵活配置。
|
||||||
|
|
||||||
## 实现功能
|
## 实现功能
|
||||||
|
|
||||||
|
@ -29,35 +36,57 @@
|
||||||
* 多线程执行
|
* 多线程执行
|
||||||
|
|
||||||
## 目录结构
|
## 目录结构
|
||||||
├── Cache // 存放缓存文件
|
├── Cache // 存放缓存文件
|
||||||
├── config // 配置
|
├── config // 配置
|
||||||
│ ├── conf.yaml // 公共配置
|
│ ├── conf.yaml // 公共配置
|
||||||
│ ├── setting.py // 环境路径存放区域
|
│ ├── setting.py // 环境路径存放区域
|
||||||
├── data // 测试用例数据
|
├── data // 测试用例数据
|
||||||
├── docs // 文档
|
├── Enums // 枚举层,用于存放项目中所需的枚举
|
||||||
├── lib // 对象层,用作于接口的调用
|
├── File // 上传文件接口所需的文件存放区域
|
||||||
├── log // 日志层
|
├── log // 日志层
|
||||||
├── report // 测试报告层
|
├── report // 测试报告层
|
||||||
├── test_case // 测试用例代码
|
├── test_case // 测试用例代码
|
||||||
├── tool // 所有公共模块的封装
|
├── utils // 工具类
|
||||||
│ └── allureDataControl.py // allure报告数据清洗
|
│ └── assertUtils // 断言
|
||||||
│ └── assertControl.py // 断言模块
|
│ └── assertUtils .py
|
||||||
│ └── cacheControl.py // 缓存模块
|
│ └── cacheUtils // 缓存处理模块
|
||||||
│ └── dingtalkControl.py // 钉钉发送通知
|
│ └── cacheControl.py
|
||||||
│ └── excelControl.py // 读取excel文件
|
│ └── redisControl.py
|
||||||
│ └── gettimeControl.py // 时间模块
|
│ └── logUtils // 日志处理模块
|
||||||
│ └── logControl.py // 日志模块
|
│ └── logControl.py
|
||||||
│ └── logDecorator.py // 日志装饰器
|
│ └── logDecoratrol.py // 日志装饰器
|
||||||
│ └── mysqlControl.py // 数据库模块
|
│ └── runTimeDecoratrol.py // 统计用例执行时长装饰器
|
||||||
│ └── regularControl.py // 正则模块
|
│ └── mysqlUtils // 数据库模块
|
||||||
│ └── requestControl.py // 请求模块
|
│ └── get_sql_data.py
|
||||||
│ └── runtimeControl.py // 响应时长统计模块
|
│ └── mysqlControl.py
|
||||||
│ └── sendmailControl.py // 发送邮件
|
│ └── noticUtils // 通知模块
|
||||||
│ └── testcaseAutomaticControl.py // 自动生成测试代码
|
│ └── dingtalkControl.py // 钉钉通知
|
||||||
│ └── yamlControl.py // yaml文件
|
│ └── feishuControl.py // 飞书通知
|
||||||
├── Readme.md // help
|
│ └── sendmailControl.py // 邮箱通知
|
||||||
|
│ └── weChatSendControl.py // 企业微信通知
|
||||||
|
│ └── otherUtils // 其他工具类
|
||||||
|
│ └── allureDate // allure封装
|
||||||
|
│ └── allure_report_data.py // allure报告数据清洗
|
||||||
|
│ └── allure_tools..py // allure 方法封装
|
||||||
|
│ └── localIpControl.py // 获取本地IP
|
||||||
|
│ └── threadControl.py // 定时器类
|
||||||
|
│ └── readFilesUtils // 文件操作
|
||||||
|
│ └── caseAutomaticControl.py // 自动生成测试代码
|
||||||
|
│ └── clean_files.py // 清理文件
|
||||||
|
│ └── excelControl.py // 读写excel
|
||||||
|
│ └── get_all_files_path.py // 获取所有文件路径
|
||||||
|
│ └── get_yaml_data_analysis.py // yaml用例数据清洗
|
||||||
|
│ └── regularControl.py // 正则
|
||||||
|
│ └── yamlControl.py // yaml文件读写
|
||||||
|
│ └── recordingUtils // 代理录制
|
||||||
|
│ └── mitmproxyContorl..py
|
||||||
|
│ └── requestsUtils
|
||||||
|
│ └── dependentCase.py // 数据依赖处理
|
||||||
|
│ └── requestControl..py // 请求封装
|
||||||
|
│ └── timeUtils
|
||||||
|
├── Readme.md // help
|
||||||
├── pytest.ini
|
├── pytest.ini
|
||||||
├── run.py // 运行入口
|
├── run.py // 运行入口
|
||||||
|
|
||||||
|
|
||||||
## 依赖库
|
## 依赖库
|
||||||
|
@ -99,140 +128,433 @@
|
||||||
xlutils==2.0.0
|
xlutils==2.0.0
|
||||||
xlwt==1.3.0
|
xlwt==1.3.0
|
||||||
|
|
||||||
#### 安装Python、Pip环境,创建虚拟环境
|
|
||||||
```
|
|
||||||
一、安装Python环境
|
|
||||||
|
|
||||||
# 1、下载Python程序
|
|
||||||
# Python包地址:https://www.python.org/ftp/python/
|
|
||||||
wget https://www.python.org/ftp/python/3.8.5/Python-3.8.5.tgz
|
|
||||||
|
|
||||||
# 2、解压Python-3.8.5.tgz
|
|
||||||
tar -zxvf Python-3.8.5.tgz
|
|
||||||
|
|
||||||
# 3、编译安装
|
|
||||||
sudo mkdir /usr/local/python3.8.5
|
|
||||||
cd Python-3.8.5
|
|
||||||
sudo ./configure --prefix=/usr/local/python3.8.5
|
|
||||||
sudo make && sudo make install
|
|
||||||
|
|
||||||
# 4、建立软链接
|
|
||||||
sudo ln -s /usr/local/python3.8.5/bin/python3 /usr/bin/python3
|
|
||||||
sudo ln -s /usr/local/python3.8.5/bin/pip3 /usr/bin/pip3
|
|
||||||
|
|
||||||
# 5、验证安装
|
|
||||||
python3 -V
|
|
||||||
pip3 -V
|
|
||||||
|
|
||||||
二、安装虚拟环境、创建虚拟环境
|
|
||||||
# 1、安装虚拟环境virtualenv
|
|
||||||
yum install -y python-virtualenv
|
|
||||||
|
|
||||||
# 2、创建虚拟环境
|
|
||||||
# 在项目根目录创建虚拟环境
|
|
||||||
virtualenv -p python3 venv
|
|
||||||
|
|
||||||
# 3、激活虚拟环境
|
|
||||||
source ./venv/bin/activate
|
|
||||||
|
|
||||||
# 4、退出虚拟环境
|
|
||||||
deactivate
|
|
||||||
```
|
|
||||||
|
|
||||||
## 安装教程
|
## 安装教程
|
||||||
|
|
||||||
输入如下命令,安装本框架的所有第三方库依赖
|
输入如下命令,安装本框架的所有第三方库依赖
|
||||||
|
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
## 使用说明
|
## 用例中相关字段的介绍
|
||||||
|
|
||||||
### config-->conf.yaml
|

|
||||||
|
|
||||||

|
上方截图,就是一个用例中需要维护的相关字段,下面我会对每个字段的作用,做出解释。
|
||||||
|
|
||||||
首先是配置文件,这里主要存放了一个公共的配置数据,如项目名称、钉钉、邮箱、企业微信、数据库等相关的配置全部都在这里
|
1、case_common: 这个公共参数的维护,方便后期如有需要新增的字段,可以添加在公共参数中,
|
||||||
所有的字段,在conf.yaml中,都有相关的注释,自行修改即可。
|
目前只有三个:allureEpic、allureFeature、allureStory,
|
||||||
|
这三个都是allure报告需要用到的装饰器内容,后续自动生成 pytest 中 test_case 会用到这三个参数值。
|
||||||
|
2、spu_apply_list_01: 用例ID,唯一
|
||||||
|
3、host: 接口的域名: 填写规则如下 ${{host}},执行脚本时,会去读取conf.yaml 文件中配置域名
|
||||||
|
4、url: 接口路径
|
||||||
|
5、header: 请求头
|
||||||
|
6、requestType: 请求参数类型,有json、file、params、data四种类型
|
||||||
|
7、is_run: 是否执行,为空、或者 True 都会执行
|
||||||
|
8、data: 请求参数,所有的请求参数,全部放在 data 下方
|
||||||
|
9、dependence_case:判断该条用力,是否有依赖业务,如为空或者 false 则表示没有
|
||||||
|
10、dependence_case_data:依赖用例中需要的相关数据(下方数据依赖示例中,会对该字段下方的内容,做详细介绍)
|
||||||
|
11、assert: 断言,支持判断sql、或者接口响应内容。
|
||||||
|
12、sql:该用例中所需使用的sql
|
||||||
|
|
||||||
目前框架主要是用的企业微信通知,在用例执行成功之后发送通知,通知内容如下,可以根据公司主要使用的通讯工具自行更改。
|
### 如何发送get请求
|
||||||
在公共方法中分别封装了钉钉通知、以及邮箱通知。
|
上方了解了用例的数据结构之后,下面我们开始编写第一个get请求方式的接口。
|
||||||
|
首先,开始编写项目之后,我们在 conf.yaml 中配置项目的域名
|
||||||
|
|
||||||
# 注意点:
|

|
||||||
# 之前为了小伙伴们拉下代码执行的时候不受影响,企业微信、钉钉、邮箱的通知配置的都是我的
|
|
||||||
# 我发现很多拉代码的小伙伴这里配置都没改,所有的通知都发到我这里来了哦~~麻烦看到这里的小伙伴自己在conf.yaml改一下相关配置
|
|
||||||
|
|
||||||

|
域名配置好之后,我们来编写测试用例,在 data 文件下面,创建一个名称为
|
||||||
|
spu_apply_list.yaml 的用例文件,内容如下
|
||||||
|
|
||||||
如程序执行执行异常时,会自动收集错误信息,并将内容发送邮件。
|
# 公共参数
|
||||||
|
case_common:
|
||||||

|
allureEpic: 电商平台端
|
||||||
|
allureFeature: 审核中心
|
||||||
### config --> setting.py
|
allureStory: 商品审核列表
|
||||||
|
|
||||||
setting.py 文件主要是用来存放项目中所有文件的目录地址
|
|
||||||
|
|
||||||
更改过一些公用的配置之后,下面我们来开始编写自动化
|
|
||||||
|
|
||||||
### data 用来存放测试用例
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
上方主要是测试用例,测试用例是整个自动化程序中非常重要的一部分,需要严格按照我上方图中的格式进行编写。
|
|
||||||
下面我会对每个字段依次进行解释对应的作用。
|
|
||||||
|
|
||||||
- url: 请求接口的地址,${{MerchantHost}} 为接口的host,放在conf.yaml 文件中,可以更改成公司项目的host
|
|
||||||
- method: 请求方式,目前支持GET、POST、DELETE、PUT,本人公司目前设计到的请求方式只有这四种,如有需求可自行添加
|
|
||||||
- detail: 用例描述,程序中未强制要求必填,但是最好是每个用例都填写上,打印日志以及生成代码的函数注释,都会依赖用例描述
|
|
||||||
- header: 请求头
|
|
||||||
- requestType: 必填,这个字段主要取决于你请求的是参数是以json、params、file、或者data的格式
|
|
||||||
- data: 请求参数
|
|
||||||
如接口中需要的请求参数全部放在data中
|
|
||||||
- allureEpic: 作用与allure装饰器,必填(如有多个测试用例,只需要写在第一个用例中就行)
|
|
||||||
- allureFeature: 作用于allure装饰器,必填(如有多个测试用例,只需要写在第一个用例中就行)
|
|
||||||
- resp: 响应断言相关的数据
|
|
||||||
- 响应接口的参数字段(如code): code,就是接口的响应状态码,这些参数都是自己加的。
|
|
||||||
- jsonpath: 这里获取到对应的接口数据,主要使用到了jsonpath。如果有不了这一块的,大家可以看我的博客:https://blog.csdn.net/weixin_43865008/article/details/118371620
|
|
||||||
- value: 预期值,这里会根据你前面jsonpath中获取到的响应数据,然后和你添加的预期值进行断言。如果断言失败,会打印对应的日志信息,以及allure测试报告中也会呈现这条用例的失败状态
|
|
||||||
- type: 断言的类型,如判断是否相等,则使用”==“,或者”!=“,则表示内容不相等,”IN“则表示预期值是否在响应值中,对应的还有"NOTIN"
|
|
||||||
- AssertType: 目前自动化支持两种断言类型,接口响应断言和数据库断言。如果是接口响应断言,则AssertType的值可不填,如果值为"SQL"的话,则走数据库断言。为sql的时候,sql查询出来的数据类型是字典类型,因此value值会从sql查询出来的字段中使用jsonpath的形式读取sql查询出来的数据
|
|
||||||
- 如有多个数据,则可像上方图中一样,创建多个字段
|
|
||||||
- sql: sql 是以 LIST 的类型存储的,可以将我们这个接口需要依赖的sql语句全部放在这里,程序中会循环查询出sql中的所有语句,并且返回数据库中的值,从而与接口响应的值做匹配。(这里也是对于sql多表联查不太会的朋友的福音。如果不会多表联查的话,可以编写单表sql,程序中会将所有单表的数据内容全部查询出来)
|
|
||||||
- 接口中如有多条测试用例,则以上方格式为例,添加多个即可。
|
|
||||||
|
|
||||||
## lib---> xxx.py
|
|
||||||
|
|
||||||
假设我们按照上方图中的格式内容,创建了一个用例创建成功之后yaml文件的用例,创建之后下面我们来生成自动化脚本,执行第一条用例。
|
|
||||||

|
|
||||||
|
|
||||||
首先,我们找到tools目录下的 testcaseAutomaticControl.py 文件,然后执行这里的代码
|
|
||||||
|
|
||||||
执行成功之后,我们可以看到lib和test_case目录下,会生成一个和创建用例yaml文件名称一模一样的py文件,test_case名称会以test_开头
|
|
||||||
内容如下:
|
|
||||||

|
|
||||||
|
|
||||||
下面我们就可以开始执行我们的测试用例了,这里生成的文件,主要类似于我们自动化模型中的PO模型,生成的page
|
|
||||||
|
spu_apply_list_01:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /api/v1/work/spu/approval/spuList
|
||||||
|
method: GET
|
||||||
|
detail: 查看商品审核列表
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
token: work_login_init
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: params
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run: False
|
||||||
|
data:
|
||||||
|
spuType: 1
|
||||||
|
pageNum: 1
|
||||||
|
pageSize: 10
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case:
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
AssertType:
|
||||||
|
sql:
|
||||||
|
|
||||||
执行之后,我们可以看到下方详细的请求日志信息,方便我们进行用例调试(lie层只是作用域单个接口的调试,如果需要多接口跑业务的话,直接到test_case层去做即可)
|
get请求我们 requestType 写的是params,这样发送请求时,我们会将请求参数拼接中url中,最终像服务端发送请求的地址格式会为:
|
||||||
|
|
||||||

|
${{host}}/api/v1/work/spu/approval/spuList?supType=1&pageNum=1&pageSize=10
|
||||||
|
|
||||||
test_case --> test_apply_verifycode.py
|
### 如何发送post请求
|
||||||
|
|
||||||
__用例调试成功之后,下面我们进入编写用例脚本阶段,主要内容如下:__
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 盲盒APP
|
||||||
|
allureFeature: 登录模块
|
||||||
|
allureStory: 获取登录验证码
|
||||||
|
|
||||||
|
send_sms_code_01:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /mobile/sendSmsCode
|
||||||
|
method: POST
|
||||||
|
detail: 正常获取登录验证码
|
||||||
|
headers:
|
||||||
|
appId: '23132'
|
||||||
|
masterAppId: masterAppId
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run:
|
||||||
|
data:
|
||||||
|
phoneNumber: "180xxxx9278"
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: False
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: '00000'
|
||||||
|
AssertType:
|
||||||
|
success:
|
||||||
|
jsonpath: $.success
|
||||||
|
type: ==
|
||||||
|
value: true
|
||||||
|
AssertType:
|
||||||
|
|
||||||
|
sql:
|
||||||
|
|
||||||
|
这里post请求,我们需要请求的数据格式是json格式的,那么requestType 则填写为json格式。包括 PUT/DELETE/HEAD 请求的数据格式都是一样的,唯一不同的就是需要配置 reuqestType,如果需要请求的参数是json格式,则requestType我们就填写json,如果是url拼接的形式,我们就填写 params
|
||||||
|
|
||||||

|
### 如何测试上传文件接口
|
||||||
|
|
||||||
其中代码中关于pytest的相关内容,网上的资料有非常多,并且非常详情,这里不做赘述。
|
首先,我们将所有需要测试的文件,全部都放在 files 文件夹中
|
||||||
|

|
||||||
|
|
||||||
所有的用例内容,格式都为统一的,目前只能生成单接口的业务用例,如果需要接口执行的话,还需要在case层调用对应业务的接口
|
requestType: file
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run:
|
||||||
|
data:
|
||||||
|
file:
|
||||||
|
# file 直接写文件名称
|
||||||
|
files:排入水体名.png
|
||||||
|
|
||||||
用例添加完成之后,执行run.py,程序会执行所有文件的用例,并且生成测试报告,发送钉钉通知。
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: False
|
||||||
|
|
||||||
|
在yaml文件中,我们需要注意两个地方,主要是用例中的requestType、和 filename 字段:
|
||||||
|
1、requestType: 上传文件,我们需要更改成 file
|
||||||
|
2、filename 参数名称: 上传文件,我们只需要填写files文件夹下的文件名称即可,程序在发送请求时,会去识别文件
|
||||||
|
|
||||||
|
### 多业务逻辑,如何编写测试用例
|
||||||
|
多业务这一块,我们拿个简单的例子举例,比如登录场景,在登陆之前,我们需要先获取到验证码。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
首先,我们先创建一个 get_send_sms_code.yaml 的文件,编写一条发送验证码的用例
|
||||||
|
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 盲盒APP
|
||||||
|
allureFeature: 登录模块
|
||||||
|
allureStory: 获取登录验证码
|
||||||
|
|
||||||
|
send_sms_code_01:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /mobile/sendSmsCode
|
||||||
|
method: POST
|
||||||
|
detail: 正常获取登录验证码
|
||||||
|
headers:
|
||||||
|
appId: '23132'
|
||||||
|
masterAppId: masterAppId
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run:
|
||||||
|
data:
|
||||||
|
phoneNumber: "180****9278"
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: False
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: '00000'
|
||||||
|
AssertType:
|
||||||
|
success:
|
||||||
|
jsonpath: $.success
|
||||||
|
type: ==
|
||||||
|
value: true
|
||||||
|
AssertType:
|
||||||
|
|
||||||
|
sql:
|
||||||
|
|
||||||
|
编写好之后,我们在创建一个 login.yaml 文件
|
||||||
|
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 盲盒APP
|
||||||
|
allureFeature: 登录模块
|
||||||
|
allureStory: 登录
|
||||||
|
|
||||||
|
login_02:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /login/phone
|
||||||
|
method: POST
|
||||||
|
detail: 登录输入错误的验证码
|
||||||
|
headers:
|
||||||
|
appId: '23132'
|
||||||
|
masterAppId: masterAppId
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run:
|
||||||
|
data:
|
||||||
|
phoneNumber: 18014909278
|
||||||
|
code:
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: True
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
- case_id: send_sms_code_02
|
||||||
|
dependent_data:
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.code
|
||||||
|
replace_key: $.data.code
|
||||||
|
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: '00000'
|
||||||
|
AssertType:
|
||||||
|
sql:
|
||||||
|
|
||||||
|
其中处理多业务的核心区域,主要在这里:
|
||||||
|
|
||||||
|
dependence_case: True
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
- case_id: send_sms_code_02
|
||||||
|
dependent_data:
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.code
|
||||||
|
replace_key: $.data.code
|
||||||
|
|
||||||
|
首先,我们 dependence_case 需要设置成 True,并且在下面的 dependence_case_data 中设计相关依赖的数据。
|
||||||
|
|
||||||
|
1、case_id:上方场景中,我们登录需要先获取验证码,因此依赖的case_id 就是发送短信验证码的 case_id :send_sms_code_02
|
||||||
|
2、dependent_type:我们依赖的是获取短信验证码接口中的响应内容,因此这次填写的是 response
|
||||||
|
3、jsonpath: 通过jsonpath 提取方式,提取到短信验证码中的验证码内容
|
||||||
|
4、replace_key:拿到验证码之后,我们将本条用例中的data中的code参数,那么我们使用jsonpath的方式,进行替换 $.data.code
|
||||||
|
|
||||||
|
### 多业务逻辑,需要依赖同一个接口中的多个数据
|
||||||
|
dependence_case_data:
|
||||||
|
- case_id: send_sms_code_02
|
||||||
|
dependent_data:
|
||||||
|
# 提取接口响应的code码
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.code
|
||||||
|
replace_key: $.data.code
|
||||||
|
# 提取接口响应的accessToken
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.data.accessToken
|
||||||
|
# 替换请求头中的accessToken
|
||||||
|
replace_key: $.headers.accessToken
|
||||||
|
|
||||||
|
|
||||||
### 关于框架未来功能的规划
|
如上方示例,可以添加多个 dependent_type
|
||||||
|
|
||||||
1、计划后期多接口业务逻辑,也统一放在yaml文件中维护,并且生成对应业务逻辑的相关代码
|
### 多业务逻辑,需要依赖不同接口的数据
|
||||||
2、自动生成代码的功能,计划通过多线程实现
|
假设我们需要获取 send_sms_code_01、get_code_01两个接口中的数据,用例格式如下
|
||||||
|
|
||||||
|
dependence_case: True
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
- case_id: send_sms_code_01
|
||||||
|
dependent_data:
|
||||||
|
# 提取接口响应的code码
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.code
|
||||||
|
replace_key: $.data.code
|
||||||
|
- case_id: get_code_01
|
||||||
|
dependent_data:
|
||||||
|
# 提取接口响应的code码
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.code
|
||||||
|
replace_key: $.data.code
|
||||||
|
|
||||||
|
### 用例中需要依赖登录的token,如何设计
|
||||||
|
|
||||||
|
首先,为了防止重复请求调用登录接口,pytest中的 conftest.py 提供了热加载机制,看上方截图中的代码,我们需要在 conftest.py 提前编写好登录的代码。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如上方代码所示,我们会先去读取login.yaml文件中的用例,然后执行获取到响应中的token,然后 编写 Cache('work_login_init').set_caches(token),将token写入缓存中,其中 work_login_init 是缓存名称。
|
||||||
|
|
||||||
|
编写好之后,我们会在 requestControl.py 文件中,读取缓存中的token,如果该条用例需要依赖token,则直接进行内容替换。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这里在编写用例的时候,token 填写我们所编写的缓存名称即可。
|
||||||
|
|
||||||
|
### 用例中如何生成随机数据
|
||||||
|
|
||||||
|
比如我们有些特殊的场景,可能会涉及到一些定制化的数据,每次执行数据,需要按照指定规则随机生成。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如上图所示,我们用例中的 reason 审核原因后方,需要展示审核的当前时间。那么我们首先需要封装一个获取当前时间的方法
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
那么我们就在 regularControl.py 文件中,编写 get_time 的方法。编写好之后,在用例中编写规则如下:
|
||||||
|
|
||||||
|
reason: 审核时间${{get_time}}
|
||||||
|
使用 ${{函数名称}}的方法,程序调用时,会生成当前时间。在regularControl.py 文件中,我还封装了一些常用的随机数,如随机生成男生姓名、女生姓名、身份证、邮箱、手机号码之类的,方便大家使用。 如,随机生成邮箱,我们在用例中编写的格式为 ${{get_email}} 。
|
||||||
|
|
||||||
|
其他所需随机生成的数据,可在文件中自行添加。
|
||||||
|
|
||||||
|
|
||||||
|
### 用例中如何进行接口断言和数据库断言
|
||||||
|
|
||||||
|
假设现在我需要测试一个报表统计的数据,该接口返回了任务的处理时长 和 处理数量。功能如下截图所示:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
假设下方是我们拿到接口响应的数据内容:
|
||||||
|
|
||||||
|
{"code": 200, "times": 155.91, "counts": 9}
|
||||||
|
|
||||||
|
这个时候,我们需要判断该接口返回的数据是否正确,就需要编写sql,对响应内容进行校验。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
因此我们编写了如上sql,查出对应的数据,那么用例中编写规则如下,下方我们分别断言了两个内容,一个是对接口的响应code码进行断言,一个是断言数据库中的数据。
|
||||||
|
|
||||||
|
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
# 断言接口响应时,可以为空
|
||||||
|
AssertType:
|
||||||
|
do_time:
|
||||||
|
# jsonpath 拿到接口响应的数据
|
||||||
|
jsonpath: $.times
|
||||||
|
type: ==
|
||||||
|
# sql 查出来的数据,是字典类型的,因此这里是从字段中提取查看出来的字段
|
||||||
|
value: $.do_time
|
||||||
|
# 断言sql的时候,AssertType 的值需要填写成 SQL
|
||||||
|
AssertType: SQL
|
||||||
|
question_counts:
|
||||||
|
jsonpath: $.counts
|
||||||
|
type: ==
|
||||||
|
#
|
||||||
|
value: $.question_counts
|
||||||
|
# 断言sql的时候,AssertType 的值需要填写成 SQL
|
||||||
|
AssertType: SQL
|
||||||
|
sql:
|
||||||
|
- select * from test_goods where shop_id = 515
|
||||||
|
|
||||||
|
我们分别对用例的数据进行讲解,首先是响应断言, 编写规则如下
|
||||||
|
|
||||||
|
code:
|
||||||
|
# 通过jsonpath获取接口响应中的code {"code": 200, "times": 155.91, "counts": 9}
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
# 断言接口响应时,可以为空
|
||||||
|
AssertType:
|
||||||
|
|
||||||
|
下面是对sql进行断言
|
||||||
|
|
||||||
|
question_counts:
|
||||||
|
# 断言接口响应的问题上报数量counts {"code": 200, "times": 155.91, "counts": 9}
|
||||||
|
jsonpath: $.counts
|
||||||
|
type: ==
|
||||||
|
# 查询sql,我们数据库查到的数据是一个字段,数据是这样的:{question_counts: 13, do_time: 1482.70}, 这里我们通过 jsonpath获取question_counts
|
||||||
|
value: $.question_counts
|
||||||
|
# 断言sql的时候,AssertType 的值需要填写成 SQL
|
||||||
|
AssertType: SQL
|
||||||
|
sql:
|
||||||
|
- SELECT round( sum(( UNIX_TIMESTAMP( filing_time )- UNIX_TIMESTAMP( report_time )) / 60 ) / 60, 2 ) AS do_time, count( id ) AS question_counts FROM fl_report_info WHERE state IN ( 1, 3 )
|
||||||
|
|
||||||
|
有些细心的小伙伴会发现,我们的sql,是列表类型的。这样就意味这,我们的sql可以同时编写多条,这样会对不会编写多表联查的小伙伴比较友好,可以进行单表查询,获取我们需要的数据。
|
||||||
|
|
||||||
|
sql:
|
||||||
|
- select * from users;
|
||||||
|
- select * from goods;
|
||||||
|
|
||||||
|
### 自动生成test_case层代码
|
||||||
|
|
||||||
|
小伙伴们在编写好 yaml 用例之后,可以直接执行 caseAutomaticControl.py ,会跟你设计的测试用例,生成对应的代码。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 发送钉钉通知通知
|
||||||
|

|
||||||
|
|
||||||
|
### 发送企业微信通知
|
||||||
|

|
||||||
|
|
||||||
|
### 日志打印装饰器
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在requestControl.py中,我单独封装了一个日志装饰器,需要的小伙伴可以不用改动代码,直接使用,如果不需要,直接注释,或者改成False。控制台将不会有日志输出
|
||||||
|
|
||||||
|
### 统计用例运行时长
|
||||||
|

|
||||||
|
|
||||||
|
同样,这里封装了一个统计用例运行时长的装饰器,使用改装饰器前,需要先进行导包
|
||||||
|
|
||||||
|
from utils.logUtils.runTimeDecoratorl import execution_duration
|
||||||
|
导入之后,调用改装饰器,装饰器中填写的用例执行时长,以毫秒为单位,如这里设置的2000ms,那么如果该用例执行大于2000ms,则会输出一条告警日志。
|
||||||
|
|
||||||
|
@execution_duration(2000)
|
||||||
|
|
||||||
|
### 生成allure报告
|
||||||
|
我们直接运行主程序 run.py ,运行完成之后,就可以生成漂亮的allure报告啦~
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 其他
|
||||||
|
|
||||||
|
本框架为2.0升级版本,升级之后的功能,现在基本上都是在yaml中维护用例,无需测试人员编写代码,
|
||||||
|
和 1.0版本的区别在于,1.0版本还需要测试人员手动编写多业务逻辑的代码,需要有一定基础编码的能力
|
||||||
|
|
||||||
|
但是1.0版本,同样也可以自动生成代码,yaml中维护数据,对相对简单,如果偏于yaml简单维护的同学,可以切换查看1.0分支
|
||||||
|
下方是1.0分支的操作文档:[点我查看](https://blog.csdn.net/weixin_43865008/article/details/121903028?spm=1001.2014.3001.5502)
|
||||||
|
|
||||||
*******************************************************
|
*******************************************************
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,17 @@ ProjectName:
|
||||||
- 余少琪的框架
|
- 余少琪的框架
|
||||||
-
|
-
|
||||||
|
|
||||||
|
Env: 测试环境
|
||||||
# 测试人员名称,作用于自动生成代码的作者,以及发送企业微信、钉钉通知的测试负责人
|
# 测试人员名称,作用于自动生成代码的作者,以及发送企业微信、钉钉通知的测试负责人
|
||||||
TestName: 余少琪
|
TesterName: 余少琪
|
||||||
|
|
||||||
# 域名1
|
# 域名1
|
||||||
Host: https://redisdatarecall.csdn.net
|
host: https://www.baidu.com # 域名随便写的,记得修改
|
||||||
|
app_host:
|
||||||
# 域名2
|
# 域名2
|
||||||
work:
|
work:
|
||||||
|
|
||||||
# 报告通知类型:1:钉钉 2:企业微信通知 3、邮箱
|
# 报告通知类型:0: 不发送通知 1:钉钉 2:企业微信通知 3、邮箱通知 4、飞书通知
|
||||||
NotificationType: 2
|
NotificationType: 2
|
||||||
|
|
||||||
# 注意点:
|
# 注意点:
|
||||||
|
@ -24,12 +26,11 @@ DingTalk:
|
||||||
|
|
||||||
# 数据库相关配置
|
# 数据库相关配置
|
||||||
MySqlDB:
|
MySqlDB:
|
||||||
# 数据库开关
|
|
||||||
switch: False
|
switch: False
|
||||||
host:
|
host:
|
||||||
user:
|
user: dev
|
||||||
password:
|
password:
|
||||||
db: test_obp_data
|
db:
|
||||||
|
|
||||||
|
|
||||||
# 企业通知的相关配置
|
# 企业通知的相关配置
|
||||||
|
@ -39,6 +40,10 @@ WeChat:
|
||||||
email:
|
email:
|
||||||
send_user: 1603453211@qq.com
|
send_user: 1603453211@qq.com
|
||||||
email_host: smtp.qq.com
|
email_host: smtp.qq.com
|
||||||
stmp_key: rzuabbobadbuhadc
|
stamp_key: rzuabbobadbuhadc
|
||||||
# 收件人
|
# 收件人
|
||||||
send_list: 1603453211@qq.com
|
send_list: 1603453211@qq.com
|
||||||
|
|
||||||
|
# 飞书通知
|
||||||
|
FeiShuTalk:
|
||||||
|
webhook:
|
|
@ -28,23 +28,16 @@ class ConfigHandler:
|
||||||
# 项目路径
|
# 项目路径
|
||||||
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
# 测试数据路径
|
# 用例路径
|
||||||
date_path = os.path.join(root_path, 'data' + _SLASH + "Merchant" + _SLASH + "UserLogin")
|
case_path = os.path.join(root_path, 'test_case' + _SLASH)
|
||||||
|
# 测试用例数据路径
|
||||||
merchant_data_path = os.path.join(root_path, 'data' + _SLASH)
|
|
||||||
|
|
||||||
data_path = os.path.join(root_path, 'data' + _SLASH)
|
data_path = os.path.join(root_path, 'data' + _SLASH)
|
||||||
|
|
||||||
cache_path = os.path.join(root_path, 'Cache' + _SLASH)
|
cache_path = os.path.join(root_path, 'Cache' + _SLASH)
|
||||||
|
if not os.path.exists(cache_path):
|
||||||
|
os.mkdir(cache_path)
|
||||||
|
|
||||||
case_path = os.path.join(root_path, 'test_case' + _SLASH)
|
log_path = os.path.join(root_path, 'logs' + _SLASH + 'log.log')
|
||||||
|
|
||||||
# 测试报告路径
|
|
||||||
report_path = os.path.join(root_path, 'report')
|
|
||||||
|
|
||||||
json_path = os.path.join(root_path, 'data' + _SLASH + 'data.json')
|
|
||||||
|
|
||||||
log_path = os.path.join(root_path + _SLASH + 'logs')
|
|
||||||
|
|
||||||
info_log_path = os.path.join(root_path, 'logs' + _SLASH + 'info.log')
|
info_log_path = os.path.join(root_path, 'logs' + _SLASH + 'info.log')
|
||||||
|
|
||||||
|
@ -52,23 +45,20 @@ class ConfigHandler:
|
||||||
|
|
||||||
warning_log_path = os.path.join(root_path, 'logs' + _SLASH + 'warning.log')
|
warning_log_path = os.path.join(root_path, 'logs' + _SLASH + 'warning.log')
|
||||||
|
|
||||||
if not os.path.exists(report_path):
|
config_path = os.path.join(root_path, 'config' + _SLASH + 'config.yaml')
|
||||||
os.mkdir(report_path)
|
|
||||||
|
|
||||||
config_path = os.path.join(root_path, 'config' + _SLASH + 'conf.yaml')
|
file_path = os.path.join(root_path, 'Files' + _SLASH)
|
||||||
|
|
||||||
token_yaml_path = os.path.join(root_path, 'data' + _SLASH + 'token.yaml')
|
# 测试报告路径
|
||||||
|
report_path = os.path.join(root_path, 'report')
|
||||||
excel_path = os.path.join(root_path, 'data' + _SLASH)
|
|
||||||
|
|
||||||
# lib 存放po文件
|
# lib 存放po文件
|
||||||
lib_path = os.path.join(root_path, "lib" + _SLASH)
|
lib_path = os.path.join(root_path, "lib" + _SLASH)
|
||||||
|
|
||||||
temp_path = os.path.join(root_path, 'report' + _SLASH + 'tmp')
|
# temp_path = os.path.join(root_path, 'report' + _SLASH + 'tmp')
|
||||||
if not os.path.exists(temp_path):
|
# if not os.path.exists(temp_path):
|
||||||
os.mkdir(temp_path)
|
# os.mkdir(temp_path)
|
||||||
html_path = os.path.join(root_path, 'report' + _SLASH + 'html')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print(ConfigHandler.temp_path)
|
print(ConfigHandler.cache_path)
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 电商平台端
|
||||||
|
allureFeature: 登录模块
|
||||||
|
allureStory: 正常登录
|
||||||
|
|
||||||
|
login:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /api/v1/work/user/loginByPassword
|
||||||
|
method: POST
|
||||||
|
detail: 正常登录
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run: True
|
||||||
|
data:
|
||||||
|
param:
|
||||||
|
phone: '13300000000'
|
||||||
|
password: '123456'
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: False
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
AssertType:
|
||||||
|
sql:
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022/3/30 14:56
|
||||||
|
# @Author : 余少琪
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'WorkApplyCenter/sup_apply_list.yaml').case_process()
|
||||||
|
print(TestData)
|
||||||
|
# print([i for i in TestData])
|
||||||
|
is_run = [i['is_run'] for i in TestData]
|
||||||
|
print(is_run)
|
|
@ -0,0 +1,31 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 电商平台
|
||||||
|
allureFeature: 文件模块
|
||||||
|
allureStory: PATCH
|
||||||
|
|
||||||
|
batchDisable_01:
|
||||||
|
host: {{host}}
|
||||||
|
url: /adpt/advert/adplan/batchDisable
|
||||||
|
method: PATCH
|
||||||
|
detail: 测试PATCH接口
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
Authorization: work_login_init
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run: Fasle
|
||||||
|
data:
|
||||||
|
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: False
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
AssertType:
|
||||||
|
sql:
|
|
@ -0,0 +1,41 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 电商平台端
|
||||||
|
allureFeature: 审核中心
|
||||||
|
allureStory: 商品审核
|
||||||
|
|
||||||
|
spu_apply_01:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /api/v1/work/spu/approval/pass
|
||||||
|
method: PUT
|
||||||
|
detail: 正常审核商品(测试一个接口依赖多个数据)
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
token: work_login_init
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run: False
|
||||||
|
data:
|
||||||
|
applyId:
|
||||||
|
reason: 审核时间${{get_time}}
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: True
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
- case_id: spu_apply_list_01
|
||||||
|
dependent_data:
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.data.data.[0].applyId
|
||||||
|
replace_key: $.data.applyId
|
||||||
|
- dependent_type: request
|
||||||
|
jsonpath: $.detail
|
||||||
|
replace_key: $.data.reason
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
AssertType:
|
||||||
|
sql:
|
||||||
|
- select * from test_goods where shop_id = 515
|
|
@ -0,0 +1,34 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 电商平台端
|
||||||
|
allureFeature: 审核中心
|
||||||
|
allureStory: 商品审核列表
|
||||||
|
|
||||||
|
|
||||||
|
spu_apply_list_01:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /api/v1/work/spu/approval/spuList
|
||||||
|
method: GET
|
||||||
|
detail: 查看商品审核列表
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
token: work_login_init
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: params
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run: False
|
||||||
|
data:
|
||||||
|
spuType: 1
|
||||||
|
pageNum: 1
|
||||||
|
pageSize: 10
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case:
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
AssertType:
|
||||||
|
sql:
|
|
@ -0,0 +1,42 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 电商平台端
|
||||||
|
allureFeature: 审核中心
|
||||||
|
allureStory: 商品审核详情
|
||||||
|
|
||||||
|
spuApplyDetails_01:
|
||||||
|
host: ${{host}}
|
||||||
|
url: /api/v1/work/spu/approval/spuApplyDetails/$url_param{good_id}
|
||||||
|
method: GET
|
||||||
|
detail: 查看商品审核详情
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
token: work_login_init
|
||||||
|
# 请求的数据,是 params 还是 json、或者file\date
|
||||||
|
requestType: json
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run: False
|
||||||
|
data:
|
||||||
|
auth:
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: True
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
- case_id: spu_apply_list_01
|
||||||
|
dependent_data:
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.data.data.[0].applyId
|
||||||
|
replace_key: $url_param{good_id}
|
||||||
|
- case_id: login_01
|
||||||
|
dependent_data:
|
||||||
|
- dependent_type: response
|
||||||
|
jsonpath: $.data.data.[0].token
|
||||||
|
replace_key: $.data.auth
|
||||||
|
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 200
|
||||||
|
AssertType:
|
||||||
|
sql:
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Time : 2021/11/18 23:05
|
# @Time : 2022/3/28 10:49
|
||||||
# @Author : 余少琪
|
# @Author : 余少琪
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
- # 用例001
|
|
||||||
url: ${{Host}}/recommend/get_head_word
|
|
||||||
method: POST
|
|
||||||
detail: 测试接口
|
|
||||||
headers:
|
|
||||||
Content-Type: application/json;charset=UTF-8
|
|
||||||
requestType: params
|
|
||||||
# 测试平台名称
|
|
||||||
allureEpic: 这里是测试平台名称
|
|
||||||
# 测试模块名称
|
|
||||||
allureFeature: 这里是测试模块名称
|
|
||||||
data:
|
|
||||||
# 请求类型:params 是以url拼接的形式请求,json则传的是json串
|
|
||||||
bid: blog-121903028
|
|
||||||
resp:
|
|
||||||
code:
|
|
||||||
jsonpath: $.status
|
|
||||||
type: ==
|
|
||||||
value: 200
|
|
||||||
AssertType:
|
|
||||||
msg:
|
|
||||||
jsonpath: $.msg
|
|
||||||
type: ==
|
|
||||||
value: 查询成功
|
|
||||||
AssertType:
|
|
||||||
|
|
||||||
sql:
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 婚奢汇
|
||||||
|
allureFeature: 文件上传
|
||||||
|
allureStory: 上传excel文件
|
||||||
|
|
||||||
|
upload_files_02:
|
||||||
|
host: {{host}}
|
||||||
|
url: /adpt/advert/mate/batchUploadMate
|
||||||
|
method: POST
|
||||||
|
detail: 测试上传文件接口
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
Authorization: work_login_ini
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: file
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run:
|
||||||
|
data:
|
||||||
|
file:
|
||||||
|
files: test.png
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
data:
|
||||||
|
uids: vc-upload-1649224175138-20
|
||||||
|
params:
|
||||||
|
test: 1
|
||||||
|
dependence_case:
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 1011006
|
||||||
|
AssertType:
|
||||||
|
sql:
|
|
@ -0,0 +1,32 @@
|
||||||
|
# 公共参数
|
||||||
|
case_common:
|
||||||
|
allureEpic: 婚奢汇
|
||||||
|
allureFeature: 文件上传
|
||||||
|
allureStory: 上传excel文件
|
||||||
|
|
||||||
|
upload_files_01:
|
||||||
|
host: http://parkyz.kkx88.cn
|
||||||
|
url: /api/biz/company/importData
|
||||||
|
method: POST
|
||||||
|
detail: 测试上传文件接口
|
||||||
|
headers:
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjA1ZTc3ZDRiLWU3NWEtNGMyNi04NjA1LTI4M2Q3ZjdlNWNmZSJ9.2htV4vh5KxR9jEDltfifiwZUPd1OYrwLRXRLM2K1AEgoY-jTCn9z1m5aLPmpIIf2dL5YoSEbyxmGT9Pm1CwzMg
|
||||||
|
# 请求的数据,是 params 还是 json、或者file
|
||||||
|
requestType: file
|
||||||
|
# 是否执行,空或者 true 都会执行
|
||||||
|
is_run:
|
||||||
|
data:
|
||||||
|
file:
|
||||||
|
file: companySewage.xlsx
|
||||||
|
# 是否有依赖业务,为空或者false则表示没有
|
||||||
|
dependence_case: False
|
||||||
|
# 依赖的数据
|
||||||
|
dependence_case_data:
|
||||||
|
assert:
|
||||||
|
code:
|
||||||
|
jsonpath: $.code
|
||||||
|
type: ==
|
||||||
|
value: 401
|
||||||
|
AssertType:
|
||||||
|
sql:
|
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 119 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 149 KiB |
Before Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 136 KiB |
Before Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 62 KiB |
BIN
images/group.png
Before Width: | Height: | Size: 716 KiB |
BIN
images/img.png
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 154 KiB |
|
@ -1,28 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Time : 2022-03-16 13:07:13
|
|
||||||
# @Author : 余少琪
|
|
||||||
|
|
||||||
|
|
||||||
from tools.requestControl import RequestControl
|
|
||||||
from tools.yamlControl import GetCaseData
|
|
||||||
from config.setting import ConfigHandler
|
|
||||||
|
|
||||||
|
|
||||||
class DateDemo(object):
|
|
||||||
@staticmethod
|
|
||||||
def dateDemo(inData):
|
|
||||||
"""
|
|
||||||
测试接口
|
|
||||||
:param inData:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
resp = RequestControl().http_request(inData['method'], inData)
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
path = GetCaseData(ConfigHandler.data_path + r'test_demo\DateDemo.yaml').get_yaml_case_data()[0]
|
|
||||||
data = DateDemo().dateDemo(path)
|
|
||||||
print(data)
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Time : 2021/11/18 23:05
|
# @Time : 2022/3/28 10:49
|
||||||
# @Author : 余少琪
|
# @Author : 余少琪
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
%(levelname)-8s2022-02-21 18:37:52,617 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\error.log:conftest.py:94 执行失败用例数:1
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,385 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\error.log:conftest.py:94 执行失败用例数:0
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
%(levelname)-8s2022-04-02 20:11:02,465 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:57 断言失败, 预期值:200, 断言类型==, 实际值1011006
|
||||||
|
%(levelname)-8s2022-04-02 22:38:57,192 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:111 JsonPath值获取失败$.code
|
||||||
|
%(levelname)-8s2022-04-02 22:39:56,756 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:111 JsonPath值获取失败$.code
|
||||||
|
%(levelname)-8s2022-04-02 22:45:55,163 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:115 JsonPath值获取失败$.code
|
||||||
|
%(levelname)-8s2022-04-02 22:46:21,310 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:115 JsonPath值获取失败$.code
|
||||||
|
%(levelname)-8s2022-04-02 23:02:12,628 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:61 断言失败, 预期值:200, 断言类型==, 实际值1011006
|
||||||
|
%(levelname)-8s2022-04-02 23:45:41,734 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:61 断言失败, 预期值:200, 断言类型==, 实际值1011006
|
||||||
|
%(levelname)-8s2022-04-02 23:59:33,188 C:\work\Study\pytest-auto-api3\logs\error.log:assertControl.py:61 断言失败, 预期值:200, 断言类型==, 实际值1011006
|
|
@ -1,45 +0,0 @@
|
||||||
%(levelname)-8s2022-02-21 18:37:50,684 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:run.py:19
|
|
||||||
_ _ _ _____ _
|
|
||||||
__ _ _ __ (_) / \ _ _| |_ __|_ _|__ ___| |_
|
|
||||||
/ _` | '_ \| | / _ \| | | | __/ _ \| |/ _ \/ __| __|
|
|
||||||
| (_| | |_) | |/ ___ \ |_| | || (_) | | __/\__ \ |_
|
|
||||||
\__,_| .__/|_/_/ \_\__,_|\__\___/|_|\___||___/\__|
|
|
||||||
|_|
|
|
||||||
开始执行余少琪的框架项目...
|
|
||||||
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,389 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:logDecorator.py:25
|
|
||||||
=================================================================================
|
|
||||||
测试标题: 测试接口
|
|
||||||
请求方式: POST
|
|
||||||
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
|
||||||
请求路径: https://redisdatarecall.csdn.net/recommend/get_head_word
|
|
||||||
请求参数类型: params
|
|
||||||
请求内容: {'bid': 'blog-121903028'}
|
|
||||||
接口响应内容: {'status': 200, 'msg': '查询成功', 'content': ['自动化测试', 'yaml', 'pytest', 'gitee', 'jenkins'], 'error': False}
|
|
||||||
数据库断言数据: {'sql': None}
|
|
||||||
=================================================================================
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,391 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:assertControl.py:61 断言成功, 预期值:200, 断言类型==, 实际值200
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,391 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:assertControl.py:61 断言成功, 预期值:查询成功, 断言类型==, 实际值查询成功
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,617 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:91 执行用例总数: 1
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,617 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:92 执行通过用例数:0
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,620 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:96 执行异常用例数:0
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,620 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:98 执行跳过用例数:0
|
|
||||||
%(levelname)-8s2022-02-21 18:37:52,621 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:100 执行成功率: 成功率:0.00%
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,375 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:logDecorator.py:25
|
|
||||||
=================================================================================
|
|
||||||
测试标题: 测试接口
|
|
||||||
请求方式: POST
|
|
||||||
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
|
||||||
请求路径: https://redisdatarecall.csdn.net/recommend/get_head_word
|
|
||||||
请求参数类型: params
|
|
||||||
请求内容: {'bid': 'blog-121903028'}
|
|
||||||
接口响应内容: {'status': 200, 'msg': '查询成功', 'content': ['自动化测试', 'yaml', 'pytest', 'gitee', 'jenkins'], 'error': False}
|
|
||||||
数据库断言数据: {'sql': None}
|
|
||||||
=================================================================================
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,377 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:assertControl.py:61 断言成功, 预期值:200, 断言类型==, 实际值200
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,378 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:assertControl.py:61 断言成功, 预期值:查询成功, 断言类型==, 实际值查询成功
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,384 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:91 执行用例总数: 1
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,384 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:92 执行通过用例数:1
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,385 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:96 执行异常用例数:0
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,386 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:98 执行跳过用例数:0
|
|
||||||
%(levelname)-8s2022-02-21 18:38:30,386 C:\Users\hzxy\PycharmProjects\py_auto_demo\logs\info.log:conftest.py:100 执行成功率: 成功率:100.00%
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
%(levelname)-8s2022-04-02 22:48:54,293 C:\work\Study\pytest-auto-api3\logs\warning.log:assertControl.py:118 该用例当前不执行,跳过断言判断
|
||||||
|
%(levelname)-8s2022-04-02 22:56:48,119 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '753263e5f81e3b40436d8b7ceffcdf791c5c'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: {'res': False}
|
||||||
|
数据库断言数据: {'sql': False}
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 22:57:31,857 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532109233fa72ad486c97e471d6ff2d6204'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: {'res': False}
|
||||||
|
数据库断言数据: {'sql': False}
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 22:59:47,978 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:00:16,779 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 正常登录
|
||||||
|
请求方式: POST
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/user/loginByPassword
|
||||||
|
请求内容: {'param': {'phone': '13300000000', 'password': '123456'}}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:01:45,748 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 正常登录
|
||||||
|
请求方式: POST
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/user/loginByPassword
|
||||||
|
请求内容: {'param': {'phone': '13300000000', 'password': '123456'}}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:01:45,748 C:\work\Study\pytest-auto-api3\logs\warning.log:conftest.py:61 登录用例设置的是不执行,无法获取到token信息
|
||||||
|
%(levelname)-8s2022-04-02 23:01:46,083 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:02:12,204 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 正常登录
|
||||||
|
请求方式: POST
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/user/loginByPassword
|
||||||
|
请求内容: {'param': {'phone': '13300000000', 'password': '123456'}}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:02:12,205 C:\work\Study\pytest-auto-api3\logs\warning.log:conftest.py:61 登录用例设置的是不执行,无法获取到token信息
|
||||||
|
%(levelname)-8s2022-04-02 23:02:12,817 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:02:12,840 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:02:12,847 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:45:41,234 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 正常登录
|
||||||
|
请求方式: POST
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/user/loginByPassword
|
||||||
|
请求内容: {'param': {'phone': '13300000000', 'password': '123456'}}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:45:41,235 C:\work\Study\pytest-auto-api3\logs\warning.log:conftest.py:61 登录用例设置的是不执行,无法获取到token信息
|
||||||
|
%(levelname)-8s2022-04-02 23:45:41,626 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:45:41,645 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:45:41,970 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:59:32,711 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 正常登录
|
||||||
|
请求方式: POST
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/user/loginByPassword
|
||||||
|
请求内容: {'param': {'phone': '13300000000', 'password': '123456'}}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:59:32,711 C:\work\Study\pytest-auto-api3\logs\warning.log:conftest.py:61 登录用例设置的是不执行,无法获取到token信息
|
||||||
|
%(levelname)-8s2022-04-02 23:59:32,711 C:\work\Study\pytest-auto-api3\logs\warning.log:conftest.py:61 登录用例设置的是不执行,无法获取到token信息
|
||||||
|
%(levelname)-8s2022-04-02 23:59:32,714 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 正常登录
|
||||||
|
请求方式: POST
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/user/loginByPassword
|
||||||
|
请求内容: {'param': {'phone': '13300000000', 'password': '123456'}}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:59:32,715 C:\work\Study\pytest-auto-api3\logs\warning.log:conftest.py:61 登录用例设置的是不执行,无法获取到token信息
|
||||||
|
%(levelname)-8s2022-04-02 23:59:33,111 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:59:33,116 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-02 23:59:33,410 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 查看商品审核列表
|
||||||
|
请求方式: GET
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'token': '7532b925b258a4c54a7a97e24f668727d0d5'}
|
||||||
|
请求路径: http://work.test.feng-go.com/api/v1/work/spu/approval/spuList
|
||||||
|
请求内容: {'spuType': 1, 'pageNum': 1, 'pageSize': 10}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
||||||
|
%(levelname)-8s2022-04-03 00:00:28,088 C:\work\Study\pytest-auto-api3\logs\warning.log:logDecoratorl.py:51
|
||||||
|
=================================================================================
|
||||||
|
该条用例跳过执行.
|
||||||
|
测试标题: 测试patch请求方式
|
||||||
|
请求方式: PATCH
|
||||||
|
请求头: {'Content-Type': 'application/json;charset=UTF-8', 'Authorization': 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjEyNjU0NzY4OTA2NzI2NzI4MDgsImFjY291bnQiOiJzdXBlckFkbWluIiwidXVpZCI6IjJiOTNlNTNjLWRkM2QtNGM0MS05YjI2LTA1Y2NhM2JjMjNlOSIsInN1YiI6IjEyNjU0NzY4OTA2NzI2NzI4MDgiLCJpYXQiOjE2NDg2ODg2NTgsImV4cCI6MTY0ODc3NTA1OH0.640mDK2Eyid_KjSi0Ijei6VW6LYQZ7oYfGCgq4ajqehACzqfvaG4XJ5lqizRSVhidl7J1XTJZeBYVCjEe0GMdw'}
|
||||||
|
请求路径: http://39.105.186.77:8082/adpt/advert/adplan/batchDisable
|
||||||
|
请求内容: {'ids': ['1509343309343780875']}
|
||||||
|
依赖测试用例: 暂无依赖用例数据
|
||||||
|
接口响应内容: False
|
||||||
|
数据库断言数据: False
|
||||||
|
=================================================================================
|
|
@ -1,4 +1,9 @@
|
||||||
[pytest]
|
[pytest]
|
||||||
|
addopts = -p no:warnings
|
||||||
|
testpaths = test_case/
|
||||||
|
python_files = test_*.py
|
||||||
|
python_classes = Test*
|
||||||
|
python_function = test_*
|
||||||
|
|
||||||
markers =
|
markers =
|
||||||
shop: project_shop
|
smoke: 冒烟测试
|
||||||
shop_list: project_shop_list
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
<environment>
|
|
||||||
<parameter>
|
|
||||||
<key>测试平台</key>
|
|
||||||
<value>测试项目</value>
|
|
||||||
</parameter>
|
|
||||||
<parameter>
|
|
||||||
<key>测试环境</key>
|
|
||||||
<value>TEST</value>
|
|
||||||
</parameter>
|
|
||||||
<parameter>
|
|
||||||
<key>测试人员</key>
|
|
||||||
<value>余少琪</value>
|
|
||||||
</parameter>
|
|
||||||
<parameter>
|
|
||||||
<key>邮箱</key>
|
|
||||||
<value>1603453211@qq.com</value>
|
|
||||||
</parameter>
|
|
||||||
<parameter>
|
|
||||||
<key>python.Version</key>
|
|
||||||
<value>3.9.0</value>
|
|
||||||
</parameter>
|
|
||||||
</environment>
|
|
52
run.py
|
@ -1,23 +1,23 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Time : 2021/11/26 23:12
|
# @Time : 2022/3/29 15:01
|
||||||
# @Author : 余少琪
|
# @Author : 余少琪
|
||||||
import traceback
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
import os
|
import os
|
||||||
from tools.logControl import INFO
|
import traceback
|
||||||
from tools.yamlControl import GetYamlData
|
import pytest
|
||||||
from config.setting import ConfigHandler
|
from utils import project_name
|
||||||
from tools import getNotificationType
|
from utils.logUtils.logControl import INFO
|
||||||
from tools.weChatSendControl import WeChatSend
|
from utils import get_notification_type
|
||||||
from tools.dingtalkControl import DingTalkSendMsg
|
from utils.noticUtils.weChatSendControl import WeChatSend
|
||||||
from tools.sendmailControl import SendEmail
|
from utils.noticUtils.dingtalkControl import DingTalkSendMsg
|
||||||
|
from utils.noticUtils.sendmailControl import SendEmail
|
||||||
|
from Enums.notificationType_enum import NotificationType
|
||||||
|
from utils.noticUtils.feishuControl import FeiShuTalkChatBot
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
# 从配置文件中获取项目名称
|
# 从配置文件中获取项目名称
|
||||||
project_name = GetYamlData(ConfigHandler.config_path).get_yaml_data()['ProjectName'][0]
|
|
||||||
try:
|
try:
|
||||||
INFO.logger.info(
|
INFO.logger.info(
|
||||||
"""
|
"""
|
||||||
|
@ -30,15 +30,33 @@ def run():
|
||||||
开始执行{}项目...
|
开始执行{}项目...
|
||||||
""".format(project_name)
|
""".format(project_name)
|
||||||
)
|
)
|
||||||
pytest.main(['-s', '-W', 'ignore:Module already imported:pytest.PytestWarning', '--alluredir', './report/tmp'])
|
|
||||||
|
pytest.main(['-s', '-W', 'ignore:Module already imported:pytest.PytestWarning',
|
||||||
|
'--alluredir', './report/tmp'])
|
||||||
|
"""
|
||||||
|
--reruns: 失败重跑次数
|
||||||
|
--count: 重复执行次数
|
||||||
|
-v: 显示错误位置以及错误的详细信息
|
||||||
|
-s: 等价于 pytest --capture=no 可以捕获print函数的输出
|
||||||
|
-q: 简化输出信息
|
||||||
|
-m: 运行指定标签的测试用例
|
||||||
|
-x: 一旦错误,则停止运行
|
||||||
|
--maxfail: 设置最大失败次数,当超出这个阈值时,则不会在执行测试用例
|
||||||
|
"--reruns=3", "--reruns-delay=2"
|
||||||
|
"""
|
||||||
|
|
||||||
os.system(r"allure generate ./report/tmp -o ./report/html --clean")
|
os.system(r"allure generate ./report/tmp -o ./report/html --clean")
|
||||||
# 通过配置文件判断发送报告通知类型:1:钉钉 2:企业微信通知 3、邮箱
|
# 判断通知类型
|
||||||
if getNotificationType() == 1:
|
if get_notification_type() == NotificationType.DEFAULT.value:
|
||||||
|
pass
|
||||||
|
elif get_notification_type() == NotificationType.DING_TALK.value:
|
||||||
DingTalkSendMsg().send_ding_notification()
|
DingTalkSendMsg().send_ding_notification()
|
||||||
elif getNotificationType() == 2:
|
elif get_notification_type() == NotificationType.WECHAT.value:
|
||||||
WeChatSend().send_email_notification()
|
WeChatSend().send_wechat_notification()
|
||||||
elif getNotificationType() == 3:
|
elif get_notification_type() == NotificationType.EMAIL.value:
|
||||||
SendEmail().send_main()
|
SendEmail().send_main()
|
||||||
|
elif get_notification_type() == NotificationType.FEI_SHU.value:
|
||||||
|
FeiShuTalkChatBot().post()
|
||||||
else:
|
else:
|
||||||
raise ValueError("通知类型配置错误,暂不支持该类型通知")
|
raise ValueError("通知类型配置错误,暂不支持该类型通知")
|
||||||
os.system(f"allure serve ./report/tmp -p 9999")
|
os.system(f"allure serve ./report/tmp -p 9999")
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'Login/login.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("电商平台端")
|
||||||
|
@allure.feature("登录模块")
|
||||||
|
class TestLogin:
|
||||||
|
|
||||||
|
@allure.story("正常登录")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_login(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_login.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'uplpad_file_test/batchDisable.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("换社会")
|
||||||
|
@allure.feature("登录模块")
|
||||||
|
class TestBatchdisable:
|
||||||
|
|
||||||
|
@allure.story("测试patch请求方式")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_batchDisable(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_batchDisable.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'WorkApplyCenter/spu_apply.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("电商平台端")
|
||||||
|
@allure.feature("审核中心")
|
||||||
|
class TestSpuApply:
|
||||||
|
|
||||||
|
@allure.story("商品审核")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_spu_apply(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_spu_apply.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'WorkApplyCenter/sup_apply_list.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("电商平台端")
|
||||||
|
@allure.feature("审核中心")
|
||||||
|
class TestSupApplyList:
|
||||||
|
|
||||||
|
@allure.story("商品审核列表")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_sup_apply_list(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_sup_apply_list.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'WorkApplyCenter/work_apply_good_detail.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("电商平台端")
|
||||||
|
@allure.feature("审核中心")
|
||||||
|
class TestWorkApplyGoodDetail:
|
||||||
|
|
||||||
|
@allure.story("商品审核详情")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_work_apply_good_detail(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_work_apply_good_detail.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -1,21 +1,26 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Time : 2021/11/28 23:05
|
# @Time : 2022/3/30 14:12
|
||||||
# @Author : 余少琪
|
# @Author : 余少琪
|
||||||
import pytest
|
|
||||||
import os
|
import os
|
||||||
|
import pytest
|
||||||
|
import time
|
||||||
|
import allure
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
from config.setting import ConfigHandler
|
from config.setting import ConfigHandler
|
||||||
from tools.yamlControl import GetYamlData
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.cacheUtils.cacheControl import Cache
|
||||||
|
from utils.readFilesUtils.get_all_files_path import get_all_files
|
||||||
_PROJECT_NAME = GetYamlData(ConfigHandler.config_path).get_yaml_data()['ProjectName'][0]
|
from utils.logUtils.logControl import WARNING, INFO, ERROR
|
||||||
_TEST_NAME = GetYamlData(ConfigHandler.config_path).get_yaml_data()['TestName']
|
from Enums.yamlData_enum import YAMLDate
|
||||||
|
from utils.otherUtils.allureDate.allure_tools import allure_step, allure_step_no
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session", autouse=True)
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
def clear_report():
|
def clear_report():
|
||||||
try:
|
try:
|
||||||
for one in os.listdir(ConfigHandler.report_path + f'/tmp'):
|
for one in os.listdir(ConfigHandler.report_path + '/tmp'):
|
||||||
if 'json' in one:
|
if 'json' in one:
|
||||||
os.remove(ConfigHandler.report_path + f'/tmp/{one}')
|
os.remove(ConfigHandler.report_path + f'/tmp/{one}')
|
||||||
if 'txt' in one:
|
if 'txt' in one:
|
||||||
|
@ -26,3 +31,101 @@ def clear_report():
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def write_case_process():
|
||||||
|
"""
|
||||||
|
获取所有用例,写入用例池中
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
case_data = {}
|
||||||
|
# 循环拿到所有存放用例的文件路径
|
||||||
|
for i in get_all_files(ConfigHandler.data_path):
|
||||||
|
# 循环读取文件中的数据
|
||||||
|
case_process = CaseData(i).case_process(case_id_switch=True)
|
||||||
|
# 转换数据类型
|
||||||
|
for case in case_process:
|
||||||
|
for k, v in case.items():
|
||||||
|
# 判断 case_id 是否已存在
|
||||||
|
case_id_exit = k in case_data.keys()
|
||||||
|
# 如果case_id 不存在,则将用例写入缓存池中
|
||||||
|
if case_id_exit is False:
|
||||||
|
case_data[k] = v
|
||||||
|
# 当 case_id 为 True 存在时,则跑出异常
|
||||||
|
elif case_id_exit is True:
|
||||||
|
raise ValueError(f"case_id: {k} 存在重复项, 请修改case_id\n"
|
||||||
|
f"文件路径: {i}")
|
||||||
|
|
||||||
|
Cache('case_process').set_caches(case_data)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def work_login_init():
|
||||||
|
"""
|
||||||
|
获取平台端的token信息
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
login_yaml = CaseData(ConfigHandler.data_path + 'Login/login.yaml').case_process()[0]
|
||||||
|
res = RequestControl().http_request(login_yaml)
|
||||||
|
# 将token写入缓存中
|
||||||
|
if res[0] is not False:
|
||||||
|
token = res[0]['data']['token']
|
||||||
|
Cache('work_login_init').set_caches(token)
|
||||||
|
return token
|
||||||
|
else:
|
||||||
|
WARNING.logger.warning("登录用例设置的是不执行,无法获取到token信息")
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_collection_modifyitems(items):
|
||||||
|
"""
|
||||||
|
测试用例收集完成时,将收集到的 item 的 name 和 node_id 的中文显示在控制台上
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for item in items:
|
||||||
|
item.name = item.name.encode("utf-8").decode("unicode_escape")
|
||||||
|
item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")
|
||||||
|
|
||||||
|
|
||||||
|
# 定义单个标签
|
||||||
|
def pytest_configure(config):
|
||||||
|
config.addinivalue_line(
|
||||||
|
"markers", "smoke"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
|
def case_skip(in_data):
|
||||||
|
"""处理跳过用例"""
|
||||||
|
if in_data['is_run'] is False:
|
||||||
|
allure.dynamic.title(in_data[YAMLDate.DETAIL.value])
|
||||||
|
allure_step_no(f"请求URL: {in_data[YAMLDate.IS_RUN.value]}")
|
||||||
|
allure_step_no(f"请求方式: {in_data[YAMLDate.METHOD.value]}")
|
||||||
|
allure_step("请求头: ", in_data[YAMLDate.HEADER.value])
|
||||||
|
allure_step("请求数据: ", in_data[YAMLDate.DATA.value])
|
||||||
|
allure_step("依赖数据: ", in_data[YAMLDate.DEPENDENCE_CASE_DATA.value])
|
||||||
|
allure_step("预期数据: ", in_data[YAMLDate.ASSERT.value])
|
||||||
|
pytest.skip()
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_terminal_summary(terminalreporter):
|
||||||
|
"""
|
||||||
|
收集测试结果
|
||||||
|
"""
|
||||||
|
|
||||||
|
_PASSED = len([i for i in terminalreporter.stats.get('passed', []) if i.when != 'teardown'])
|
||||||
|
_ERROR = len([i for i in terminalreporter.stats.get('error', []) if i.when != 'teardown'])
|
||||||
|
_FAILED = len([i for i in terminalreporter.stats.get('failed', []) if i.when != 'teardown'])
|
||||||
|
_SKIPPED = len([i for i in terminalreporter.stats.get('skipped', []) if i.when != 'teardown'])
|
||||||
|
_TOTAL = terminalreporter._numcollected
|
||||||
|
_TIMES = time.time() - terminalreporter._sessionstarttime
|
||||||
|
|
||||||
|
INFO.logger.info(f"成功用例数: {_PASSED}")
|
||||||
|
ERROR.logger.error(f"异常用例数: {_ERROR}")
|
||||||
|
ERROR.logger.error(f"失败用例数: {_FAILED}")
|
||||||
|
WARNING.logger.warning(f"跳过用例数: {_SKIPPED}")
|
||||||
|
INFO.logger.info("用例执行时长: %.2f" % _TIMES + " s")
|
||||||
|
|
||||||
|
try:
|
||||||
|
_RATE = round((_PASSED + _SKIPPED) / _TOTAL * 100, 2)
|
||||||
|
INFO.logger.info("用例成功率: %.2f" % _RATE + " %")
|
||||||
|
except ZeroDivisionError:
|
||||||
|
INFO.logger.info("用例成功率: 0.00 %")
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Time : 2022-03-16 13:07:13
|
|
||||||
# @Author : 余少琪
|
|
||||||
|
|
||||||
|
|
||||||
import allure
|
|
||||||
import pytest
|
|
||||||
from config.setting import ConfigHandler
|
|
||||||
from tools.yamlControl import GetCaseData
|
|
||||||
from lib.test_demo.DateDemo import DateDemo
|
|
||||||
from tools.assertControl import Assert
|
|
||||||
|
|
||||||
TestData = GetCaseData(ConfigHandler.merchant_data_path + r'test_demo\DateDemo.yaml').get_yaml_case_data()
|
|
||||||
|
|
||||||
|
|
||||||
@allure.epic("这里是测试平台名称")
|
|
||||||
@allure.feature("这里是测试模块名称")
|
|
||||||
class TestDateDemo:
|
|
||||||
|
|
||||||
@allure.story("这是一个测试的demo接口")
|
|
||||||
@pytest.mark.parametrize('data', TestData)
|
|
||||||
def test_date_demo(self, date):
|
|
||||||
"""
|
|
||||||
测试接口
|
|
||||||
:param :
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
res = DateDemo().dateDemo(date)
|
|
||||||
Assert(date['resp']).assert_equality(response_data=res[0], sql_data=res[1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
pytest.main(['test_DateDemo.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning', "--reruns=2",
|
|
||||||
"--reruns-delay=2"])
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'uplpad_file_test/up_files.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("婚奢汇")
|
||||||
|
@allure.feature("文件上传")
|
||||||
|
class TestUpFiles:
|
||||||
|
|
||||||
|
@allure.story("上传excel文件")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_up_files(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_up_files.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2022-04-07 21:03:43
|
||||||
|
# @Author : 余少琪
|
||||||
|
|
||||||
|
|
||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
from config.setting import ConfigHandler
|
||||||
|
from utils.readFilesUtils.get_yaml_data_analysis import CaseData
|
||||||
|
from utils.assertUtils.assertControl import Assert
|
||||||
|
from utils.requestsUtils.requestControl import RequestControl
|
||||||
|
|
||||||
|
|
||||||
|
TestData = CaseData(ConfigHandler.data_path + r'uplpad_file_test/upload_files.yaml').case_process()
|
||||||
|
|
||||||
|
|
||||||
|
@allure.epic("婚奢汇")
|
||||||
|
@allure.feature("文件上传")
|
||||||
|
class TestUploadFiles:
|
||||||
|
|
||||||
|
@allure.story("上传excel文件")
|
||||||
|
@pytest.mark.parametrize('in_data', TestData, ids=[i['detail'] for i in TestData])
|
||||||
|
def test_upload_files(self, in_data, case_skip):
|
||||||
|
"""
|
||||||
|
:param :
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = RequestControl().http_request(in_data)
|
||||||
|
Assert(in_data['assert']).assert_equality(response_data=res[0], sql_data=res[1])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['test_upload_files.py', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning'])
|
|
@ -1,159 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Time : 2021/12/14 22:06
|
|
||||||
# @Author : 余少琪
|
|
||||||
|
|
||||||
import allure
|
|
||||||
import json
|
|
||||||
import datetime
|
|
||||||
from config.setting import get_current_system, ConfigHandler
|
|
||||||
from tools.yamlControl import GetYamlData
|
|
||||||
|
|
||||||
|
|
||||||
def allure_step(step: str, var: str) -> None:
|
|
||||||
"""
|
|
||||||
:param step: 步骤及附件名称
|
|
||||||
:param var: 附件内容
|
|
||||||
"""
|
|
||||||
with allure.step(step):
|
|
||||||
allure.attach(
|
|
||||||
json.dumps(
|
|
||||||
str(var),
|
|
||||||
ensure_ascii=False,
|
|
||||||
indent=4),
|
|
||||||
step,
|
|
||||||
allure.attachment_type.JSON)
|
|
||||||
|
|
||||||
|
|
||||||
def allure_step_no(step: str):
|
|
||||||
"""
|
|
||||||
无附件的操作步骤
|
|
||||||
:param step: 步骤名称
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
with allure.step(step):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def slash():
|
|
||||||
# 判断系统路径
|
|
||||||
SLASH = '\\'
|
|
||||||
|
|
||||||
# 判断当前操作系统
|
|
||||||
if get_current_system() == 'Linux' or get_current_system() == "Darwin":
|
|
||||||
SLASH = '/'
|
|
||||||
|
|
||||||
return SLASH
|
|
||||||
|
|
||||||
|
|
||||||
def SqlSwitch() -> bool:
|
|
||||||
"""获取数据库开关"""
|
|
||||||
switch = GetYamlData(ConfigHandler.config_path) \
|
|
||||||
.get_yaml_data()['MySqlDB']["switch"]
|
|
||||||
return switch
|
|
||||||
|
|
||||||
|
|
||||||
def getNotificationType():
|
|
||||||
# 获取报告通知类型,是发送钉钉还是企业邮箱
|
|
||||||
Date = GetYamlData(ConfigHandler.config_path).get_yaml_data()['NotificationType']
|
|
||||||
return Date
|
|
||||||
|
|
||||||
|
|
||||||
def writePageFiles(classTitle, funcTitle, caseDetail, casePath, yamlPath):
|
|
||||||
"""
|
|
||||||
自动写成 py 文件
|
|
||||||
:param yamlPath:
|
|
||||||
:param casePath: 生成的py文件地址
|
|
||||||
:param classTitle: 类名称, 读取用例中的 caseTitle 作为类名称
|
|
||||||
:param funcTitle: 函数名称 caseTitle,首字母小写
|
|
||||||
:param caseDetail: 函数描述,读取用例中的描述内容,做为函数描述
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
Author = GetYamlData(ConfigHandler.config_path).get_yaml_data()['TestName']
|
|
||||||
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
page = f'''#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Time : {now}
|
|
||||||
# @Author : {Author}
|
|
||||||
|
|
||||||
|
|
||||||
from tools.requestControl import RequestControl
|
|
||||||
from tools.yamlControl import GetCaseData
|
|
||||||
from config.setting import ConfigHandler
|
|
||||||
|
|
||||||
|
|
||||||
class {classTitle}(object):
|
|
||||||
@staticmethod
|
|
||||||
def {funcTitle}(inData):
|
|
||||||
"""
|
|
||||||
{caseDetail}
|
|
||||||
:param inData:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
resp = RequestControl().HttpRequest(inData['method'], inData)
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
path = GetCaseData(ConfigHandler.data_path + r'{yamlPath}').get_yaml_case_data()[0]
|
|
||||||
data = {classTitle}().{funcTitle}(path)
|
|
||||||
print(data)
|
|
||||||
'''
|
|
||||||
with open(casePath, 'w', encoding="utf-8") as f:
|
|
||||||
f.write(page)
|
|
||||||
|
|
||||||
|
|
||||||
def writeTestCaseFile(allureEpic, allureFeature, classTitle, funcTitle, caseDetail, casePath, yamlPath, fileName, PackagePath):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:param allureEpic: 项目名称
|
|
||||||
:param allureFeature: 模块名称
|
|
||||||
:param classTitle: 类名称
|
|
||||||
:param funcTitle: 函数名称
|
|
||||||
:param caseDetail: 用例描述
|
|
||||||
:param casePath: case 路径
|
|
||||||
:param yamlPath: yaml 文件路径
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
Author = GetYamlData(ConfigHandler.config_path).get_yaml_data()['TestName']
|
|
||||||
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
page = f'''#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Time : {now}
|
|
||||||
# @Author : {Author}
|
|
||||||
|
|
||||||
|
|
||||||
import allure
|
|
||||||
import pytest
|
|
||||||
from config.setting import ConfigHandler
|
|
||||||
from tools.yamlControl import GetCaseData
|
|
||||||
{PackagePath}
|
|
||||||
from tools.assertControl import Assert
|
|
||||||
|
|
||||||
TestData = GetCaseData(ConfigHandler.merchant_data_path + r'{yamlPath}').get_yaml_case_data()
|
|
||||||
|
|
||||||
|
|
||||||
@allure.epic("{allureEpic}")
|
|
||||||
@allure.feature("{allureFeature}")
|
|
||||||
class Test{classTitle}:
|
|
||||||
|
|
||||||
@allure.story("这是一个测试的demo接口")
|
|
||||||
@pytest.mark.parametrize('inData', TestData)
|
|
||||||
def test_{funcTitle}(self, inData):
|
|
||||||
"""
|
|
||||||
{caseDetail}
|
|
||||||
:param :
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
res = {classTitle}().{funcTitle}(inData)
|
|
||||||
Assert(inData['resp']).assertEquality(responseData=res[0], sqlData=res[1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
pytest.main(['{fileName}', '-s', '-W', 'ignore:Module already imported:pytest.PytestWarning', "--reruns=2", "--reruns-delay=2"])
|
|
||||||
'''
|
|
||||||
with open(casePath, 'w', encoding="utf-8") as f:
|
|
||||||
f.write(page)
|
|