增加allure报告优化类,allure报告增加步骤信息
This commit is contained in:
parent
5f3808d8f5
commit
fffc80efc2
|
@ -7,8 +7,9 @@
|
|||
import base64
|
||||
import json
|
||||
import time
|
||||
from typing import Optional, Tuple, Dict, Any
|
||||
from typing import Optional, Tuple, Any
|
||||
|
||||
import allure
|
||||
import py3curl
|
||||
import requests
|
||||
from requests import PreparedRequest
|
||||
|
@ -17,6 +18,7 @@ from requests.structures import CaseInsensitiveDict
|
|||
from common.base_log import logger
|
||||
from common.exceptions import ValueNotFoundError
|
||||
from configs.lins_environment import EntryPoint
|
||||
from utils.allure_handle import allure_attach_text, allure_attach_json
|
||||
from utils.time_utils import TimeUtil
|
||||
|
||||
|
||||
|
@ -64,7 +66,7 @@ class BaseApi:
|
|||
return params
|
||||
|
||||
@staticmethod
|
||||
def request(method, address, headers=None, params=None, data=None, json=None, files=None) -> requests.Response:
|
||||
def request(method, address, headers=None, params=None, data=None, json_data=None, files=None) -> requests.Response:
|
||||
"""发送http请求,返回response对象"""
|
||||
# 处理请求参数
|
||||
url = BaseApi._make_url(address)
|
||||
|
@ -76,20 +78,41 @@ class BaseApi:
|
|||
start_time = time.time() # 记录请求开始时间
|
||||
# 发起请求
|
||||
response = requests.request(method=method, url=url, headers=headers, params=params,
|
||||
data=data, json=json, files=files)
|
||||
data=data, json=json_data, files=files)
|
||||
end_time = time.time() # 记录请求结束时间
|
||||
elapsed_time = end_time - start_time # 计算请求时长
|
||||
duration = end_time - start_time # 计算请求时长
|
||||
# 记录请求时的详情信息
|
||||
r_uri = response.request.url
|
||||
r_method = method.upper()
|
||||
r_headers = response.request.headers
|
||||
r_body = BaseApi.get_request_body(response)
|
||||
r_curl = BaseApi.request_to_curl(response)
|
||||
r_respone = response.json()
|
||||
r_duration = duration
|
||||
r_respone_status_code = response.status_code
|
||||
r_respone_headers = response.headers
|
||||
_log_msg = f"\n==================================================\n" \
|
||||
f"请求路径:{response.request.url}\n" \
|
||||
f"请求方式:{method.upper()}\n" \
|
||||
f"请求头:{response.request.headers}\n" \
|
||||
f"请求内容:{BaseApi.get_request_body(response)}\n" \
|
||||
f"请求curl命令:{BaseApi.request_to_curl(response)}\n" \
|
||||
f"接口响应内容:{response.json()}\n" \
|
||||
f"接口响应时长:{elapsed_time:.2f}秒\n" \
|
||||
f"HTTP状态码:{response.status_code}\n" \
|
||||
f"请求路径:{r_uri}\n" \
|
||||
f"请求方式:{r_method}\n" \
|
||||
f"请求头:{r_headers}\n" \
|
||||
f"请求内容:{r_body}\n" \
|
||||
f"请求curl命令:{r_curl}\n" \
|
||||
f"接口响应内容:{r_respone}\n" \
|
||||
f"接口响应头:{r_respone_headers}\n" \
|
||||
f"接口响应时长:{r_duration:.2f}秒\n" \
|
||||
f"HTTP状态码:{r_respone_status_code}\n" \
|
||||
f"=================================================="
|
||||
with allure.step("请求内容"):
|
||||
allure_attach_text("请求路径", f"{r_uri}")
|
||||
allure_attach_text("请求方式", f"{r_method}")
|
||||
allure_attach_text("请求头", f"{r_headers}")
|
||||
allure_attach_json("请求体", f"{r_body}")
|
||||
allure_attach_text("请求curl命令", f"{r_curl}")
|
||||
with allure.step("响应内容"):
|
||||
allure_attach_json("响应体", f"{json.dumps(r_respone, ensure_ascii=False, indent=4)}")
|
||||
allure_attach_text("HTTP状态码", f"{r_respone_status_code}")
|
||||
allure_attach_text("响应头", f"{r_respone_headers}")
|
||||
|
||||
if response.status_code == 200:
|
||||
logger.info(_log_msg)
|
||||
else:
|
||||
|
@ -107,19 +130,22 @@ class BaseApi:
|
|||
return BaseApi.request(method='get', address=address, params=params, headers=headers)
|
||||
|
||||
@staticmethod
|
||||
def post(address, data=None, json=None, headers=None, files=None) -> requests.Response:
|
||||
def post(address, data=None, json_data=None, headers=None, files=None) -> requests.Response:
|
||||
"""发送post请求,返回response对象"""
|
||||
return BaseApi.request(method='post', address=address, data=data, json=json, headers=headers, files=files)
|
||||
return BaseApi.request(method='post', address=address, data=data, json_data=json_data, headers=headers,
|
||||
files=files)
|
||||
|
||||
@staticmethod
|
||||
def delete(address, data=None, json=None, headers=None, files=None) -> requests.Response:
|
||||
"""发送delete请求,返回response对象"""
|
||||
return BaseApi.request(method='delete', address=address, data=data, json=json, headers=headers, files=files)
|
||||
return BaseApi.request(method='delete', address=address, data=data, json_data=json, headers=headers,
|
||||
files=files)
|
||||
|
||||
@staticmethod
|
||||
def put(address, data=None, json=None, headers=None, files=None) -> requests.Response:
|
||||
def put(address, data=None, json_data=None, headers=None, files=None) -> requests.Response:
|
||||
"""发送put请求,返回response对象"""
|
||||
return BaseApi.request(method='put', address=address, data=data, json=json, headers=headers, files=files)
|
||||
return BaseApi.request(method='put', address=address, data=data, json_data=json_data, headers=headers,
|
||||
files=files)
|
||||
|
||||
@staticmethod
|
||||
def get_json(response: requests.Response) -> json:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# @File : models.py
|
||||
# @project : SensoroApi
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from enum import Enum, unique
|
||||
from typing import Text
|
||||
|
||||
|
||||
|
@ -34,3 +34,33 @@ class TestMetrics:
|
|||
if __name__ == '__main__':
|
||||
print(Environment.DEV.name)
|
||||
print(Environment.DEV.value)
|
||||
|
||||
|
||||
@unique # 枚举类装饰器,确保只有一个名称绑定到任何一个值。
|
||||
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"
|
||||
|
|
31
conftest.py
31
conftest.py
|
@ -4,45 +4,22 @@
|
|||
# @Author : wangjie
|
||||
# @File : conftest.py
|
||||
# @project : SensoroApi
|
||||
import os.path
|
||||
import platform
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from common.models import TestMetrics
|
||||
from common.settings import ENV
|
||||
from configs.dir_path_config import BASE_DIR
|
||||
from configs.lins_environment import EntryPoint
|
||||
from utils.report_data_handle import ReportDataHandle
|
||||
|
||||
|
||||
def pytest_sessionstart():
|
||||
"""在整个pytest运行过程开始之前设置allure报告的环境变量信息"""
|
||||
allure_env = {
|
||||
'OperatingEnvironment': ENV.name,
|
||||
'BaseUrl': EntryPoint.URL(),
|
||||
'PythonVersion': platform.python_version(),
|
||||
'Platform': platform.platform(),
|
||||
'PytestVersion': pytest.__version__,
|
||||
}
|
||||
allure_env_file = os.path.join(BASE_DIR, 'environment.properties')
|
||||
with open(allure_env_file, 'w', encoding='utf-8') as f:
|
||||
for _k, _v in allure_env.items():
|
||||
f.write(f'{_k}={_v}\n')
|
||||
"""在整个pytest运行过程开始之前执行的操作"""
|
||||
pass
|
||||
|
||||
|
||||
def pytest_sessionfinish(session, exitstatus):
|
||||
"""运行完成后生成allure报告文件,再将本地启动方式放入该目录下"""
|
||||
# # allure报告展示environment时所需要的数据,这里是在项目根路径下创建的environment.properties文件拷贝到allure-report报告中,保证环境文件不会被清空
|
||||
# FileHandle.copy_file(BASE_DIR + os.sep + 'environment.properties', TEMP_DIR)
|
||||
# # allure报告展示运行器时所需要的数据
|
||||
# FileHandle.copy_file(BASE_DIR + os.sep + 'executor.json', TEMP_DIR)
|
||||
# # 使用allure generate -o 命令将./Temp目录下的临时报告生成到Report目录下变成html报告
|
||||
# os.system(f'allure generate {TEMP_DIR} -o {ALLURE_REPORT_DIR} --clean')
|
||||
# # 将本地启动脚本和查看allure报告方法放入报告目录下面
|
||||
# FileHandle.copy_file(BASE_DIR + os.sep + 'open_report.sh', ALLURE_REPORT_DIR)
|
||||
# FileHandle.copy_file(BASE_DIR + os.sep + '查看allure报告方法', ALLURE_REPORT_DIR)
|
||||
"""在整个pytest session结束后执行的操作"""
|
||||
pass
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(items) -> None:
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
OperatingEnvironment=TEST
|
||||
BaseUrl=https://www.wanandroid.com
|
||||
PythonVersion=3.10.4
|
||||
Platform=macOS-12.3.1-arm64-arm-64bit
|
||||
PytestVersion=7.4.0
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "汪杰",
|
||||
"type": "jenkins",
|
||||
"url": "http://helloqa.com",
|
||||
"buildOrder": 3,
|
||||
"buildName": "allure-report_deploy#1",
|
||||
"buildUrl": "http://helloqa.com#1",
|
||||
"reportUrl": "http://helloqa.com#1/AllureReport",
|
||||
"reportName": "汪杰 Allure Report"
|
||||
}
|
|
@ -15,7 +15,7 @@ class Login(BaseApi):
|
|||
'password': password
|
||||
}
|
||||
|
||||
return self.post(address, json=json)
|
||||
return self.post(address, json_data=json)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
16
run.py
16
run.py
|
@ -16,6 +16,7 @@ import pytest
|
|||
|
||||
from common.base_log import logger
|
||||
from common.models import TestMetrics
|
||||
from utils.allure_handle import AllureReportBeautiful
|
||||
from utils.command_parser import command_parser
|
||||
from common.mail_sender import MailSender
|
||||
from common.robot_sender import EnterpriseWechatNotification
|
||||
|
@ -58,17 +59,22 @@ if __name__ == '__main__':
|
|||
# '-m smoke', # 只运行mark标记为smoke的测试用例
|
||||
])
|
||||
|
||||
###################发送allure报告
|
||||
# allure报告展示environment时所需要的数据,这里是在项目根路径下创建的environment.properties文件拷贝到allure-report报告中,保证环境文件不会被清空
|
||||
FileHandle.copy_file(BASE_DIR + os.sep + 'environment.properties', TEMP_DIR)
|
||||
# allure报告展示运行器时所需要的数据
|
||||
FileHandle.copy_file(BASE_DIR + os.sep + 'executor.json', TEMP_DIR)
|
||||
# ------------------------------发送allure报告----------------------------------
|
||||
# 生成allure报告环境信息
|
||||
AllureReportBeautiful.set_report_env_on_results()
|
||||
# 生成allure报告执行器信息
|
||||
AllureReportBeautiful.set_report_executer_on_results()
|
||||
# 使用allure generate -o 命令将./Temp目录下的临时报告生成到Report目录下变成html报告
|
||||
os.system(f'allure generate {TEMP_DIR} -o {ALLURE_REPORT_DIR} --clean')
|
||||
# 修改allure报告浏览器窗口标题
|
||||
AllureReportBeautiful.set_windows_title("Sensoro自动化")
|
||||
# 修改allure报告标题
|
||||
AllureReportBeautiful.set_report_name("Sensoro自动化测试报告")
|
||||
# 将本地启动脚本和查看allure报告方法放入报告目录下面
|
||||
FileHandle.copy_file(BASE_DIR + os.sep + 'open_report.sh', ALLURE_REPORT_DIR)
|
||||
FileHandle.copy_file(BASE_DIR + os.sep + '查看allure报告方法', ALLURE_REPORT_DIR)
|
||||
|
||||
# ------------------------------发送通知消息----------------------------------
|
||||
# 发送企业微信群聊
|
||||
pytest_result = asdict(TestMetrics(**ReportDataHandle.pytest_json_report_case_count()))
|
||||
if IS_SEND_WECHAT: # 判断是否需要发送企业微信
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
# @Author : wangjie
|
||||
# @File : conftest.py
|
||||
# @project : SensoroApi
|
||||
import os.path
|
||||
import platform
|
||||
|
||||
import allure
|
||||
import pytest
|
||||
|
||||
|
@ -14,6 +11,7 @@ from common.base_api import BaseApi
|
|||
from common.base_log import logger
|
||||
from common.exceptions import ValueNotFoundError
|
||||
from pageApi.login import Login
|
||||
from utils.allure_handle import allure_attach_text
|
||||
|
||||
# 定义一个全局变量,用于存储提取的参数内容
|
||||
_global_data = {}
|
||||
|
@ -28,8 +26,9 @@ def set_global_data():
|
|||
|
||||
def _set_global_data(cache_name, value):
|
||||
_global_data[cache_name] = value
|
||||
allure.attach(str(f"'{cache_name}':'{value}'"), '设置变量:', allure.attachment_type.TEXT)
|
||||
allure.attach(str(_global_data), '当前可使用的全局变量:', allure.attachment_type.TEXT)
|
||||
with allure.step("提取"):
|
||||
allure_attach_text("设置变量", str(f"'{cache_name}':'{value}'"))
|
||||
allure_attach_text("当前可使用的全局变量", str(_global_data))
|
||||
|
||||
yield _set_global_data
|
||||
_global_data.clear()
|
||||
|
@ -44,11 +43,12 @@ def get_global_data():
|
|||
|
||||
def _get_global_data(cache_data):
|
||||
try:
|
||||
allure.attach(str(f"{cache_data}:{_global_data.get(cache_data, None)}"), '取出来的变量:',
|
||||
allure.attachment_type.TEXT)
|
||||
with allure.step("提取"):
|
||||
allure_attach_text("取出来的变量", str(f"{cache_data}:{_global_data.get(cache_data, None)}"))
|
||||
return _global_data[cache_data]
|
||||
except KeyError:
|
||||
allure.attach(str(_global_data), '获取变量失败,当前可使用的全局变量:', allure.attachment_type.TEXT)
|
||||
with allure.step("获取变量失败,当前可使用的全局变量"):
|
||||
allure_attach_text("获取变量失败,当前可使用的全局变量", str(_global_data))
|
||||
raise ValueNotFoundError(f"{cache_data}的缓存数据未找到,请检查是否将该数据存入缓存中")
|
||||
|
||||
return _get_global_data
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
# !/usr/bin/python
|
||||
# -*- coding:utf-8 -*-
|
||||
# @Time : 2023/9/27 20:05
|
||||
# @Author : wangjie
|
||||
# @File : allure_handle.py
|
||||
# @project : SensoroApiAutoTest
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
|
||||
import allure
|
||||
import pytest
|
||||
|
||||
from common.models import AllureAttachmentType
|
||||
from common.settings import ENV
|
||||
from configs.dir_path_config import TEMP_DIR, ALLURE_REPORT_DIR
|
||||
from configs.lins_environment import EntryPoint
|
||||
|
||||
|
||||
def allure_title(title: str) -> None:
|
||||
"""allure中动态生成用例标题"""
|
||||
# allure.dynamic动态属性
|
||||
allure.dynamic.title(title)
|
||||
|
||||
|
||||
def allure_attach_text(name: str, body: str = None) -> None:
|
||||
"""
|
||||
allure报告添加文本格式附件
|
||||
:param name: 附件名称
|
||||
:param body: 附件内容
|
||||
:return:
|
||||
"""
|
||||
allure.attach(body=body, name=name, attachment_type=allure.attachment_type.TEXT)
|
||||
|
||||
|
||||
def allure_attach_json(name: str, body: str = None) -> None:
|
||||
"""
|
||||
allure报告添加json格式附件
|
||||
:param name: 附件名称
|
||||
:param body: 附件内容
|
||||
:return:
|
||||
"""
|
||||
allure.attach(body=body, name=name, attachment_type=allure.attachment_type.JSON)
|
||||
|
||||
|
||||
def allure_attach_file(name: str, source: str):
|
||||
"""
|
||||
allure报告上传附件、图片、excel等
|
||||
:param name: 名称
|
||||
:param source: 文件路径,相当于传一个文件
|
||||
:return:
|
||||
"""
|
||||
# 获取上传附件的尾缀,判断对应的 attachment_type 枚举值
|
||||
_name = source.split('.')[-1]
|
||||
if _name == "txt" or _name == "uri":
|
||||
_name = "text" if _name == "txt" else "uri_list"
|
||||
attachment_type_mapping = {
|
||||
AllureAttachmentType.TEXT: allure.attachment_type.TEXT,
|
||||
AllureAttachmentType.CSV: allure.attachment_type.CSV,
|
||||
AllureAttachmentType.TSV: allure.attachment_type.TSV,
|
||||
AllureAttachmentType.URI_LIST: allure.attachment_type.URI_LIST,
|
||||
AllureAttachmentType.HTML: allure.attachment_type.HTML,
|
||||
AllureAttachmentType.XML: allure.attachment_type.XML,
|
||||
AllureAttachmentType.JSON: allure.attachment_type.JSON,
|
||||
AllureAttachmentType.YAML: allure.attachment_type.YAML,
|
||||
AllureAttachmentType.PCAP: allure.attachment_type.PCAP,
|
||||
AllureAttachmentType.PNG: allure.attachment_type.PNG,
|
||||
AllureAttachmentType.JPG: allure.attachment_type.JPG,
|
||||
AllureAttachmentType.SVG: allure.attachment_type.SVG,
|
||||
AllureAttachmentType.GIF: allure.attachment_type.GIF,
|
||||
AllureAttachmentType.BMP: allure.attachment_type.BMP,
|
||||
AllureAttachmentType.TIFF: allure.attachment_type.TIFF,
|
||||
AllureAttachmentType.MP4: allure.attachment_type.MP4,
|
||||
AllureAttachmentType.OGG: allure.attachment_type.OGG,
|
||||
AllureAttachmentType.WEBM: allure.attachment_type.WEBM,
|
||||
AllureAttachmentType.PDF: allure.attachment_type.PDF, }
|
||||
_attachment_type = attachment_type_mapping.get(getattr(AllureAttachmentType, _name.upper(), None), None)
|
||||
allure.attach.file(source=source, name=name,
|
||||
attachment_type=_attachment_type,
|
||||
extension=_name)
|
||||
|
||||
|
||||
class AllureReportBeautiful:
|
||||
"""
|
||||
美化allure测试报告
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def set_windows_title(new_title):
|
||||
"""
|
||||
设置打开的 Allure 报告的浏览器窗口标题文案
|
||||
@param new_title: 需要更改的标题文案 【 原文案为:Allure Report 】
|
||||
@return:
|
||||
"""
|
||||
report_title_filepath = os.path.join(ALLURE_REPORT_DIR, "index.html")
|
||||
# 定义为只读模型,并定义名称为: f
|
||||
with open(report_title_filepath, 'r+', encoding="utf-8") as f:
|
||||
# 读取当前文件的所有内容
|
||||
all_the_lines = f.readlines()
|
||||
f.seek(0)
|
||||
f.truncate()
|
||||
# 循环遍历每一行的内容,将 "Allure Report" 全部替换为 → new_title(新文案)
|
||||
for line in all_the_lines:
|
||||
f.write(line.replace("Allure Report", new_title))
|
||||
# 关闭文件
|
||||
f.close()
|
||||
|
||||
@staticmethod
|
||||
def set_report_name(new_name):
|
||||
"""
|
||||
修改Allure报告Overview的标题文案
|
||||
@param new_name: 需要更改的标题文案 【 原文案为:ALLURE REPORT 】
|
||||
@return:
|
||||
"""
|
||||
title_filepath = os.path.join(ALLURE_REPORT_DIR, "widgets", "summary.json")
|
||||
# 读取summary.json中的json数据,并改写reportName
|
||||
with open(title_filepath, 'rb') as f:
|
||||
# 加载json文件中的内容给params
|
||||
params = json.load(f)
|
||||
# 修改内容
|
||||
params['reportName'] = new_name
|
||||
# 将修改后的内容保存在dict中
|
||||
new_params = params
|
||||
# 往summary.json中,覆盖写入新的json数据
|
||||
with open(title_filepath, 'w', encoding="utf-8") as f:
|
||||
json.dump(new_params, f, ensure_ascii=False, indent=4)
|
||||
|
||||
@staticmethod
|
||||
def set_report_env_on_results():
|
||||
"""
|
||||
在allure-results报告的根目录下生成一个写入了环境信息的文件:environment.properties(注意:不能放置中文,否则会出现乱码)
|
||||
@return:
|
||||
"""
|
||||
# 需要写入的环境信息
|
||||
allure_env = {
|
||||
'OperatingEnvironment': ENV.name,
|
||||
'BaseUrl': EntryPoint.URL(),
|
||||
'PythonVersion': platform.python_version(),
|
||||
'Platform': platform.platform(),
|
||||
'PytestVersion': pytest.__version__,
|
||||
}
|
||||
allure_env_file = os.path.join(TEMP_DIR, 'environment.properties')
|
||||
with open(allure_env_file, 'w', encoding='utf-8') as f:
|
||||
for _k, _v in allure_env.items():
|
||||
f.write(f'{_k}={_v}\n')
|
||||
|
||||
@staticmethod
|
||||
def set_report_executer_on_results():
|
||||
"""
|
||||
在allure-results报告的根目录下生成一个写入了执行人的文件:executor.json
|
||||
@return:
|
||||
"""
|
||||
# 需要写入的环境信息
|
||||
allure_executor = {
|
||||
"name": "汪杰",
|
||||
"type": "jenkins",
|
||||
"url": "http://helloqa.com",
|
||||
"buildOrder": 3,
|
||||
"buildName": "allure-report_deploy#1",
|
||||
"buildUrl": "http://helloqa.com#1",
|
||||
"reportUrl": "http://helloqa.com#1/AllureReport",
|
||||
"reportName": "汪杰 Allure Report"
|
||||
}
|
||||
allure_env_file = os.path.join(TEMP_DIR, 'executor.json')
|
||||
with open(allure_env_file, 'w', encoding='utf-8') as f:
|
||||
f.write(str(json.dumps(allure_executor, ensure_ascii=False, indent=4)))
|
Loading…
Reference in New Issue