import asyncio
import json
import re
import time
from collections import defaultdict
from datetime import datetime
from typing import List, Any, Callable
from app.core.constructor.case_constructor import TestcaseConstructor
from app.core.constructor.http_constructor import HttpConstructor
from app.core.constructor.python_constructor import PythonConstructor
from app.core.constructor.redis_constructor import RedisConstructor
from app.core.constructor.sql_constructor import SqlConstructor
from app.core.msg.dingtalk import DingTalk
from app.core.msg.mail import Email
from app.core.paramters import parameters_parser
from app.core.render import Render
from app.core.ws_connection_manager import ws_manage
from app.crud.auth.UserDao import UserDao
from app.crud.config.AddressDao import PityGatewayDao
from app.crud.config.EnvironmentDao import EnvironmentDao
from app.crud.config.GConfigDao import GConfigDao
from app.crud.project.ProjectDao import ProjectDao
from app.crud.test_case.TestCaseAssertsDao import TestCaseAssertsDao
from app.crud.test_case.TestCaseDao import TestCaseDao
from app.crud.test_case.TestCaseOutParametersDao import PityTestCaseOutParametersDao
from app.crud.test_case.TestPlan import PityTestPlanDao
from app.crud.test_case.TestReport import TestReportDao
from app.crud.test_case.TestResult import TestResultDao
from app.crud.test_case.TestcaseDataDao import PityTestcaseDataDao
from app.enums.ConstructorEnum import ConstructorType
from app.enums.GconfigEnum import GConfigParserEnum, GconfigType
from app.enums.NoticeEnum import NoticeType
from app.enums.RequestBodyEnum import BodyType
from app.middleware.AsyncHttpClient import AsyncRequest
from app.models.constructor import Constructor
from app.models.out_parameters import PityTestCaseOutParameters
from app.models.project import Project
from app.models.test_case import TestCase
from app.models.test_plan import PityTestPlan
from app.models.testcase_asserts import TestCaseAsserts
from app.utils.case_logger import CaseLog
from app.utils.decorator import case_log, lock
from app.utils.gconfig_parser import StringGConfigParser, JSONGConfigParser, YamlGConfigParser
from app.utils.json_compare import JsonCompare
from app.utils.logger import Log
from config import Config
# construct method mapping
construct_type = {
ConstructorType.testcase: TestcaseConstructor,
ConstructorType.sql: SqlConstructor,
ConstructorType.redis: RedisConstructor,
ConstructorType.py_script: PythonConstructor,
ConstructorType.http: HttpConstructor,
}
# gconfig parser mapping
gconfig_parser = {
GConfigParserEnum.string: StringGConfigParser.get_data,
GConfigParserEnum.json: JSONGConfigParser.get_data,
GConfigParserEnum.yaml: YamlGConfigParser.get_data,
}
class Executor(object):
log = Log("Executor")
el_exp = r"\$\{(.+?)\}"
pattern = re.compile(el_exp)
# 需要替换全局变量的字段
fields = ['url', 'request_headers']
def __init__(self, log: CaseLog = None):
# 这里是一个彩蛋, 奔驰大G LB(括弧1.3T)
self.glb = None
if log is None:
self._logger = CaseLog()
self._main = True
else:
self._logger = log
self._main = False
@property
def logger(self):
return self._logger
@staticmethod
def get_constructor_type(c: Constructor):
return construct_type.get(c.type)
def append(self, content, end=False):
if end:
self.logger.append(content, end)
else:
self.logger.append(content, end)
@case_log
async def parse_gconfig(self, data, type_, env, *fields):
"""
解析全局变量
"""
for f in fields:
await self.parse_field(data, f, GconfigType.text(type_), env)
async def load_testcase_variables(self, data, type_, *fields):
"""load_testcase_variables, include global variables"""
for f in fields:
self.append("解析{}: [{}]中的变量".format(GconfigType.text(type_), data, f))
origin_field = getattr(data, f)
# if not None or ""
if origin_field:
rendered = Render.render(self.glb, origin_field)
if rendered != origin_field:
self.append("替换变量成功, [{}]:\n\n[{}] -> [{}]\n".format(f, origin_field, rendered))
setattr(data, f, rendered)
@case_log
async def query_gconfig(self, env: int):
"""加载全局变量"""
gconfig_list = await GConfigDao.list_gconfig(env)
gconfig_map = dict()
for g in gconfig_list:
parser = Executor.get_parser(g.key_type)
gconfig_map[g.key] = parser(g.value)
self.glb = gconfig_map
@staticmethod
def get_parser(key_type) -> Callable:
"""获取变量解析器
"""
parser = gconfig_parser.get(key_type)
if parser is None:
raise Exception(f"全局变量类型: {key_type}不合法, 请检查!")
return parser
async def parse_field(self, data, field, name, env):
"""
解析字段
"""
try:
self.append("获取{}: [{}]字段: [{}]中的el表达式".format(name, data, field))
field_origin = getattr(data, field)
variables = self.get_el_expression(field_origin)
for v in variables:
key = v.split(".")[0]
cf = await GConfigDao.async_get_gconfig_by_key(key, env)
if cf is not None:
# 解析变量
parse = self.get_parser(cf.key_type)
new_value = parse(cf.value, v)
new_field = field_origin.replace("${%s}" % v, new_value)
setattr(data, field, new_field)
self.append("替换全局变量成功, 字段: [{}]:\n\n[{}] -> [{}]\n".format(field, "${%s}" % v, new_value))
field_origin = new_field
self.append("获取{}字段: [{}]中的el表达式".format(name, field), True)
except Exception as e:
Executor.log.error(f"查询全局变量失败, error: {str(e)}")
raise Exception(f"查询全局变量失败, error: {str(e)}")
def replace_params(self, field_name, field_origin, params: dict):
new_data = dict()
if not isinstance(field_origin, str):
return new_data
variables = self.get_el_expression(field_origin)
for v in variables:
key = v.split(".")
if not params.get(key[0]):
continue
result = params
for branch in key:
if isinstance(result, str):
# 说明需要反序列化
try:
result = json.loads(result)
except Exception as e:
self.append(f"反序列化失败, result: {result}\nERROR: {e}")
break
if branch.isdigit():
# 说明路径里面的是数组
result = result[int(branch)]
else:
result = result.get(branch)
if result is None:
raise Exception(f"变量路径: {v}不存在, 请检查JSON或路径!")
if field_name == "request_headers":
new_value = json.loads(result)
elif not isinstance(result, str):
new_value = json.dumps(result, ensure_ascii=False)
else:
new_value = result
if new_value is None:
self.append("替换变量失败, 找不到对应的数据")
continue
new_data["${%s}" % v] = new_value
return new_data
async def parse_params(self, data: TestCase, params: dict):
self.append("正在替换变量")
try:
for c in data.__table__.col
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
一个持续迭代的开源接口测试平台 (311个子文件)
CNAME 22B
supervisor.conf 5KB
supervisor.conf 1KB
umi.css 56KB
p__Notification.5523d38e.chunk.css 19KB
p__ApiTest__TestCaseDirectory.b6d14dec.chunk.css 7KB
p__Dashboard__Workspace.dad987ae.chunk.css 4KB
umi.45c78013.css 3KB
p__UserInfo.171393de.chunk.css 2KB
p__ApiTest__TestCaseComponent.25b7dbf3.chunk.css 2KB
p__BuildHistory__ReportDetail.27ac4cf3.chunk.css 2KB
p__account__settings__index.aae61f0e.chunk.css 1KB
p__ApiTest__ProjectDetail.b1b644f2.chunk.css 1KB
p__ApiTest__Project.b1b644f2.chunk.css 1KB
p__ApiTest__TestPlan.57951ad3.chunk.css 1KB
p__Tool__SqlOnline.757009a0.chunk.css 1KB
p__Config__GConfig.db2607b7.chunk.css 1KB
p__Manager__UserList.9aa2d129.chunk.css 1KB
p__Config__Environment.9aa2d129.chunk.css 1KB
p__Config__Oss.9aa2d129.chunk.css 1KB
p__BuildHistory__ReportList.9aa2d129.chunk.css 1KB
t__plugin-layout__Layout.74b4118c.chunk.css 966B
p__Statistics.cb349146.chunk.css 458B
p__datafactory__index.ff196a6a.chunk.css 259B
p__Tool__Request.74ec59d8.chunk.css 80B
dockerfile 904B
dev.env 426B
.gitignore 2KB
.gitkeep 0B
pity.fun.har 1.21MB
report.html 12KB
reset_password.html 10KB
404.html 862B
index.html 862B
index.html 394B
favicon.ico 4KB
alembic.ini 3KB
data_driven.jpeg 39KB
umi.a566cfa5.js 1.71MB
7403.40e9fd06.async.js 1.5MB
6912.55c6887f.async.js 984KB
8744.b81f30b0.async.js 915KB
umi.js 619KB
6531.b74d290d.async.js 597KB
5557.755cbfa9.async.js 465KB
2220.aeb8dfe1.async.js 362KB
1691.84310fb9.async.js 285KB
6281.35ef9f47.async.js 152KB
1602.34598cbf.async.js 142KB
1465.ba11a094.async.js 128KB
5611.f24155a2.async.js 101KB
1101.7b969df9.async.js 100KB
6331.bd50adb7.async.js 97KB
6838.22b8ca9c.async.js 94KB
8928.859b0f01.async.js 93KB
6510.4ab6ae27.async.js 89KB
4240.0665442c.async.js 86KB
9683.26bdfd1e.async.js 69KB
2877.bb8f4ff8.async.js 59KB
p__datafactory__index.84aebed5.async.js 59KB
p__ApiTest__TestCaseDirectory.e3920b19.async.js 56KB
9893.e0b40f82.async.js 52KB
p__BuildHistory__ReportDetail.d8106331.async.js 47KB
p__ApiTest__ProjectDetail.0b7e78c9.async.js 47KB
9905.d7b40d8f.async.js 46KB
7258.6a83b674.async.js 44KB
6476.b61e509d.async.js 31KB
p__ApiTest__TestCaseComponent.f8f684c3.async.js 30KB
p__Config__GConfig.a03b2381.async.js 27KB
2759.af6bb2b9.async.js 27KB
5373.eb2a3ba4.async.js 26KB
p__Config__Environment.2553c25c.async.js 26KB
p__Statistics.fe7c2586.async.js 25KB
5418.7f798d62.async.js 25KB
6365.d885839f.async.js 25KB
p__ApiTest__TestPlan.7e209378.async.js 24KB
8131.0ed0df50.async.js 23KB
p__BuildHistory__ReportList.c31fdebf.async.js 23KB
p__UserInfo.a85c1e52.async.js 23KB
3363.7220e618.async.js 21KB
p__ApiTest__Project.a60876a0.async.js 21KB
p__Dashboard__Workspace.a4d8cf1a.async.js 21KB
8325.c084a41d.async.js 20KB
5514.48917ca8.async.js 20KB
p__Manager__UserList.51465a11.async.js 19KB
p__ApiTest__TestCaseRecorder.fdacf720.async.js 19KB
p__Tool__Request.3ed51fa5.async.js 18KB
9847.b08d50f5.async.js 18KB
7763.00bb1f85.async.js 17KB
7612.7b214a1c.async.js 16KB
p__Config__Address.ef0f932b.async.js 15KB
p__Config__Redis.2310c2c5.async.js 15KB
9814.f7d9cca6.async.js 14KB
p__User__Login__index.54f76831.async.js 14KB
9072.e824df32.async.js 13KB
5282.0b1f69c6.async.js 13KB
8045.5d4a4862.async.js 12KB
p__Config__Oss.87d7ab27.async.js 12KB
p__account__settings__index.f426af59.async.js 11KB
9400.559cafa0.async.js 11KB
共 311 条
- 1
- 2
- 3
- 4
资源评论
Java程序员-张凯
- 粉丝: 1w+
- 资源: 7365
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功