实现通过用例数据动态配置pytest.mark, 包括自定义标记,pytest.mark.skip以及pytest,mark.usefixtues功能
This commit is contained in:
65
README.md
65
README.md
@@ -28,6 +28,7 @@
|
||||
* 动态多断言: 如接口需要同时校验响应数据和sql校验,支持多场景断言
|
||||
* 框架天然支持接口动态传参、关联灵活处理
|
||||
* 支持测试数据分析,测试数据不符合规范有预警机制
|
||||
* 支持通过用例数据动态配置pytest.mark, 包括自定义标记,pytest.mark.skip以及pytest,mark.usefixtues
|
||||
* 测试数据隔离, 实现数据驱动
|
||||
* 自动生成用例代码: 测试人员在yaml/excel文件中填写好测试用例, 程序可以直接生成用例代码,纯小白也能使用
|
||||
* 多种报告随心选择:框架支持pytest-html以及Allure测试报告,可以动态配置所需报告
|
||||
@@ -183,6 +184,8 @@ case_common :公共参数
|
||||
allure_epic:用作于@allure.epic()装饰器中的内容。
|
||||
allure_feature:用作于@allure.feature()装饰器中的内容。
|
||||
allure_story:用作于@allure.story()装饰器中的内容。
|
||||
case_markers: 给测试方法添加标记,支持自定义标记,skip, usefixtures。 格式是列表嵌套字符串或者字典。例如:['glcc', {'skip': '跳过执行该用例'}]
|
||||
|
||||
case_001:用例ID
|
||||
feature:用例所属模块, 类似于@allure.feature()。
|
||||
title:用例标题
|
||||
@@ -193,7 +196,7 @@ case_001:用例ID
|
||||
cookies:请求cookies,格式是:DICT, CookieJar对象
|
||||
request_type:请求数据类型:params, json, file, data
|
||||
payload:请求参数
|
||||
files: 需要上传的文件,参考如下传参:{接口中文件参数的名称:”文件路径地址”/[“文件地址1”, “文件地址2”]}
|
||||
files: 需要上传的文件,参考如下传参:{接口中文件参数的名称:'文件路径地址'/['文件地址1', '文件地址2']}
|
||||
extract:后置提取参数
|
||||
assert_response:响应断言
|
||||
assert_sql:数据库断言
|
||||
@@ -251,42 +254,46 @@ excel表单2名称是:示例模块
|
||||
|
||||
|
||||
## 九 、详细功能说明
|
||||
- [如何实现动态数据、随机数据的热加载?](https://www.gitlink.org.cn/zone/tester/newdetail/204)
|
||||
- [如何实现动态数据、随机数据的热加载?](https://www.gitlink.org.cn/zone/tester/newdetail/236)
|
||||
我们有些特殊的场景,可能会涉及到一些定制化的数据,每次执行数据,需要按照指定规则随机生成,实时加载数据,那么这部分应该如何处理呢?
|
||||
|
||||
- [如何提取响应数据作为全局变量并使用?](https://www.gitlink.org.cn/zone/tester/newdetail/205)
|
||||
在测试过程中,通常下一个接口需要用到上一个接口的响应数据,这个时候就涉及到参数的提取。
|
||||
|
||||
- [如何进行响应数据断言?](https://www.gitlink.org.cn/zone/tester/newdetail/206)
|
||||
持5种响应断言方式:eq, in, gt, lt, not。
|
||||
|
||||
- [如何进行数据库断言?](https://www.gitlink.org.cn/zone/tester/newdetail/207)
|
||||
目前暂时支持两种数据库断言方式:len, eq。其他方式待扩展。
|
||||
|
||||
- [如何配置邮箱通知?](https://www.gitlink.org.cn/zone/tester/newdetail/208)
|
||||
我们通过第三方模块yagmail发送邮件。
|
||||
|
||||
- [如何配置钉钉通知?](https://www.gitlink.org.cn/zone/tester/newdetail/209)
|
||||
我们通过封装钉钉机器人发送钉钉通知。
|
||||
|
||||
- [如何配置企业微信通知?](https://www.gitlink.org.cn/zone/tester/newdetail/210)
|
||||
过封装企业微信机器人发送通知。
|
||||
|
||||
- [如何测试上传文件接口?](https://www.gitlink.org.cn/zone/tester/newdetail/211)
|
||||
我们通过MultipartEncoder的方式进行文件上传。
|
||||
|
||||
- [如何处理同一环境存在多域名的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/214)
|
||||
|
||||
- [如何处理同一环境存在多域名的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/234)
|
||||
很多公司,通常一套环境是由多个微服务组成。每一个微服务具备不同的域名。那么针对这种同一环境存在多域名的情况,我们应该如何处理呢?
|
||||
|
||||
- [如何处理同一套框架测试多套环境的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/215)
|
||||
- [如何处理同一套框架测试多套环境的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/233)
|
||||
假如我想要我的自动化代码分别在不同环境执行,如何处理呢?
|
||||
|
||||
- [如何处理用例中需要依赖登录的token/cookies的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/228)
|
||||
- [如何处理用例中需要依赖登录的token/cookies的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/235)
|
||||
我们进行测试的时候,很多接口都是需要先登录之后再进行操作。但是我们不可能每测试一次接口,都登录一次吧,这样有点冗余了。那么,针对这种情况如何处理呢?
|
||||
|
||||
- [如何测试上传文件接口?](https://www.gitlink.org.cn/zone/tester/newdetail/238)
|
||||
我们通过MultipartEncoder的方式进行文件上传。
|
||||
|
||||
- [如何通过用例数据动态配置pytest.mark](https://www.gitlink.org.cn/zone/tester/newdetail/257)
|
||||
在测试过程中,我们经常需要对测试用例进行分类,运行时仅执行这一类用例。为了实现这一功能,我在测试用例中引入了添加pytest的自定义标记的功能,同时扩展支持了pytest.mark.skip以及pytest,mark.usefixtues。
|
||||
注意:目前这一功能,仅支持通过YAML格式编写用例。EXCEL用例暂时不支持。
|
||||
|
||||
- [如何提取响应数据作为全局变量并使用?](https://www.gitlink.org.cn/zone/tester/newdetail/237)
|
||||
在测试过程中,通常下一个接口需要用到上一个接口的响应数据,这个时候就涉及到参数的提取。
|
||||
|
||||
- [如何进行响应数据断言?](https://www.gitlink.org.cn/zone/tester/newdetail/239)
|
||||
目前支持5种响应断言方式:eq, in, gt, lt, not。
|
||||
|
||||
- [如何进行数据库断言?](https://www.gitlink.org.cn/zone/tester/newdetail/240)
|
||||
目前暂时支持两种数据库断言方式:len, eq。其他方式待扩展。
|
||||
|
||||
- [如何配置邮箱通知?](https://www.gitlink.org.cn/zone/tester/newdetail/242)
|
||||
我们通过第三方模块yagmail发送邮件。
|
||||
|
||||
- [如何配置钉钉通知?](https://www.gitlink.org.cn/zone/tester/newdetail/243)
|
||||
我们通过封装钉钉机器人发送钉钉通知。
|
||||
|
||||
- [如何配置企业微信通知?](https://www.gitlink.org.cn/zone/tester/newdetail/241)
|
||||
我们通过封装企业微信机器人发送通知。
|
||||
|
||||
|
||||
|
||||
## 十、初始化项目可能遇到的问题
|
||||
- [测试机安装的是python3.7,但是本框架要求3.9.5,怎么办?](https://www.gitlink.org.cn/zone/tester/newdetail/212)
|
||||
- [无法安装依赖包或者安装很慢,怎么办?](https://www.gitlink.org.cn/zone/tester/newdetail/213)
|
||||
- [测试机安装的是python3.7,但是本框架要求3.9.5,怎么办?](https://www.gitlink.org.cn/zone/tester/newdetail/245)
|
||||
- [无法安装依赖包或者安装很慢,怎么办?](https://www.gitlink.org.cn/zone/tester/newdetail/244)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import os
|
||||
from string import Template
|
||||
import datetime
|
||||
import re
|
||||
# 第三方库导入
|
||||
from xpinyin import Pinyin # 纯 Python 编写的中文字符串拼音转换模块,不需要依赖外部程序和词库。
|
||||
from loguru import logger
|
||||
@@ -18,6 +19,7 @@ from common_utils.files_handle import get_files, get_relative_path
|
||||
from config.models import CaseFileType
|
||||
from config.settings import CASE_FILE_TYPE
|
||||
from config.path_config import DATA_DIR, CASE_TEMPLATE_DIR, AUTO_CASE_DIR
|
||||
from config.global_vars import CUSTOM_MARKERS
|
||||
from case_utils.case_data_analysis import CaseDataCheck
|
||||
|
||||
"""
|
||||
@@ -138,16 +140,17 @@ def generate_cases():
|
||||
if CASE_FILE_TYPE == CaseFileType.EXCEL.value:
|
||||
# 在用例数据"DATA_DIR"目录中寻找后缀是xlsx, xls的文件
|
||||
excel_files = get_files(target=DATA_DIR, start="test_", end=".xlsx") \
|
||||
+ get_files(target=DATA_DIR, start="test_", end=".xls")
|
||||
+ get_files(target=DATA_DIR, start="test_", end=".xls")
|
||||
elif CASE_FILE_TYPE == CaseFileType.YAML.value:
|
||||
# 在用例数据"DATA_DIR"目录中寻找后缀是yaml, yml的文件
|
||||
yaml_files = get_files(target=DATA_DIR, start="test_", end=".yaml") \
|
||||
+ get_files(target=DATA_DIR, start="test_", end=".yml")
|
||||
+ get_files(target=DATA_DIR, start="test_", end=".yml")
|
||||
elif CASE_FILE_TYPE == CaseFileType.ALL.value:
|
||||
# 在用例数据"DATA_DIR"目录中寻找后缀是xlsx,xls, yaml, yml的文件
|
||||
excel_files = get_files(target=DATA_DIR, start="test_", end=".xlsx") + get_files(target=DATA_DIR, start="test_",
|
||||
end=".xls")
|
||||
yaml_files = get_files(target=DATA_DIR, start="test_", end=".yaml") + get_files(target=DATA_DIR, start="test_", end=".yml")
|
||||
end=".xls")
|
||||
yaml_files = get_files(target=DATA_DIR, start="test_", end=".yaml") + get_files(target=DATA_DIR, start="test_",
|
||||
end=".yml")
|
||||
else:
|
||||
logger.error(f"{CASE_FILE_TYPE}不在CaseFileType内,不能自动生成用例!")
|
||||
# 自动生成测试用例
|
||||
@@ -173,9 +176,28 @@ def gen_case_file(filename, case_template_path, case_common, case_data, target_c
|
||||
如果设置为 True,则不论目录是否已存在,os.makedirs 都不会报错;如果设置为 False(默认值),则在目录已存在时会引发 FileExistsError 异常。
|
||||
"""
|
||||
os.makedirs(target_case_path, exist_ok=True)
|
||||
# 定义生成的测试用例的模板
|
||||
# 获取用例数据中的标记
|
||||
case_markers = case_common.get("case_markers", [])
|
||||
logger.debug(f"从用例中拿到的标记有:{case_markers}")
|
||||
# 先读取用例模板中每一行的内容
|
||||
with open(file=case_template_path, mode="r", encoding="utf-8") as f:
|
||||
case_template = f.read()
|
||||
case_template = f.readlines()
|
||||
current_case_template = []
|
||||
for line_num, content in enumerate(case_template):
|
||||
current_case_template.append(content)
|
||||
# 这里是预计往 @pytest.mark.parametrize( 这一行的上面插入标记
|
||||
if content.strip().startswith('@pytest.mark.parametrize('):
|
||||
# 往测试用例模板中插入自定义标记
|
||||
for case_marker in case_markers:
|
||||
# 获取符合要求格式的自定义标记名称,并插入到测试模板中
|
||||
marker = is_valid_marker(case_marker)
|
||||
if marker and isinstance(marker, str):
|
||||
# !! 注意这里的4个空格,必须要有4个空格!!
|
||||
current_case_template.append(f" @pytest.mark.{marker}\n")
|
||||
if marker and isinstance(marker, dict):
|
||||
for k, v in marker.items():
|
||||
# !! 注意这里的4个空格,必须要有4个空格!!
|
||||
current_case_template.append(f" @pytest.mark.{k}('{v}')\n")
|
||||
# 将用例数据的名称作为测试用例文件名称, 如test_login_demo
|
||||
func_name = filename
|
||||
# 方法名test_demo的类名是TestDemo
|
||||
@@ -184,11 +206,13 @@ def gen_case_file(filename, case_template_path, case_common, case_data, target_c
|
||||
"""
|
||||
string.Template是将一个string设置为模板,通过替换变量的方法,最终得到想要的string。
|
||||
"""
|
||||
my_case = Template(case_template).safe_substitute(
|
||||
current_template = ''.join(current_case_template)
|
||||
my_case = Template(current_template).safe_substitute(
|
||||
{
|
||||
"allure_epic": case_common["allure_epic"],
|
||||
"allure_feature": case_common["allure_feature"],
|
||||
"allure_story": case_common["allure_story"],
|
||||
"case_markers": case_common["case_markers"],
|
||||
"case_data": case_data,
|
||||
"func_title": func_name,
|
||||
"class_title": class_name,
|
||||
@@ -199,3 +223,38 @@ def gen_case_file(filename, case_template_path, case_common, case_data, target_c
|
||||
# 将测试用例方法写入py文件中
|
||||
with open(os.path.join(target_case_path, func_name + '.py'), "w", encoding="utf-8") as fp:
|
||||
fp.write(my_case)
|
||||
|
||||
|
||||
def is_valid_marker(markers):
|
||||
"""
|
||||
检查标记名称是否合法:仅支持非数字/下划线开头,由数字,字母,下划线组成的标记名称
|
||||
"""
|
||||
pattern = r'^[a-zA-Z_][a-zA-Z0-9_]*$'
|
||||
if isinstance(markers, str):
|
||||
if re.match(pattern, markers):
|
||||
# 将自定义标记放到CUSTOM_MARKERS, 方便后续统一注册
|
||||
if markers not in ("skip", "skipif", "parametrize", "usefixtures", "xfail", "filterwarings"):
|
||||
CUSTOM_MARKERS.append(markers)
|
||||
# 返回合法有效的标记名称,用于添加到测试方法中
|
||||
return markers
|
||||
else:
|
||||
logger.error(f"{markers} 格式不合法, 建议仅输入数字,字母,下划线组合,且不能以数字,下划线开头")
|
||||
return False
|
||||
elif isinstance(markers, dict):
|
||||
if len(markers) == 1:
|
||||
marker_name = list(markers.keys())[0]
|
||||
if re.match(pattern, marker_name):
|
||||
# 将自定义标记放到CUSTOM_MARKERS, 方便后续统一注册
|
||||
if marker_name not in ("skip", "skipif", "parametrize", "usefixtures", "xfail", "filterwarings"):
|
||||
CUSTOM_MARKERS.append(markers)
|
||||
return markers
|
||||
else:
|
||||
logger.error(f"{markers} 格式不合法, 建议仅输入数字,字母,下划线组合,且不能以数字,下划线开头")
|
||||
return None
|
||||
else:
|
||||
logger.error(f"{markers} 格式不合法, 只能存在一对键值对")
|
||||
return None
|
||||
|
||||
else:
|
||||
logger.error(f"{markers} 仅支持字符串或者字典格式")
|
||||
return None
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
# @File : global_vars.py
|
||||
# @Software: PyCharm
|
||||
# @Desc:
|
||||
|
||||
# 定义一个全局变量,用于存储运行过程中相关数据
|
||||
GLOBAL_VARS = {}
|
||||
|
||||
# 定义一个变量。存储自定义的标记markers
|
||||
CUSTOM_MARKERS = []
|
||||
|
||||
ENV_VARS = {
|
||||
"common": {
|
||||
"report_title": "自动化测试报告",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
# ------------------------------------ 配置信息 ----------------------------------------------------#
|
||||
# 0代表执行Excel和yaml两种格式的用例, 1 代表 yaml文件,2 用例代表Excel用例, 其他数值将不自动生成用例,仅能执行手动编写的用例
|
||||
CASE_FILE_TYPE = 3
|
||||
CASE_FILE_TYPE = 1
|
||||
|
||||
# 0表示默认不发送任何通知, 1代表钉钉通知,2代表企业微信通知, 3代表邮件通知, 4代表所有途径都发送通知
|
||||
SEND_RESULT_TYPE = 0
|
||||
|
||||
22
conftest.py
22
conftest.py
@@ -15,13 +15,14 @@ from loguru import logger
|
||||
from py._xmlgen import html # 安装pytest-html,版本最好是2.1.1
|
||||
import pytest
|
||||
# 本地应用/模块导入
|
||||
from config.global_vars import ENV_VARS, GLOBAL_VARS
|
||||
from config.global_vars import ENV_VARS, GLOBAL_VARS, CUSTOM_MARKERS
|
||||
|
||||
|
||||
# ------------------------------------- START: pytest钩子函数处理---------------------------------------#
|
||||
def pytest_configure(config):
|
||||
"""
|
||||
# 在测试运行前,修改Environment部分信息,配置测试报告环境信息
|
||||
1. 在测试运行前,修改Environment部分信息,配置测试报告环境信息
|
||||
2. 注册自定义标记
|
||||
"""
|
||||
# 给环境表 添加项目名称及开始时间
|
||||
config._metadata["项目名称"] = ENV_VARS["common"]["project_name"]
|
||||
@@ -29,10 +30,17 @@ def pytest_configure(config):
|
||||
# 给环境表 移除packages 及plugins
|
||||
config._metadata.pop("Packages")
|
||||
config._metadata.pop("Plugins")
|
||||
# 向pytest的配置中添加marker
|
||||
# TODO 暂时还没给用例添加
|
||||
config.addinivalue_line("markers", 'smoke')
|
||||
config.addinivalue_line("markers", '回归测试')
|
||||
# 注册自定义标记
|
||||
print(f"需要注册的标记:{CUSTOM_MARKERS}")
|
||||
markers = list(set(CUSTOM_MARKERS))
|
||||
for custom_marker in markers:
|
||||
if isinstance(custom_marker, str):
|
||||
config.addinivalue_line('markers', f'{custom_marker}')
|
||||
print(f"注册了自定义标记:{custom_marker}")
|
||||
elif isinstance(custom_marker, dict):
|
||||
for k, v in custom_marker.items():
|
||||
config.addinivalue_line('markers', f'{k}:{v}')
|
||||
print(f"注册了自定义标记:{custom_marker}")
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
@@ -83,7 +91,7 @@ def pytest_terminal_summary(terminalreporter, config):
|
||||
"-------------测试结果--------------------\n"
|
||||
f"用例总数: {_TOTAL}\n"
|
||||
f"跳过用例数: {_SKIPPED}\n"
|
||||
f"实际执行用例总数: {_TOTAL - _SKIPPED}\n\n"
|
||||
f"实际执行用例总数: {_PASSED + _FAILED + _XPASSED + _XFAILED}\n\n"
|
||||
f"异常用例数: {_ERROR}\n"
|
||||
f"失败用例数: {_FAILED}\n"
|
||||
f"重跑的用例数(--reruns的值): {_RERUN}({reruns_value})\n"
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
case_common:
|
||||
allure_epic: GitLink接口(自动生成用例)
|
||||
allure_epic: GitLink接口(自动生成用例)
|
||||
allure_feature: 开源夏令营模块
|
||||
allure_story: 获取项目列表接口
|
||||
case_markers:
|
||||
- glcc
|
||||
- get_project
|
||||
- skip: 跳过执行该用例
|
||||
|
||||
case_glcc_demo_01:
|
||||
feature: GLCC
|
||||
|
||||
@@ -3,11 +3,16 @@ case_common:
|
||||
allure_epic: GitLink接口(手动编写用例) # 敏捷里面的概念,定义史诗,相当于module级的标签, 往下是 feature
|
||||
allure_feature: 登录模块 # 功能点的描述,相当于class级的标签, 理解成模块往下是 story
|
||||
allure_story: 登录接口 # 故事,可以理解为场景,相当于method级的标签, 往下是 title
|
||||
case_markers: # pytest框架的标记 pytest.mark.
|
||||
- glcc: glcc相关的接口
|
||||
- get_project
|
||||
- skip: 跳过执行该用例
|
||||
|
||||
# 用例数据
|
||||
case_login_demo_01:
|
||||
feature: 登录
|
||||
title: 用户名密码正确,登录成功(不校验数据库)
|
||||
run: False
|
||||
run: True
|
||||
url: /api/accounts/login.json
|
||||
method: POST
|
||||
headers: {"Content-Type": "application/json; charset=utf-8;"}
|
||||
|
||||
@@ -3,6 +3,10 @@ case_common:
|
||||
allure_epic: GitLink接口(自动生成用例) # 敏捷里面的概念,定义史诗,相当于module级的标签, 往下是 feature
|
||||
allure_feature: 开源项目模块 # 功能点的描述,相当于class级的标签, 理解成模块往下是 story
|
||||
allure_story: 新建项目接口 # 故事,可以理解为场景,相当于method级的标签, 往下是 title
|
||||
case_markers:
|
||||
- gitlink
|
||||
- new_project
|
||||
- usefixtures: login_init
|
||||
|
||||
# 用例数据
|
||||
case_new_project_demo_01:
|
||||
@@ -34,7 +38,7 @@ case_new_project_demo_01:
|
||||
case_new_project_demo_02:
|
||||
feature: 新建项目
|
||||
title: 正确输入各项必填参数,新建项目成功(不校验数据库,单独传cookies)
|
||||
run: True
|
||||
run: False
|
||||
url: /api/projects.json
|
||||
method: POST
|
||||
headers:
|
||||
@@ -88,7 +92,7 @@ case_new_project_demo_03:
|
||||
case_new_project_demo_04:
|
||||
feature: 新建项目
|
||||
title: 正确输入各项必填参数,新建项目成功(04)
|
||||
run: True
|
||||
run: False
|
||||
url: /api/projects.json
|
||||
method: POST
|
||||
headers:
|
||||
@@ -113,7 +117,7 @@ case_new_project_demo_04:
|
||||
case_new_project_demo_05:
|
||||
feature: 新建项目
|
||||
title: 正确输入各项必填参数,新建项目成功(05)
|
||||
run: True
|
||||
run: False
|
||||
url: /api/projects.json
|
||||
method: POST
|
||||
headers:
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
# 公共参数
|
||||
case_common:
|
||||
allure_epic: GitLink接口(自动生成用例)
|
||||
allure_epic: GitLink接口(自动生成用例)
|
||||
allure_feature: 上传文件模块
|
||||
allure_story: 上传文件
|
||||
case_markers:
|
||||
- gitlink
|
||||
- upload_file
|
||||
|
||||
# 用例数据
|
||||
case_upload_demo_01:
|
||||
feature: 上传文件
|
||||
title: 测试单文件上传
|
||||
run: True
|
||||
run: False
|
||||
url: /api/attachments.json
|
||||
method: POST
|
||||
headers:
|
||||
|
||||
@@ -9,6 +9,5 @@ addopts =
|
||||
--reruns-delay=5
|
||||
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True
|
||||
markers =
|
||||
test_login_demo: login
|
||||
auto: auto generate case
|
||||
test_demo: demo case
|
||||
1
run.py
1
run.py
@@ -10,6 +10,7 @@
|
||||
1、用例创建原则,测试文件名必须以“test”开头,测试函数必须以“test”开头。
|
||||
2、运行方式:
|
||||
> python run.py (默认在test环境运行测试用例, 报告采用allure)
|
||||
> python run.py -m demo 在test环境仅运行打了标记demo用例, 默认报告采用allure
|
||||
> python run.py -env live 在live环境运行测试用例
|
||||
> python run.py -env=test 在test环境运行测试用例
|
||||
> python run.py -report=pytest-html (默认在test环境运行测试用例, 报告采用pytest-html)
|
||||
|
||||
@@ -25,7 +25,7 @@ def case_skip(request):
|
||||
pytest.skip(reason)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
@pytest.fixture(scope="session")
|
||||
def login_init():
|
||||
"""
|
||||
获取登录的cookie
|
||||
|
||||
@@ -34,8 +34,7 @@ for k, v in yaml_data.items():
|
||||
class TestLoginDemo:
|
||||
|
||||
@allure.story(case_common["allure_story"])
|
||||
@pytest.mark.test_login_demo
|
||||
@pytest.mark.auto
|
||||
@pytest.mark.test_demo
|
||||
@pytest.mark.parametrize("case", cases, ids=["{}".format(case["title"]) for case in cases])
|
||||
def test_login_demo_auto(self, case, extra):
|
||||
logger.info("\n-----------------------------START-开始执行用例-----------------------------\n")
|
||||
|
||||
Reference in New Issue
Block a user