根据最新框架,更新readme文件;并对部分模块代码进行细微优化调整

This commit is contained in:
floraachy
2023-06-28 16:55:00 +08:00
parent a96d674518
commit f226441d32
9 changed files with 80 additions and 54 deletions
+23 -19
View File
@@ -24,11 +24,12 @@
## 二、实现功能
* 通过session会话方式,解决了登录之后cookie关联处理
* 数据库断言: 直接在测试用例中写入查询的sql即可断言,无需编写代码
* 动态多断言: 如接口需要同时校验响应数据和sql校验,支持多场景断言
* 框架天然支持接口动态传参、关联灵活处理
* 支持测试数据分析,测试数据不符合规范有预警机制
* 测试数据隔离, 实现数据驱动
* 自动生成用例代码: 测试人员在yaml/excel文件中填写好测试用例, 程序可以直接生成用例代码,纯小白也能使用
* 动态多断言: 支持响应断言和数据库断言
* 多种报告随心选择:框架支持pytest-html以及Allure测试报告,可以动态配置所需报告
* 日志模块: 采用loguru管理日志,可以输出更为优雅,简洁的日志
* 钉钉、企业微信通知: 支持多种通知场景,执行成功之后,可选择发送钉钉、或者企业微信、邮箱通知
@@ -46,6 +47,7 @@
│ ├────case_data_analysis 分析用例数据是否符合规范
│ ├────case_fun_handle.py 根据配置文件,从指定类型文件中读取用例数据,并调用生成用例文件方法,生成用例文件
│ ├────data_handle.py 数据处理
│ ├────extract_data_handle.py 提取数据的一些方法
│ ├────get_results_handle.py 从pytest-html/allure测试报告中获取测试结果
│ ├────platform_handle.py 跨平台的支持allure,用于生成allure测试报告
│ ├────request_data_handle.py 针对用例数据进行请求前后的处理
@@ -177,24 +179,24 @@ pip install pipenv
### 5. 用例中相关字段的介绍
```yaml
- case_common :公共参数
- allure_epic:用作于@allure.epic()装饰器中的内容。如果是使用Excel管理用例数据,这个目前是写死的。可在case_utils.case_handle.py中更改。
- allure_feature:用作于@allure.feature()装饰器中的内容。如果是使用Excel管理用例数据, 这个用的是excel的表单名称。
- allure_story:用作于@allure.story()装饰器中的内容。如果是使用Excel管理用例数据, 这个用的是excel的表单名称。
- case_info:用例数据
- feature:用例所属模块, 类似于@allure.feature()。
- title:用例标题
- run:是否执行用例,为空或者True都会执行,为False则不执行。
- url:请求路径(可填写全路径 或者 资源路径)。通常我们填写资源路径。在用例执行前,会针对路径进行处理。具体可见case_utils.request_data_handle.py.RequestPreDataHandle.url_handle。注:请求路径=基准路径(host/base_url+资源路径(url)。
- method:请求方式,例如:GET, POST, DELETE, PUT, PATCH等
- headers:请求头,注意如果在headers里面防止cookies,其值类型需要是字符串
- cookies:请求cookies,格式是:DICT CookieJar对象
- request_type:请求数据类型:params, json, file, data
- payload:请求参数
- files:上传附件接口所需的文件绝对路径
- extract:后置提取参数
- assert_response:响应断言
- assert_sql:数据库断言
case_common :公共参数
allure_epic:用作于@allure.epic()装饰器中的内容。
allure_feature:用作于@allure.feature()装饰器中的内容。
allure_story:用作于@allure.story()装饰器中的内容。
case_001:用例ID
feature:用例所属模块, 类似于@allure.feature()。
title:用例标题
run:是否执行用例,为空或者True都会执行,为False则不执行。
url:请求路径(可填写全路径 或者 资源路径)。通常我们填写资源路径。在用例执行前,会针对路径进行处理。具体可见case_utils.request_data_handle.py.RequestPreDataHandle.url_handle。注:请求路径=基准路径(host/base_url+资源路径(url)。
method:请求方式,例如:GET, POST, DELETE, PUT, PATCH等
headers:请求头,注意如果在headers里面防止cookies,其值类型需要是字符串
cookies:请求cookies,格式是:DICT CookieJar对象
request_type:请求数据类型:params, json, file, data
payload:请求参数
files: 需要上传的文件,参考如下传参:{接口中文件参数的名称:”文件路径地址”/[“文件地址1”, “文件地址2”]}
extract:后置提取参数
assert_response:响应断言
assert_sql:数据库断言
```
### 6. Excel用例单独说明
框架支持excel多表单自动生成测试用例,每一个表单作为一个测试用例模块。
@@ -269,6 +271,8 @@ excel表单2名称是:示例模块
- [如何处理同一套框架测试多套环境的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/215)
- [如何处理用例中需要依赖登录的token/cookies的情况?](https://www.gitlink.org.cn/zone/tester/newdetail/228)
## 十、初始化项目可能遇到的问题
+10 -8
View File
@@ -6,9 +6,11 @@
# @Software: PyCharm
# @Desc: 断言
# 第三方库导入
from loguru import logger
from requests import Response
from case_utils.data_handle import json_extractor, re_extract
# 本地应用/模块导入
from case_utils.extract_data_handle import json_extractor, re_extract
from case_utils.request_data_handle import response_type
from case_utils.allure_handle import allure_step
from common_utils.mysql_handle import MysqlServer
@@ -53,19 +55,19 @@ def assert_response(response: Response, expected: dict) -> None:
try:
if k == "eq": # 预期结果 = 实际结果
assert _v == actual
logger.debug(f"预期结果: {_k}: {_v} == 实际结果: {actual}, 断言成功!")
logger.success(f"预期结果: {_k}: {_v} == 实际结果: {actual}, 断言成功!")
elif k == "in": # 实际结果 包含 预期结果
assert _v in actual
logger.debug(f"预期结果: {_k}: {_v} in 实际结果: {actual}, 断言成功!")
logger.success(f"预期结果: {_k}: {_v} in 实际结果: {actual}, 断言成功!")
elif k == "gt": # 预期结果 > 实际结果 (值应该为数值型)
assert _v > actual
logger.debug(f"预期结果: {_k}: {_v} > 实际结果: {actual}, 断言成功!")
logger.success(f"预期结果: {_k}: {_v} > 实际结果: {actual}, 断言成功!")
elif k == "lt": # 预期结果 < 实际结果 (值应该为数值型)
assert _v < actual
logger.debug(f"预期结果: {_k}: {_v} < 实际结果: {actual}, 断言成功!")
logger.success(f"预期结果: {_k}: {_v} < 实际结果: {actual}, 断言成功!")
elif k == "not": # 预期结果 != 实际结果
assert _v != actual
logger.debug(f"预期结果: {_k}: {_v} != 实际结果: {actual}, 断言成功!")
logger.success(f"预期结果: {_k}: {_v} != 实际结果: {actual}, 断言成功!")
else:
logger.error(f"判断关键字: {k} 错误!, 目前仅支持如下关键字:eq, in, gt, lt, not")
allure_step(step_title=f'判断关键字: {k} 错误!',
@@ -129,13 +131,13 @@ def assert_sql(db_info, expected: dict):
if k == "eq": # 预期结果 = 实际结果
if _k == "len":
assert _v == len(sql_result)
logger.info(f"预期结果: {_v} == 实际结果: {len(sql_result)}, 断言成功!")
logger.success(f"预期结果: {_v} == 实际结果: {len(sql_result)}, 断言成功!")
allure_step(step_title=f'数据库断言结果---->预期结果: {_v} == 实际结果: {len(sql_result)}, 断言成功!')
# 如果时$.开头,则从数据库查询结果中提取相应的值作为实际结果
elif _k.startswith("$."):
actual = json_extractor(sql_result, _k)
assert _v == actual
logger.info(f"预期结果: {_v} == 实际结果: {actual}, 断言成功!")
logger.success(f"预期结果: {_v} == 实际结果: {actual}, 断言成功!")
allure_step(step_title=f'数据库断言结果---->预期结果: {_v} == 实际结果: {actual}, 断言成功!')
except AssertionError:
logger.error(f"数据库断言失败 -|- 预期结果:{_v} {k} 实际结果: {sql_result})")
+5 -1
View File
@@ -5,14 +5,18 @@
# @File : request_data_handle.py
# @Software: PyCharm
# @Desc: 处理request请求前后的用例数据
# 标准库导入
import json
import os
# 第三方库导入
from requests import Response
from loguru import logger
# 本地应用/模块导入
from common_utils.files_handle import get_file_field
from common_utils.base_request import BaseRequest
from case_utils.data_handle import eval_data_process, data_handle
from case_utils.data_handle import json_extractor, re_extract
from case_utils.extract_data_handle import json_extractor, re_extract
from case_utils.allure_handle import allure_step
from config.global_vars import GLOBAL_VARS
from config.path_config import FILES_DIR
+2 -2
View File
@@ -23,7 +23,7 @@ class ${class_title}Auto:
@pytest.mark.auto
@pytest.mark.parametrize("case", cases, ids=["{}".format(case["title"]) for case in cases])
def ${func_title}_auto(self, case, extra):
logger.info("-----------------------------START-开始执行用例-----------------------------")
logger.info("\n-----------------------------START-开始执行用例-----------------------------\n")
logger.debug(f"当前执行的用例数据:{case}")
# 添加用例标题作为allure中显示的用例标题
allure_title(case.get("title", ""))
@@ -41,5 +41,5 @@ class ${class_title}Auto:
assert_sql(db_info[GLOBAL_VARS["env_key"]], case_data["assert_sql"])
# 断言成功后进行参数提取
after_request_extract(response, case_data.get("extract", None))
logger.info("-----------------------------END-用例执行结束-----------------------------")
logger.info("\n-----------------------------END-用例执行结束-----------------------------\n")
+11 -1
View File
@@ -15,7 +15,17 @@ SEND_RESULT_TYPE = 0
# 指定日志收集级别
LOG_LEVEL = "INFO"
"""
支持的日志级别:
None 表示捕获所有日志
TRACE: 最低级别的日志级别,用于详细追踪程序的执行。
DEBUG: 用于调试和开发过程中打印详细的调试信息。
INFO: 提供程序执行过程中的关键信息。
SUCCESS: 用于标记成功或重要的里程碑事件。
WARNING: 表示潜在的问题或不符合预期的情况,但不会导致程序失败。
ERROR: 表示错误和异常情况,但程序仍然可以继续运行。
CRITICAL: 表示严重的错误和异常情况,可能导致程序崩溃或无法正常运行。
"""
# ------------------------------------ 数据库相关配置 ----------------------------------------------------#
db_info = {
"test": {
+11 -8
View File
@@ -6,13 +6,16 @@
# @Software: PyCharm
# @Desc: 这是文件的描述信息
# 标准库导入
import re
import time
from time import strftime
import re
import pytest
from py._xmlgen import html # 安装pytest-html,版本最好是2.1.1
from config.global_vars import ENV_VARS, GLOBAL_VARS
# 第三方库导入
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
# ------------------------------------- START: pytest钩子函数处理---------------------------------------#
@@ -76,24 +79,24 @@ def pytest_terminal_summary(terminalreporter, config):
_TOTAL = terminalreporter._numcollected
_TIMES = time.time() - terminalreporter._sessionstarttime
logger.info(f"\n======================================================\n"
logger.success(f"\n======================================================\n"
"-------------测试结果--------------------\n"
f"用例总数: {_TOTAL}\n"
f"跳过用例数: {_SKIPPED}\n"
f"实际执行用例总数: {_TOTAL - _SKIPPED}\n\n"
f"异常用例数: {_ERROR}\n"
f"失败用例数: {_FAILED}\n"
f"重跑的用例数 || 重跑次数: {_RERUN} || {reruns_value}\n"
f"重跑的用例数(--reruns的值): {_RERUN}({reruns_value})\n"
f"意外通过的用例数: {_XPASSED}\n"
f"预期失败的用例数: {_XFAILED}\n\n"
"用例执行时长: %.2f" % _TIMES + " s\n")
try:
_RATE = _PASSED / (_TOTAL - _SKIPPED) * 100
logger.info(
logger.success(
f"\n用例成功率: %.2f" % _RATE + " %\n"
"=====================================================")
except ZeroDivisionError:
logger.info(
logger.critical(
f"用例成功率: 0.00 %\n"
"=====================================================")
+5 -2
View File
@@ -31,12 +31,15 @@ pytest相关参数:以下也可通过pytest.ini配置
–-alluredir这个选项用于指定存储测试结果的路径
"""
# 标准库导入
import os
import shutil
from datetime import datetime
# 第三方库导入
import pytest
from loguru import logger
import click
from datetime import datetime
# 本地应用/模块导入
from case_utils.case_fun_handle import generate_cases
from case_utils.platform_handle import PlatformHandle
from case_utils.send_result_handle import send_result
@@ -71,7 +74,7 @@ def capture_all_logs(level=LOG_LEVEL):
else:
# 捕获所有日志
logger.add(
os.path.join(LOG_DIR, "runtime_{time}_{level}.log"),
os.path.join(LOG_DIR, "runtime_{time}_all.log"),
enqueue=True,
encoding="utf-8",
rotation="00:00",
+2 -2
View File
@@ -22,7 +22,7 @@ cases = [{"title": "demo用例01", "user": "flora", "age": 17, "run": True},
@pytest.mark.test_demo
@pytest.mark.parametrize("case", cases, ids=["{}".format(case["title"]) for case in cases])
def test_demo(case, extra):
logger.info("-----------------------------START-开始执行用例-----------------------------")
logger.info("\n-----------------------------START-开始执行用例-----------------------------\n")
logger.debug(f"当前执行的用例数据:{case}")
# 添加用例标题作为allure中显示的用例标题
allure_title(case.get("title", ""))
@@ -31,4 +31,4 @@ def test_demo(case, extra):
# 在allure报告中显示请求的用例数据
allure_step(step_title="用例数据", content=f"{case}")
assert case["user"] == "flora"
logger.info("-----------------------------END-用例执行结束-----------------------------")
logger.info("\n-----------------------------END-用例执行结束-----------------------------\n")
@@ -38,7 +38,7 @@ class TestLoginDemo:
@pytest.mark.auto
@pytest.mark.parametrize("case", cases, ids=["{}".format(case["title"]) for case in cases])
def test_login_demo_auto(self, case, extra):
logger.info("-----------------------------START-开始执行用例-----------------------------")
logger.info("\n-----------------------------START-开始执行用例-----------------------------\n")
logger.debug(f"当前执行的用例数据:{case}")
# 添加用例标题作为allure中显示的用例标题
allure_title(case.get("title", ""))
@@ -56,4 +56,4 @@ class TestLoginDemo:
assert_sql(db_info[GLOBAL_VARS["env_key"]], case_data["assert_sql"])
# 断言成功后进行参数提取
after_request_extract(response, case_data.get("extract", None))
logger.info("-----------------------------END-用例执行结束-----------------------------")
logger.info("\n-----------------------------END-用例执行结束-----------------------------\n")