mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-27 06:41:12 +00:00
feat: 重构前端项目结构并优化代码
refactor: 迁移前端资源文件至web目录 feat: 新增多种图标资源 style: 统一代码风格和格式化配置 docs: 更新README和文档说明 chore: 更新依赖和配置文件 fix: 修复部分类型定义和枚举 perf: 优化路由和组件加载逻辑
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import datetime
|
||||
import time
|
||||
import os
|
||||
import shutil
|
||||
import pytest
|
||||
from _pytest.terminal import TerminalReporter
|
||||
import pytest_html
|
||||
import pytest_html.extras
|
||||
from pytest_metadata.plugin import metadata_key
|
||||
import logging
|
||||
|
||||
from config.setting import settings
|
||||
from tools.email_tool import EmailPack
|
||||
from tools.dingding_tool import DingTalkPack
|
||||
from tools.qiwei_tool import QiWeiPack
|
||||
|
||||
# 常量定义
|
||||
TEST_TYPE: str = settings.TEST_TYPE
|
||||
ENVIRONMENT: str = settings.ENVIRONMENT
|
||||
TESTER: str = settings.TESTER
|
||||
|
||||
"""
|
||||
module级别的测试初始化和结果收集
|
||||
class级别的测试初始化和结果收集
|
||||
function级别的测试初始化和结果收集
|
||||
"""
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def init_session():
|
||||
"""会话级别的测试初始化和结果收集"""
|
||||
if TEST_TYPE not in ['API', 'UI']:
|
||||
raise ValueError("请输入正确的自动化测试类型['API','UI']")
|
||||
if settings.DELETE_ON_OFF == 'True':
|
||||
if os.path.exists(settings.REPORT_PATH):
|
||||
shutil.rmtree(settings.REPORT_PATH)
|
||||
logging.info("历史报告数据清理完成")
|
||||
logging.info(f"{settings.BANNER}\n"
|
||||
f"开始执行 {TEST_TYPE} 自动化测试\n"
|
||||
f"测试环境: {ENVIRONMENT}\n"
|
||||
f"测试人员: {TESTER}")
|
||||
yield
|
||||
logging.info(f"========== {TEST_TYPE} 自动化测试结束 ==========")
|
||||
|
||||
def pytest_terminal_summary(terminalreporter: TerminalReporter, exitstatus: int, config: pytest.Config):
|
||||
"""收集终端测试结果"""
|
||||
stats = terminalreporter.stats
|
||||
result = {
|
||||
'total': terminalreporter._numcollected,
|
||||
'pass_num': len(stats.get('passed', [])),
|
||||
'fail_num': len(stats.get('failed', [])),
|
||||
'skip_num': len(stats.get('skipped', [])),
|
||||
'error_num': len(stats.get('error', [])),
|
||||
'rate': f"{((len(stats.get('passed', [])) / terminalreporter._numcollected * 100) if terminalreporter._numcollected else 0):.2f}%",
|
||||
'duration': f'{round(time.time() - terminalreporter._sessionstarttime, 2)}秒',
|
||||
'reprot_url': settings.REPORT_URL,
|
||||
'jenkins_url': settings.JENKINS_URL
|
||||
}
|
||||
|
||||
logging.info(f"总用例数: {result['total']} | 通过: {result['pass_num']}| 失败: {result['fail_num']} | 跳过: {result['skip_num']} | 错误: {result['error_num']} | 成功率: {result['rate']} | 总耗时: {result['duration']}")
|
||||
|
||||
# 发送邮件
|
||||
if settings.EMAIL_ON_OFF:
|
||||
EmailPack(
|
||||
fromaddr=settings.EMAIL_SENDER,
|
||||
password=settings.EMAIL_PASSWORD,
|
||||
toaddrs=[settings.EMAIL_RECEIVER],
|
||||
server_host=settings.EMAIL_SMTP_SERVER,
|
||||
).send_default_email(
|
||||
title=TEST_TYPE,
|
||||
environment=ENVIRONMENT,
|
||||
tester=TESTER,
|
||||
**result
|
||||
)
|
||||
|
||||
# 发送钉钉消息
|
||||
if settings.DINGDING_ON_OFF:
|
||||
DingTalkPack(settings.DINGDING_WEBHOOK, settings.DINGDING_SECRET).send_dingding(
|
||||
title=TEST_TYPE,
|
||||
environment=ENVIRONMENT,
|
||||
tester=TESTER,
|
||||
**result
|
||||
)
|
||||
|
||||
# 发送企业微信消息
|
||||
if settings.QIWEI_ON_OFF:
|
||||
QiWeiPack(settings.WEBHOOK_URL).send_test_report(
|
||||
title=TEST_TYPE,
|
||||
environment=ENVIRONMENT,
|
||||
tester=TESTER,
|
||||
**result
|
||||
)
|
||||
|
||||
def pytest_html_report_title(report):
|
||||
"""设置报告标题"""
|
||||
report.title = f"{TEST_TYPE}自动化测试报告"
|
||||
|
||||
def pytest_configure(config: pytest.Config):
|
||||
"""测试配置"""
|
||||
config.stash[metadata_key].update({
|
||||
"项目名称": f"{TEST_TYPE} 自动化测试",
|
||||
"测试类型": TEST_TYPE,
|
||||
"测试环境": ENVIRONMENT,
|
||||
"测试人员": TESTER,
|
||||
"开始时间": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||||
})
|
||||
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call: pytest.CallInfo):
|
||||
"""处理测试报告"""
|
||||
outcome = yield
|
||||
report: pytest.TestReport = outcome.get_result()
|
||||
|
||||
if report.when == "call" and report.failed:
|
||||
extras = getattr(report, 'extras', [])
|
||||
if os.path.exists(settings.LOG_PATH):
|
||||
extras.append(pytest_html.extras.url(settings.LOG_PATH, name="查看详细日志"))
|
||||
report.extras = extras
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pytest
|
||||
import logging
|
||||
from typing import Dict
|
||||
from config.setting import settings
|
||||
|
||||
from tools.excel_tool import ExcelPack
|
||||
from tools.yaml_tool import YamlPack
|
||||
from tools.manage import Manage
|
||||
|
||||
manage = Manage()
|
||||
excel = ExcelPack(file_name=settings.API_EXCEL_FILE, api_host=settings.ENVIRONMENT_HOST, token=settings.ENVIRONMENT_TOKEN)
|
||||
yaml = YamlPack(yaml_path=settings.API_YAML_PATH, api_host=settings.ENVIRONMENT_HOST, token=settings.ENVIRONMENT_TOKEN)
|
||||
|
||||
|
||||
class TestExcel:
|
||||
|
||||
@pytest.mark.parametrize('case', excel.load_test_cases(), ids=lambda x: x['name'])
|
||||
def test_excel_api(self, case: Dict) -> None:
|
||||
"""Excel数据驱动的API测试类"""
|
||||
logging.info(f"开始执行用例: {case['name']}")
|
||||
|
||||
# 检查是否需要执行
|
||||
if str(case['run']).lower() != 'yes':
|
||||
logging.info(f"跳过用例: {case['name']}")
|
||||
excel.write_to_excel(row=case['row'], result=manage.create_result(case['name'], 'skip'))
|
||||
pytest.skip()
|
||||
|
||||
# 执行测试用例
|
||||
result = manage.execute_test_case(case)
|
||||
|
||||
# 写入结果
|
||||
excel.write_to_excel(row=case['row'], result=result)
|
||||
|
||||
# 断言结果
|
||||
assert result['result'] == 'pass', (
|
||||
f"用例执行失败: {case['name']}\n"
|
||||
f"请求信息: {case['request']}\n"
|
||||
f"期望结果: {case['expected']}\n"
|
||||
f"实际结果: {result['response']}"
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize('case', yaml.load_test_cases(), ids=lambda x: x['name'])
|
||||
def test_yaml_api(self, case: Dict) -> None:
|
||||
"""Yaml数据驱动的API测试类"""
|
||||
logging.info(f"开始执行用例: {case['name']}")
|
||||
|
||||
# 检查是否需要执行
|
||||
if not case['run']:
|
||||
logging.info(f"跳过用例: {case['name']}")
|
||||
pytest.skip()
|
||||
|
||||
# 执行测试用例
|
||||
result = manage.execute_test_case(case)
|
||||
|
||||
# 断言结果
|
||||
assert result['result'] == 'pass', (
|
||||
f"用例执行失败: {case['name']}\n"
|
||||
f"请求信息: {case['request']}\n"
|
||||
f"期望结果: {case['expected']}\n"
|
||||
f"实际结果: {result['response']}"
|
||||
)
|
||||
Reference in New Issue
Block a user