删除敏感信息

This commit is contained in:
chenyongzhiaaron 2023-07-04 18:05:35 +08:00
parent ae6cf6eb48
commit 979f2ffdaf
90 changed files with 1569 additions and 7260 deletions

View File

@ -1,3 +0,0 @@
2023-06-30 09:01:03 | ERROR | 发送请求失败: Value for header {BSP_USER_ID: 216684145642752200} must be of type str or bytes, not <class 'int'>
2023-06-30 09:01:25 | ERROR | 发送请求失败: Value for header {projectId: 99000022} must be of type str or bytes, not <class 'int'>
2023-06-30 09:01:34 | ERROR | 发送请求失败: Method cannot contain non-token characters '/IBS/API/IBS-LMS-BASE/WORK-KIND/PAGE/LIST?T=1636702597000&CURRENT=1&SIZE=1000&PROJECTID=99000022&KEY=&SUPPLYID=&STATUS=0&ENABLED=1' (found at least '/')

View File

@ -1,188 +0,0 @@
{
"projectId": "99000022",
"suitability": "",
"avatar": "https://bimuse.bzlrobot.com/bsp/test/opi/document/v1/document/fileStore/viewPicture/6f2a66c24aa8446b8e5b2e828ca17909",
"isTeamLeader": 0,
"name": "张妹春",
"phone": "18188888888",
"workKindCode": "GZ_CGY",
"workKindName": "仓管员",
"isSpec": 0,
"idCard": {
"memberId": "1674348283581112321",
"name": "张妹春",
"cardNo": "230281196910179732",
"sex": "男",
"clan": "土族",
"birthday": "1969-10-17",
"age": 53,
"issuingAuthority": "",
"validityStart": "",
"validityEnd": "",
"address": "香港特别行政区北镇县秀英长春路y座",
"cardFront": "",
"cardEnd": "",
"avatar": ""
},
"supplier": {
"id": "1674345370494054401",
"createTime": "2023-06-29 17:14:14",
"updateTime": "2023-06-29 17:14:14",
"companyName": "测试公司",
"shortName": "",
"companyType": "CONSTRUCTION_UNIT",
"businessLicense": "993101016769636918",
"legalPerson": "张三",
"legalIdcard": "",
"bank": "",
"bankCardNumber": "",
"bankNumber": "",
"projectId": "99000022",
"projectName": "佛山陈村旧改项目",
"companyId": "1674345370041069569",
"entryStatus": 1,
"contractName": "",
"contractUrl": "",
"supplierType": "",
"outsourcerId": "",
"outsourcerName": "",
"inGroup": "0",
"tenantId": "",
"inTime": "2023-06-29 17:13:39",
"outTime": ""
},
"team": {
"id": "1674347643433529346",
"createTime": "2023-06-29 17:23:15",
"updateTime": "2023-06-29 17:23:15",
"name": "铝模",
"teamLibraryId": "1674347643160899585",
"projectId": "99000022",
"supplyId": "1674345370494054401",
"memberId": "",
"memberName": "",
"memberIdcard": "",
"memberPhone": "",
"principal": "",
"principalIdcard": "",
"principalPhone": "",
"status": "0",
"member": null,
"contractName": "",
"contractUrl": "",
"supplier": null
},
"memberInfo": {
"memberId": "1674348283581112321",
"education": "其他",
"political": "其他",
"maritalStatus": "UM",
"emergencyContact1": "KIRA",
"emergencyPhone1": "18222222222",
"emergencyContact2": "",
"emergencyPhone2": ""
},
"laborContractInfo": {
"memberId": "1674348283581112321",
"contractType": "劳动合同",
"singingDate": "",
"validityStart": "",
"validityEnd": "",
"contractAttachment": "",
"contractAttachmentName": "",
"attachments": []
},
"certInfo": {
"createTime": "2023-06-29 17:25:13",
"updateTime": "2023-06-29 17:43:13",
"memberId": "1674348283581112321",
"certName": "注册会计师",
"certNameCode": "",
"validityStart": "2023-06-30",
"validityEnd": "2023-07-01",
"certTypeName": "",
"certTypeCode": "",
"certCategory": "1",
"certNo": "900000000",
"certPhoto": "https://bimuse.bzlrobot.com/bsp/test/opi/document/v1/document/fileStore/viewPicture/4cc4ac79ddda4b7ebdc9ca1d8a1ee38b",
"certPhotoFileName": "一个TCP 连接可以发送多少个HTTP请求.png",
"issuingAuthority": "中国政府"
},
"specialCertInfo": {
"createTime": "2023-06-29 17:25:13",
"updateTime": "2023-06-29 17:43:13",
"memberId": "1674348283581112321",
"certName": "",
"certNameCode": "",
"validityStart": "2023-06-29",
"validityEnd": "",
"certTypeName": "",
"certTypeCode": "",
"certCategory": "2",
"certNo": "",
"certPhoto": "",
"certPhotoFileName": "",
"issuingAuthority": ""
},
"safeTrainingInfo": {
"createTime": "2023-06-29 17:25:13",
"updateTime": "2023-06-29 17:43:13",
"memberId": "1674348283581112321",
"trainingType": "SAFE",
"trainingDate": "2023-06-29",
"trainingPhoto": "https://bimuse.bzlrobot.com/bsp/test/opi/document/v1/document/fileStore/viewPicture/2ef488193b9d4a38bca6aca918ae17ce",
"trainingPhotoFileName": "一等奖-幼儿园公开课-小白鱼过生日.png"
},
"bankCardInfo": {
"memberId": "1674348283581112321",
"bankName": "中国农业银行",
"accountBank": "银行沪杭",
"cardNo": "9092324234",
"cardPhoto": "https://bimuse.bzlrobot.com/bsp/test/opi/document/v1/document/fileStore/viewPicture/7934b54c857a43098e9590a51d5c2a2b",
"cardPhotoFileName": "一个TCP 连接可以发送多少个HTTP请求.png",
"status": 0
},
"healthInfo": {
"createTime": "2023-06-29 17:25:13",
"updateTime": "2023-06-29 17:43:13",
"memberId": "1674348283581112321",
"laborId": "230281196910179732",
"laborName": "张妹春",
"deviceId": "",
"projectId": "99000022",
"healthStatus": "其他",
"height": "180",
"weight": "60",
"bmi": "500",
"systolicPressure": "39",
"diastolicPressure": "500",
"pulse": "187",
"temperature": "40",
"tempvType": "",
"tempvUnit": "",
"glu": "500",
"sao2": "98",
"fatMass": "",
"fatRate": "",
"fatFreeMass": "",
"moistureMass": "",
"moistureRate": "",
"skeletonMass": "",
"muscleMass": "",
"extracellularFluid": "",
"intracellularFluid": "",
"proteinMass": "",
"mineralsMass": "",
"other": "",
"basalMetabolism": "",
"fatAdjust": "",
"muscleAdjust": "",
"isHistory": 0,
"isMajorDiseases": "1",
"isPurchaseInsurance": "0",
"inspectTime": "2023-06-21",
"actionType": "",
"fileName": "一等奖-幼儿园公开课-小白鱼过生日.png",
"filePath": "https://bimuse.bzlrobot.com/bsp/test/opi/document/v1/document/fileStore/viewPicture/b3884269188641ab97c4b80b51e3667a"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\r\n \"account\": \"18127813600\",\r\n \"password\": \"WD6Y0+LJLHXuFaplzUtSCnwktA7KgXCpjCS+OVvIFGTEoz2gbqK2oOOuJUf7ao0m2YYGiGi1pQTMBnkrxIY1cztGYbVp97kvIQwZLN4UhrOAe3h1asY/NLnDwB/byl7agcGv9WI4oy6B1Z93HVHmQiAKn7QqnDgPVITu4jthNc8=\"\r\n}", "raw": "{\r\n \"account\": \"181200\",\r\n \"password\": \"WD6YB1ZhNc8=\"\r\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -42,498 +42,11 @@
"{{url}}" "{{url}}"
], ],
"path": [ "path": [
"bsp",
"test",
"user",
"ugs",
"auth",
"loginByNotBip" "loginByNotBip"
] ]
} }
}, },
"response": [] "response": []
},
{
"name": "获取需求采购列表(默认条件查询-成功)",
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
""
],
"type": "text/javascript"
}
},
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"assert_code\", function () {\r",
" let body = JSON.parse(pm.request.body.raw)\r",
" body_code = body.code\r",
" let res = pm.response.json()\r",
" for (let i of res.data.records) {\r",
" pm.expect(i.orderCode, \"不包含0003\").to.include(body_code)\r",
" }\r",
" let requireId = res.data.records[0].id\r",
" pm.environment.set(\"requireId\", requireId)\r",
"})"
],
"type": "text/javascript"
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "BSP_TOKEN",
"value": "{{bsToken}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"ncCode\": \"\",\r\n \"applyTimeBegin\": \"\",\r\n \"applyTimeEnd\": \"\",\r\n \"applyUserName\": \"\",\r\n \"auditStatus\": \"\",\r\n \"buildingCode\": \"\",\r\n \"code\": \"RE202210270003\",\r\n \"name\": \"\",\r\n \"purchaseType\": \"\",\r\n \"size\": 10,\r\n \"current\": 1,\r\n \"projectId\": \"104966\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{url}}/bsp/test/user/ugs/ibs/api/ibs-material/material/jobRequire/pages?t=1681310676000",
"host": [
"{{url}}"
],
"path": [
"bsp",
"test",
"user",
"ugs",
"ibs",
"api",
"ibs-material",
"material",
"jobRequire",
"pages"
],
"query": [
{
"key": "t",
"value": "1681310676000"
}
]
}
},
"response": []
},
{
"name": "获取请购详情",
"request": {
"method": "GET",
"header": [
{
"key": "BSP_TOKEN",
"value": "aba920e63584c3b1fef3cb4c498bca44",
"type": "text"
}
],
"url": {
"raw": "https://bimdc.bzlrobot.com/bsp/test/user/ugs/ibs/api/ibs-material/material/jobRequire/detail?t=&isEdit=&requireId=5804&projectId=",
"protocol": "https",
"host": [
"bimdc",
"bzlrobot",
"com"
],
"path": [
"bsp",
"test",
"user",
"ugs",
"ibs",
"api",
"ibs-material",
"material",
"jobRequire",
"detail"
],
"query": [
{
"key": "t",
"value": ""
},
{
"key": "isEdit",
"value": ""
},
{
"key": "requireId",
"value": "5804"
},
{
"key": "projectId",
"value": ""
}
]
}
},
"response": []
},
{
"name": "文件上传",
"request": {
"method": "POST",
"header": [
{
"key": "Accept",
"value": "*/*"
},
{
"key": "Accept-Language",
"value": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"
},
{
"key": "Connection",
"value": "keep-alive"
},
{
"key": "Cookie",
"value": "sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221876a7f1e0f1368-09fbff283e5df9-4c657b58-2073600-1876a7f1e10e86%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E5%BC%95%E8%8D%90%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22%24latest_referrer%22%3A%22https%3A%2F%2Flogin.countrygarden.com.cn%2F%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTg3NmE3ZjFlMGYxMzY4LTA5ZmJmZjI4M2U1ZGY5LTRjNjU3YjU4LTIwNzM2MDAtMTg3NmE3ZjFlMTBlODYifQ%3D%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%22%2C%22value%22%3A%22%22%7D%2C%22%24device_id%22%3A%221876a7f1e0f1368-09fbff283e5df9-4c657b58-2073600-1876a7f1e10e86%22%7D; x-access-token=9f576f5f914c6e29584f82e5c5fe9c92"
},
{
"key": "Origin",
"value": "https://bimdc.bzlrobot.com"
},
{
"key": "Sec-Fetch-Dest",
"value": "empty"
},
{
"key": "Sec-Fetch-Mode",
"value": "cors"
},
{
"key": "Sec-Fetch-Site",
"value": "same-origin"
},
{
"key": "User-Agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.0.0"
},
{
"key": "app_token",
"value": "A4C419A561A3404A86A33628A3F681C3"
},
{
"key": "sec-ch-ua",
"value": "\"Not/A)Brand\";v=\"99\", \"Microsoft Edge\";v=\"115\", \"Chromium\";v=\"115\""
},
{
"key": "sec-ch-ua-mobile",
"value": "?0"
},
{
"key": "sec-ch-ua-platform",
"value": "\"Windows\""
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "test.jpeg"
}
]
},
"url": {
"raw": "https://bimdc.bzlrobot.com/bsp/opi/document/v1/document/fileStore/uploadFile",
"protocol": "https",
"host": [
"bimdc",
"bzlrobot",
"com"
],
"path": [
"bsp",
"opi",
"document",
"v1",
"document",
"fileStore",
"uploadFile"
]
}
},
"response": []
},
{
"name": "https://bimdc.bzlrobot.com/bsp/opi/document/v1/document/fileStore/uploadFile",
"request": {
"method": "POST",
"header": [
{
"key": "Accept",
"value": "*/*"
},
{
"key": "Accept-Language",
"value": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"
},
{
"key": "Connection",
"value": "keep-alive"
},
{
"key": "Cookie",
"value": "sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221876a7f1e0f1368-09fbff283e5df9-4c657b58-2073600-1876a7f1e10e86%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E5%BC%95%E8%8D%90%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22%24latest_referrer%22%3A%22https%3A%2F%2Flogin.countrygarden.com.cn%2F%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTg3NmE3ZjFlMGYxMzY4LTA5ZmJmZjI4M2U1ZGY5LTRjNjU3YjU4LTIwNzM2MDAtMTg3NmE3ZjFlMTBlODYifQ%3D%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%22%2C%22value%22%3A%22%22%7D%2C%22%24device_id%22%3A%221876a7f1e0f1368-09fbff283e5df9-4c657b58-2073600-1876a7f1e10e86%22%7D; x-access-token=9f576f5f914c6e29584f82e5c5fe9c92"
},
{
"key": "Origin",
"value": "https://bimdc.bzlrobot.com"
},
{
"key": "Sec-Fetch-Dest",
"value": "empty"
},
{
"key": "Sec-Fetch-Mode",
"value": "cors"
},
{
"key": "Sec-Fetch-Site",
"value": "same-origin"
},
{
"key": "User-Agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.0.0"
},
{
"key": "app_token",
"value": "A4C419A561A3404A86A33628A3F681C3"
},
{
"key": "sec-ch-ua",
"value": "\"Not/A)Brand\";v=\"99\", \"Microsoft Edge\";v=\"115\", \"Chromium\";v=\"115\""
},
{
"key": "sec-ch-ua-mobile",
"value": "?0"
},
{
"key": "sec-ch-ua-platform",
"value": "\"Windows\""
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "/C:/Users/chenyongzhi11/Desktop/微信图片_20221025174254.jpg"
}
]
},
"url": {
"raw": "https://bimdc.bzlrobot.com/bsp/opi/document/v1/document/fileStore/uploadFile",
"protocol": "https",
"host": [
"bimdc",
"bzlrobot",
"com"
],
"path": [
"bsp",
"opi",
"document",
"v1",
"document",
"fileStore",
"uploadFile"
]
}
},
"response": []
},
{
"name": "平台登录",
"event": [
{
"listen": "test",
"script": {
"exec": [
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "username",
"value": "admin",
"type": "text"
},
{
"key": "password",
"value": "3306",
"type": "text"
},
{
"key": "csrfmiddlewaretoken",
"value": "av1VLobtvmrqvvoDRygqIqBr8QOa2ExxzcB1zVpHRKXXvOtoDzhmuLapxdP8uJj7",
"type": "text"
}
]
},
"url": {
"raw": "http://127.0.0.1:8000/index/",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8000",
"path": [
"index",
""
]
}
},
"response": []
},
{
"name": "新增项目",
"request": {
"method": "POST",
"header": [
{
"key": "Cookie",
"value": "sessionid=zjs3ytyud4hh952ongttt6vvx3fihlqv",
"type": "text"
}
],
"body": {
"mode": "urlencoded",
"urlencoded": []
},
"url": {
"raw": "http://127.0.0.1:8000/project/create_project/",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8000",
"path": [
"project",
"create_project",
""
]
}
},
"response": []
},
{
"name": "查询项目列表信息",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://127.0.0.1:8000/project/get_projects/",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8000",
"path": [
"project",
"get_projects",
""
]
}
},
"response": []
},
{
"name": "新增模块",
"request": {
"method": "POST",
"header": [
{
"key": "Cookie",
"value": "sessionid=zjs3ytyud4hh952ongttt6vvx3fihlqv",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "html"
}
}
},
"url": {
"raw": "http://127.0.0.1:8000/module/create_modul/",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8000",
"path": [
"module",
"create_modul",
""
]
}
},
"response": []
},
{
"name": "查询模块列表",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://127.0.0.1:8000/module/get_module/",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8000",
"path": [
"module",
"get_module",
""
]
}
},
"response": []
} }
] ]
} }

View File

@ -14,80 +14,80 @@ import paho.mqtt.client as mqtt
class MQTTClient: class MQTTClient:
def __init__(self, broker_address, topic): def __init__(self, broker_address, topic):
self.broker_address = broker_address self.broker_address = broker_address
self.topic = topic self.topic = topic
def on_connect(self, client, userdata, flags, rc): def on_connect(self, client, userdata, flags, rc):
print("Connected with result code " + str(rc)) print("Connected with result code " + str(rc))
def on_publish(self, client, userdata, mid): def on_publish(self, client, userdata, mid):
print("Message " + str(mid) + " published.") print("Message " + str(mid) + " published.")
def send_message(self, message): def send_message(self, message):
client = mqtt.Client() client = mqtt.Client()
client.on_connect = self.on_connect client.on_connect = self.on_connect
client.on_publish = self.on_publish client.on_publish = self.on_publish
client.connect(self.broker_address) client.connect(self.broker_address)
client.loop_start() client.loop_start()
client.publish(self.topic, json.dumps(message)) client.publish(self.topic, json.dumps(message))
client.loop_stop() client.loop_stop()
msg = { msg = {
"datapoint": [ "datapoint": [
{ {
"value": "492875336", "value": "492875336",
"type": "string", "type": "string",
"index": "0" "index": "0"
}, },
{ {
"value": "2023-04-24T15:48:33.128Z", "value": "2023-04-24T15:48:33.128Z",
"type": "string", "type": "string",
"index": "6" "index": "6"
}, },
{ {
"value": 0, "value": 0,
"type": "byte", "type": "byte",
"index": "7" "index": "7"
}, },
{ {
"value": "11132.00", "value": "11132.00",
"type": "float", "type": "float",
"index": "8" "index": "8"
}, },
{ {
"index": "11", "index": "11",
"type": "string", "type": "string",
"value": "粤EJC5V3" "value": "粤EJC5V3"
}, },
{ {
"index": "12", "index": "12",
"type": "string", "type": "string",
"value": "1" "value": "1"
}, },
{ {
"index": "13", "index": "13",
"type": "string", "type": "string",
"value": "http://192.1.14.19/document/fileStore/viewPicture/08188228a79b42ffa6b32a85f08b38ba" "value": "/08188228a72a85f08b38ba"
}, },
{ {
"index": "14", "index": "14",
"type": "string", "type": "string",
"value": "https://ibs-test.bzlrobot.com/dfs/get?fileName=In-rear-pic.jpg&group=group1&path=M00/0A/4F/CgjLoWDiwteEBoWJAAAAANRLO4A310.jpg" "value": "/CgjLoBoA310.jpg"
}, },
{ {
"index": "18", "index": "18",
"type": "string", "type": "string",
"value": "20230423174821" "value": "20230423174821"
} }
], ],
"from_id": "492875336", "from_id": "492875336",
"msg_id": "1682243313128531625", "msg_id": "1682243313128531625",
"time": "2023-04-23T19:48:33.128Z", "time": "2023-04-23T19:48:33.128Z",
"type": "SYNC" "type": "SYNC"
} }
if __name__ == '__main__': if __name__ == '__main__':
p = sys.argv[0] p = sys.argv[0]
rab = MQTTClient(broker_address='192.2.3.59', topic='weigh/492875336/rtdata') rab = MQTTClient(broker_address='1.2.3.4', topic='9999999')
rab.send_message(msg) rab.send_message(msg)

View File

@ -13,111 +13,111 @@ import pika
class RabbitMQClient: class RabbitMQClient:
def __init__(self, host, queue_name=None, exchange_name=None, exchange_type=None, routing_key=None): def __init__(self, host, queue_name=None, exchange_name=None, exchange_type=None, routing_key=None):
""" """
RabbitMQClient 类的构造函数AMQP 协议默认 RabbitMQClient 类的构造函数AMQP 协议默认
参数 参数
- host: RabbitMQ 服务器的主机地址 - host: RabbitMQ 服务器的主机地址
- queue_name: 队列名称如果指定了该参数则消息将被发送到指定的队列 - queue_name: 队列名称如果指定了该参数则消息将被发送到指定的队列
- exchange_name: 主题交换机名称如果指定了该参数则消息将被发送到指定的主题交换机 - exchange_name: 主题交换机名称如果指定了该参数则消息将被发送到指定的主题交换机
- exchange_type: 主题交换机类型如果指定了 exchange_name 参数则必须指定此参数例如'direct' 'topic' - exchange_type: 主题交换机类型如果指定了 exchange_name 参数则必须指定此参数例如'direct' 'topic'
- routing_key: 路由键如果指定了 exchange_name 参数则必须指定此参数路由键用于将消息路由到特定的队列 - routing_key: 路由键如果指定了 exchange_name 参数则必须指定此参数路由键用于将消息路由到特定的队列
""" """
self.host = host self.host = host
self.queue_name = queue_name self.queue_name = queue_name
self.exchange_name = exchange_name self.exchange_name = exchange_name
self.exchange_type = exchange_type self.exchange_type = exchange_type
self.routing_key = routing_key self.routing_key = routing_key
self.connection = None self.connection = None
self.channel = None self.channel = None
def connect(self): def connect(self):
""" """
连接到 RabbitMQ 服务器并根据需要声明队列和交换机 连接到 RabbitMQ 服务器并根据需要声明队列和交换机
""" """
# 连接到 RabbitMQ 服务器 # 连接到 RabbitMQ 服务器
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.host)) self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.host))
self.channel = self.connection.channel() self.channel = self.connection.channel()
# 如果指定了 exchange_name 参数,则声明主题交换机 # 如果指定了 exchange_name 参数,则声明主题交换机
if self.exchange_name: if self.exchange_name:
self.channel.exchange_declare(exchange=self.exchange_name, exchange_type=self.exchange_type) self.channel.exchange_declare(exchange=self.exchange_name, exchange_type=self.exchange_type)
# 如果指定了 queue_name 参数,则声明队列,并将其绑定到主题交换机上 # 如果指定了 queue_name 参数,则声明队列,并将其绑定到主题交换机上
if self.queue_name: if self.queue_name:
self.channel.queue_declare(queue=self.queue_name) self.channel.queue_declare(queue=self.queue_name)
if self.exchange_name: if self.exchange_name:
self.channel.queue_bind(queue=self.queue_name, exchange=self.exchange_name, self.channel.queue_bind(queue=self.queue_name, exchange=self.exchange_name,
routing_key=self.routing_key) routing_key=self.routing_key)
def send_message(self, message): def send_message(self, message):
""" """
发送一条消息到指定的队列或主题 发送一条消息到指定的队列或主题
参数 参数
- message: 要发送的消息 - message: 要发送的消息
""" """
# 如果指定了 queue_name 参数,则将消息发送到指定的队列 # 如果指定了 queue_name 参数,则将消息发送到指定的队列
if self.queue_name: if self.queue_name:
self.channel.basic_publish(exchange='', routing_key=self.queue_name, body=message) self.channel.basic_publish(exchange='', routing_key=self.queue_name, body=message)
# 如果指定了 exchange_name 参数,则将消息发送到指定的主题交换机 # 如果指定了 exchange_name 参数,则将消息发送到指定的主题交换机
elif self.exchange_name: elif self.exchange_name:
self.channel.basic_publish(exchange=self.exchange_name, routing_key=self.routing_key, self.channel.basic_publish(exchange=self.exchange_name, routing_key=self.routing_key,
body=message) body=message)
def close(self): def close(self):
""" """
关闭与 RabbitMQ 的连接 关闭与 RabbitMQ 的连接
""" """
self.connection.close() self.connection.close()
if __name__ == '__main__': if __name__ == '__main__':
msg = { msg = {
"datapoint": [ "datapoint": [
{ {
"value": "492875336", "value": "492875336",
"type": "string", "type": "string",
"index": "0" "index": "0"
}, },
{ {
"value": "2023-04-23T17:48:33.128Z", "value": "2023-04-23T17:48:33.128Z",
"type": "string", "type": "string",
"index": "6" "index": "6"
}, },
{ {
"value": 0, "value": 0,
"type": "byte", "type": "byte",
"index": "7" "index": "7"
}, },
{ {
"value": "11132.00", "value": "11132.00",
"type": "float", "type": "float",
"index": "8" "index": "8"
}, },
{ {
"index": "11", "index": "11",
"type": "string", "type": "string",
"value": "粤EJC5V3" "value": "粤EJC5V3"
}, },
{ {
"index": "12", "index": "12",
"type": "string", "type": "string",
"value": "1" "value": "1"
}, },
{ {
"index": "18", "index": "18",
"type": "string", "type": "string",
"value": "20230423174821" "value": "20230423174821"
} }
], ],
"from_id": "492875336", "from_id": "492875336",
"msg_id": "1682243313128531625", "msg_id": "1682243313128531625",
"time": "2023-04-23T17:48:33.128Z", "time": "2023-04-23T17:48:33.128Z",
"type": "SYNC" "type": "SYNC"
} }
rab = RabbitMQClient(host='192.1.1.59:1883', exchange_name='/bridge/492/rtdata', rab = RabbitMQClient(host='1.1.1.9:18', exchange_name='/rtdata',
# exchange_type='topic', # exchange_type='topic',
# routing_key='connected' # routing_key='connected'
) )
rab.send_message(json.dumps(msg)) rab.send_message(json.dumps(msg))

View File

@ -3,11 +3,12 @@
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
# Name: bif_datetime.py # Name: bif_datetime.py
# Description: # Description:
# Author: chenyongzhi # Author: kira
# EMAIL: 262667641@qq.com # EMAIL: 262667641@qq.com
# Date: 2021/1/12 14:03 # Date: 2021/1/12 14:03
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
from datetime import datetime, timedelta from datetime import datetime, timedelta
from common.bif_functions import logger from common.bif_functions import logger
__all__ = ['get_current_date', 'get_current_time', 'get_delta_time'] __all__ = ['get_current_date', 'get_current_time', 'get_delta_time']
@ -15,46 +16,46 @@ __all__ = ['get_current_date', 'get_current_time', 'get_delta_time']
@logger.log_decorator() @logger.log_decorator()
def get_current_date(fmt="%Y-%m-%d"): def get_current_date(fmt="%Y-%m-%d"):
""" """
获取当前日期默认格式为%Y-%m-%d 获取当前日期默认格式为%Y-%m-%d
Args: Args:
fmt: 日期格式 fmt: 日期格式
Returns: Returns:
""" """
return datetime.now().strftime(fmt) return datetime.now().strftime(fmt)
@logger.log_decorator() @logger.log_decorator()
def get_current_time(fmt="%Y-%m-%d %H:%M:%S"): def get_current_time(fmt="%Y-%m-%d %H:%M:%S"):
""" """
获取当前时间默认格式为%Y-%m-%d %H:%M:%S 获取当前时间默认格式为%Y-%m-%d %H:%M:%S
Args: Args:
fmt: 时间格式 fmt: 时间格式
Returns: Returns:
""" """
return datetime.now().strftime(fmt) return datetime.now().strftime(fmt)
@logger.log_decorator() @logger.log_decorator()
def get_delta_time(days=0, hours=0, minutes=0, seconds=0, fmt="%Y-%m-%d %H:%M:%S"): def get_delta_time(days=0, hours=0, minutes=0, seconds=0, fmt="%Y-%m-%d %H:%M:%S"):
""" """
获取当前时间指定间隔后的时间 获取当前时间指定间隔后的时间
Args: Args:
days:距离当前时间多少天 days:距离当前时间多少天
hours:距离当前时间多少时 hours:距离当前时间多少时
minutes:距离当前时间多少分 minutes:距离当前时间多少分
seconds: 距离当前时间多少秒 seconds: 距离当前时间多少秒
fmt: 时间格式 fmt: 时间格式
Returns: Returns:
""" """
return (datetime.now() + timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)).strftime(fmt) return (datetime.now() + timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)).strftime(fmt)
if __name__ == '__main__': if __name__ == '__main__':
get_delta_time(4) get_delta_time(4)

View File

@ -16,17 +16,17 @@ from common.bif_functions import logger
@logger.log_decorator() @logger.log_decorator()
def md5_encryption(raw_str, sha_str='', toupper=False): def md5_encryption(raw_str, sha_str='', toupper=False):
""" """
执行md5加密 执行md5加密
Args: Args:
raw_str: 原始字符串 raw_str: 原始字符串
sha_str: md5加密的盐值 sha_str: md5加密的盐值
toupper: 是否将加密后的结果转大写 toupper: 是否将加密后的结果转大写
Returns: 经md5加密后的字符串 Returns: 经md5加密后的字符串
""" """
md5_obj = hashlib.md5(sha_str.encode('utf-8')) md5_obj = hashlib.md5(sha_str.encode('utf-8'))
md5_obj.update(str(raw_str).encode('utf-8')) md5_obj.update(str(raw_str).encode('utf-8'))
encrypted_str = md5_obj.hexdigest().upper() if toupper else md5_obj.hexdigest() encrypted_str = md5_obj.hexdigest().upper() if toupper else md5_obj.hexdigest()
return encrypted_str return encrypted_str

View File

@ -3,7 +3,7 @@
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
# Name: bif_json.py # Name: bif_json.py
# Description: # Description:
# Author: chenyongzhi # Author: kira
# EMAIL: 262667641@qq.com # EMAIL: 262667641@qq.com
# Date: 2021/1/12 14:02 # Date: 2021/1/12 14:02
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
@ -16,25 +16,25 @@ __all__ = ['json_dumps', 'json_loads']
@logger.log_decorator() @logger.log_decorator()
def json_dumps(obj): def json_dumps(obj):
""" """
Serialize ``obj`` to a JSON formatted ``str``. Serialize ``obj`` to a JSON formatted ``str``.
Args: Args:
obj: obj:
Returns: Returns:
""" """
return json.dumps(obj, ensure_ascii=False) return json.dumps(obj, ensure_ascii=False)
@logger.log_decorator() @logger.log_decorator()
def json_loads(obj): def json_loads(obj):
""" """
Deserialize ``obj`` (a ``str``, ``bytes`` or ``bytearray`` instance containing a JSON document) to a Python object. Deserialize ``obj`` (a ``str``, ``bytes`` or ``bytearray`` instance containing a JSON document) to a Python object.
Args: Args:
obj: obj:
Returns: Returns:
""" """
return json.loads(obj) return json.loads(obj)

View File

@ -3,7 +3,7 @@
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
# Name: bif_list.py # Name: bif_list.py
# Description: # Description:
# Author: chenyongzhi # Author: kira
# EMAIL: 262667641@qq.com # EMAIL: 262667641@qq.com
# Date: 2021/1/12 15:15 # Date: 2021/1/12 15:15
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
@ -14,65 +14,65 @@ __all__ = ['list_slice', 'sublist']
@logger.log_decorator() @logger.log_decorator()
def list_slice(obj, index=None, start=None, end=None, step=1): def list_slice(obj, index=None, start=None, end=None, step=1):
""" """
切片方法 切片方法
Args: Args:
obj: obj:
index: 索引 index: 索引
start: 开始索引 start: 开始索引
end: 结束索引不含 end: 结束索引不含
step: 步长 step: 步长
Returns: Returns:
""" """
if isinstance(obj, (str, tuple, list)): if isinstance(obj, (str, tuple, list)):
if index is not None: if index is not None:
try: try:
return obj[index] return obj[index]
except IndexError: except IndexError:
return return
else: else:
return obj[start:end:step] return obj[start:end:step]
return None return None
@logger.log_decorator() @logger.log_decorator()
def sublist(raw_list, start=None, end=None): def sublist(raw_list, start=None, end=None):
""" """
截取子列表 截取子列表
Args: Args:
raw_list: 原始列表 raw_list: 原始列表
start: 字符串开始位置 start: 字符串开始位置
end: 字符串结束位置 end: 字符串结束位置
Returns: 截取的字符串或子列表 Returns: 截取的字符串或子列表
""" """
if isinstance(raw_list, (str, list)) and isinstance(start, (int, str)) and isinstance(end, (int, str)): if isinstance(raw_list, (str, list)) and isinstance(start, (int, str)) and isinstance(end, (int, str)):
try: try:
start = int(start) if isinstance(start, str) and start.isdigit() else start start = int(start) if isinstance(start, str) and start.isdigit() else start
end = int(end) if isinstance(end, str) and end.isdigit() else end end = int(end) if isinstance(end, str) and end.isdigit() else end
if isinstance(raw_list, str): if isinstance(raw_list, str):
return list(raw_list[start:end]) return list(raw_list[start:end])
else: else:
return raw_list[start:end] return raw_list[start:end]
except TypeError: except TypeError:
pass pass
return [] return []
if __name__ == '__main__': if __name__ == '__main__':
# lst = [1, 2, 3, 4, 5] # lst = [1, 2, 3, 4, 5]
# print(list_slice(lst, index=2)) # 3 # print(list_slice(lst, index=2)) # 3
# print(list_slice(lst, start=1, end=4)) # [2, 3, 4] # print(list_slice(lst, start=1, end=4)) # [2, 3, 4]
# print(list_slice(lst, start=1, end=4, step=2)) # [2, 4] # print(list_slice(lst, start=1, end=4, step=2)) # [2, 4]
# print(list_slice(123)) # None # print(list_slice(123)) # None
raw_list = ['a', 'b', 'c', 'd', 'e'] raw_list = ['a', 'b', 'c', 'd', 'e']
print(sublist(raw_list, start=1, end=4)) # ['b', 'c', 'd'] print(sublist(raw_list, start=1, end=4)) # ['b', 'c', 'd']
print(sublist(raw_list, start='1', end='4')) # ['b', 'c', 'd'] print(sublist(raw_list, start='1', end='4')) # ['b', 'c', 'd']
print(sublist(raw_list, start='x', end='4')) # [] print(sublist(raw_list, start='x', end='4')) # []
print(sublist(raw_list, start=1, end=10)) # ['b', 'c', 'd', 'e'] print(sublist(raw_list, start=1, end=10)) # ['b', 'c', 'd', 'e']
print(sublist('abcdef', start=1, end=4)) # ['b', 'c', 'd'] print(sublist('abcdef', start=1, end=4)) # ['b', 'c', 'd']
print(sublist(123, start=1, end=4)) # [] print(sublist(123, start=1, end=4)) # []

View File

@ -3,7 +3,7 @@
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
# Name: bif_random.py # Name: bif_random.py
# Description: # Description:
# Author: chenyongzhi # Author: kira
# EMAIL: 262667641@qq.com # EMAIL: 262667641@qq.com
# Date: 2021/1/12 14:02 # Date: 2021/1/12 14:02
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
@ -17,38 +17,38 @@ __all__ = ['random_choice', 'gen_random_num', 'gen_random_str']
@logger.log_decorator() @logger.log_decorator()
def random_choice(args): def random_choice(args):
""" """
随机选择 随机选择
Args: Args:
args: args:
Returns: Returns:
""" """
return random.choice(args) return random.choice(args)
@logger.log_decorator() @logger.log_decorator()
def gen_random_num(length): def gen_random_num(length):
""" """
随机生成指定长度的数字 随机生成指定长度的数字
Args: Args:
length: 指定长度 length: 指定长度
Returns: Returns:
""" """
return random.randint(int('1' + '0' * (length - 1)), int('9' * length)) return random.randint(int('1' + '0' * (length - 1)), int('9' * length))
@logger.log_decorator() @logger.log_decorator()
def gen_random_str(length): def gen_random_str(length):
""" """
生成指定长度的随机字符串 生成指定长度的随机字符串
Args: Args:
length: 指定长度 length: 指定长度
Returns: Returns:
""" """
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length)) return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))

View File

@ -17,25 +17,25 @@ __all__ = ['regex_extract']
@logger.log_decorator() @logger.log_decorator()
def regex_extract(string, pattern, group=None): def regex_extract(string, pattern, group=None):
""" """
根据正则表达式提取内容 根据正则表达式提取内容
Args: Args:
string: 字符串 string: 字符串
pattern: 正则表达式 pattern: 正则表达式
group: 分组组号 group: 分组组号
Returns: Returns:
""" """
if not isinstance(string, str): if not isinstance(string, str):
string = json.dumps(string, ensure_ascii=False) string = json.dumps(string, ensure_ascii=False)
re_obj = re.search(pattern, string) re_obj = re.search(pattern, string)
result = None result = None
if re_obj: if re_obj:
result = re_obj.group(0) result = re_obj.group(0)
if group: if group:
try: try:
result = re_obj.group(group) result = re_obj.group(group)
except IndexError: except IndexError:
pass pass
return result return result

View File

@ -16,48 +16,48 @@ logger = MyLogger()
@logger.log_decorator() @logger.log_decorator()
def substr(raw_str, start=None, end=None): def substr(raw_str, start=None, end=None):
""" """
截取字符串 截取字符串
Args: Args:
raw_str: 原始字符串 raw_str: 原始字符串
start: 字符串开始位置 start: 字符串开始位置
end: 字符串结束位置 end: 字符串结束位置
Returns: 截取的字符串 Returns: 截取的字符串
""" """
try: try:
start = int(start) if (isinstance(start, str) and start.isdigit()) else start start = int(start) if (isinstance(start, str) and start.isdigit()) else start
end = int(end) if (isinstance(end, str) and end.isdigit()) else end end = int(end) if (isinstance(end, str) and end.isdigit()) else end
return raw_str[start:end] return raw_str[start:end]
except TypeError as e: except TypeError as e:
return '' return ''
@logger.log_decorator() @logger.log_decorator()
def str_join(obj, connector=","): def str_join(obj, connector=","):
""" """
连接任意数量的字符 连接任意数量的字符
Args: Args:
obj: 被连接对象类型listtuple obj: 被连接对象类型listtuple
connector: 连接符 connector: 连接符
Returns: Returns:
""" """
if not isinstance(connector, str): if not isinstance(connector, str):
connector = str(connector) connector = str(connector)
if isinstance(obj, str): if isinstance(obj, str):
return obj return obj
elif isinstance(obj, (list, tuple)): elif isinstance(obj, (list, tuple)):
temp_obj = [] temp_obj = []
for item in obj: for item in obj:
if not isinstance(item, str): if not isinstance(item, str):
item = str(item) item = str(item)
temp_obj.append(item) temp_obj.append(item)
return connector.join(temp_obj) return connector.join(temp_obj)
if __name__ == '__main__': if __name__ == '__main__':
substr() substr()
str_join() str_join()

View File

@ -16,45 +16,47 @@ __all__ = ['get_timestamp', 'ms_fmt_hms']
@logger.log_decorator("错误原因时间戳的长度只能在10到16位之间默认返回长度为13位的时间戳") @logger.log_decorator("错误原因时间戳的长度只能在10到16位之间默认返回长度为13位的时间戳")
def get_timestamp(length=13): def get_timestamp(length=13):
""" """
获取时间戳字符串长度最多为16位默认13位 获取时间戳字符串长度最多为16位默认13位
Args: Returns:
length: 时间戳长度
Args:
Returns: length: 时间戳长度
""" Returns:
if isinstance(length, (int,)) and 10 <= length <= 16:
power = length - 10 """
timestamp = time.time() if isinstance(length, (int,)) and 10 <= length <= 16:
return int(timestamp * 10 ** power) power = length - 10
else: timestamp = time.time()
get_timestamp(13) return int(timestamp * 10 ** power)
else:
get_timestamp(13)
@logger.log_decorator() @logger.log_decorator()
def ms_fmt_hms(ms): def ms_fmt_hms(ms):
""" """
将毫秒转换成 h:m:s.ms格式字符串 将毫秒转换成 h:m:s.ms格式字符串
Args: Args:
ms: ms: 毫秒
Returns: Returns:
""" """
ms = int(ms) ms = int(ms)
sec = ms // 1000 sec = ms // 1000
hour = sec // 3600 hour = sec // 3600
minute = (sec - hour * 3600) // 60 minute = (sec - hour * 3600) // 60
sec = sec % 60 sec = sec % 60
ms = ms % 1000 ms = ms % 1000
hour = str(hour).rjust(2, '0') hour = str(hour).rjust(2, '0')
minute = str(minute).rjust(2, '0') minute = str(minute).rjust(2, '0')
sec = str(sec).rjust(2, '0') sec = str(sec).rjust(2, '0')
ms = str(ms).rjust(2, '0') ms = str(ms).rjust(2, '0')
return f"{hour}:{minute}:{sec}.{ms}" return f"{hour}:{minute}:{sec}.{ms}"
if __name__ == '__main__': if __name__ == '__main__':
get_timestamp() get_timestamp()

View File

@ -1,4 +1,12 @@
# -*- coding: utf-8 -*- # coding: utf-8
# -------------------------------------------------------------------------------
# Name: bif_time.py
# Description:
# Author: kira
# EMAIL: 262667641@qq.com
# Date: 2021/1/12 14:03
# -------------------------------------------------------------------------------
import datetime import datetime
import math import math
import random import random
@ -6,109 +14,109 @@ import random
from faker import Faker from faker import Faker
__all__ = [ __all__ = [
'random_phone', 'random_gps', 'random_phone', 'random_gps',
"random_string", "random_ssn", "random_string", "random_ssn",
"random_email", "random_id_card", "random_email", "random_id_card",
"random_int", "random_male_name", "random_int", "random_male_name",
"random_female_name", "random_current_time" "random_female_name", "random_current_time"
] ]
f = Faker(locale='Zh-CN') f = Faker(locale='Zh-CN')
def random_gps(base_log=None, base_lat=None, radius=None): def random_gps(base_log=None, base_lat=None, radius=None):
""" """
Args: Args:
base_log: base_log:
base_lat: base_lat:
radius: radius:
Returns: Returns:
""" """
radius_in_degrees = radius / 111300 radius_in_degrees = radius / 111300
u = float(random.uniform(0.0, 1.0)) u = float(random.uniform(0.0, 1.0))
v = float(random.uniform(0.0, 1.0)) v = float(random.uniform(0.0, 1.0))
w = radius_in_degrees * math.sqrt(u) w = radius_in_degrees * math.sqrt(u)
t = 2 * math.pi * v t = 2 * math.pi * v
x = w * math.cos(t) x = w * math.cos(t)
y = w * math.sin(t) y = w * math.sin(t)
longitude = y + base_log longitude = y + base_log
latitude = x + base_lat latitude = x + base_lat
# 这里是想保留6位小数点 # 这里是想保留6位小数点
loga = '%.6f' % longitude loga = '%.6f' % longitude
lat = '%.6f' % latitude lat = '%.6f' % latitude
return loga, lat return loga, lat
def random_string(): def random_string():
""" """
:return:随机生成字符串,20 :return:随机生成字符串,20
""" """
return f.pystr() return f.pystr()
def random_ssn(): def random_ssn():
""" """
:return:随机生成省份中 :return:随机生成省份中
""" """
return f.ssn() return f.ssn()
def random_phone(self) -> int: def random_phone(self) -> int:
""" """
:return: 随机生成手机号码 :return: 随机生成手机号码
""" """
return f.phone_number() return f.phone_number()
def random_id_card(self) -> int: def random_id_card(self) -> int:
""" """
:return: 随机生成身份证号码 :return: 随机生成身份证号码
""" """
return f.ssn() return f.ssn()
def random_female_name(self) -> str: def random_female_name(self) -> str:
""" """
:return: 女生姓名 :return: 女生姓名
""" """
return f.name_male() return f.name_male()
def random_male_name(self) -> str: def random_male_name(self) -> str:
""" """
:return: 男生姓名 :return: 男生姓名
""" """
return f.name_female() return f.name_female()
def random_email() -> str: def random_email() -> str:
""" """
:return: 生成邮箱 :return: 生成邮箱
""" """
return f.email() return f.email()
def random_current_time() -> datetime.datetime: def random_current_time() -> datetime.datetime:
""" """
计算当前时间 计算当前时间
:return: :return:
""" """
return datetime.datetime.now() return datetime.datetime.now()
def random_int(): def random_int():
"""随机生成 0 - 9999 的数字""" """随机生成 0 - 9999 的数字"""
return f.random_int() return f.random_int()
if __name__ == '__main__': if __name__ == '__main__':
print(random_current_time()) print(random_current_time())

View File

@ -9,32 +9,37 @@
""" """
from common.crypto import logger from common.crypto import logger
from common.crypto.encryption_rsa import Rsa from common.crypto.encryption_rsa import Rsa
# from common.crypto.encryption_aes import DoAES
from extensions import sign from extensions import sign
@logger.log_decorator() @logger.log_decorator()
class EncryptData: class EncryptData:
def encrypts(self, headers_crypto, headers, request_data_crypto, request_data): """
encryption_methods = { 数据加密入口
"MD5": sign.md5_sign, """
"sha1": sign.sha1_sign,
"rsa": lambda data: Rsa(data).rsa_encrypt() def encrypts(self, headers_crypto, headers, request_data_crypto, request_data):
} encryption_methods = {
"MD5": sign.md5_sign,
if headers_crypto: "sha1": sign.sha1_sign,
encrypt_func = encryption_methods.get(headers_crypto) "rsa": lambda data: Rsa(data).rsa_encrypt()
if encrypt_func: }
try:
headers = encrypt_func(headers) if headers_crypto:
except Exception as e: encrypt_func = encryption_methods.get(headers_crypto)
logger.error(f"{headers_crypto} 加密失败:{e}") if encrypt_func:
try:
if request_data_crypto: headers = encrypt_func(headers)
encrypt_func = encryption_methods.get(request_data_crypto) except Exception as e:
if encrypt_func: logger.error(f"{headers_crypto} 加密失败:{e}")
try:
request_data = encrypt_func(request_data) if request_data_crypto:
except Exception as e: encrypt_func = encryption_methods.get(request_data_crypto)
logger.error(f"{request_data_crypto} 加密失败:{e}") if encrypt_func:
try:
return headers, request_data request_data = encrypt_func(request_data)
except Exception as e:
logger.error(f"{request_data_crypto} 加密失败:{e}")
return headers, request_data

View File

@ -41,7 +41,7 @@ class DoAES:
if __name__ == '__main__': if __name__ == '__main__':
# key = os.urandom(16) #随即产生n个字节的字符串可以作为随机加密key使用 # key = os.urandom(16) #随即产生n个字节的字符串可以作为随机加密key使用
key = '2l4LoWczlWxlMZJAAp5N0g6EygZZd9A6' # 随即产生n个字节的字符串可以作为随机加密key使用 key = '2l4LoWczlWxlMZJAAp5N0g6EygZZd9C6' # 随即产生n个字节的字符串可以作为随机加密key使用
text = '4534' # 需要加密的内容 text = '4534' # 需要加密的内容
aes_test = DoAES(key) aes_test = DoAES(key)
cipher_text = aes_test.encrypt(text) cipher_text = aes_test.encrypt(text)

File diff suppressed because one or more lines are too long

View File

@ -8,10 +8,9 @@
@desc: @desc:
""" """
import hashlib
import base64 import base64
import binascii import binascii
import rsa import hashlib
from pyDes import des, CBC, PAD_PKCS5 from pyDes import des, CBC, PAD_PKCS5
@ -20,117 +19,117 @@ from pyDes import des, CBC, PAD_PKCS5
def bs64_data_encode(st): def bs64_data_encode(st):
""" """
base64 加密 base64 加密
Args: Args:
st: st:
Returns: Returns:
""" """
return base64.b64encode(st.encode("utf-8")) return base64.b64encode(st.encode("utf-8"))
def bs64_data_decode(st): def bs64_data_decode(st):
""" """
base64 解密 base64 解密
Args: Args:
st: st:
Returns: Returns:
""" """
return base64.b64decode(st).decode() return base64.b64decode(st).decode()
def md5(st: str) -> str: def md5(st: str) -> str:
""" """
Args: Args:
st:待加密字符串 st:待加密字符串
Returns: 返回MD5 加密后的字符串 Returns: 返回MD5 加密后的字符串
""" """
md = hashlib.md5() # 创建MD5对象 md = hashlib.md5() # 创建MD5对象
md.update(st.encode(encoding="utf-8")) md.update(st.encode(encoding="utf-8"))
return md.hexdigest() return md.hexdigest()
def sha1_secret_str(st): def sha1_secret_str(st):
""" """
使用sha1加密算法返回str加密后的字符串 使用sha1加密算法返回str加密后的字符串
Args: Args:
st: st:
Returns: Returns:
""" """
sha = hashlib.sha1(st.encode("utf-8")) sha = hashlib.sha1(st.encode("utf-8"))
return sha.hexdigest() return sha.hexdigest()
def sha256_single(st): def sha256_single(st):
""" """
sha256加密 sha256加密
Args: Args:
st: 加密字符串 st: 加密字符串
Returns:加密结果转换为16进制字符串并大写 Returns:加密结果转换为16进制字符串并大写
""" """
sha_obj = hashlib.sha256() sha_obj = hashlib.sha256()
sha_obj.update(st.encode("utf-8")) sha_obj.update(st.encode("utf-8"))
return sha_obj.hexdigest().upper() return sha_obj.hexdigest().upper()
class Des: class Des:
def __init__(self, text, key): def __init__(self, text, key):
self.text = text # 原始字符串 self.text = text # 原始字符串
self.KEY = key # 这个key是固定问开发 self.KEY = key # 这个key是固定问开发
def des_encrypt(self): def des_encrypt(self):
"""DES 加密 """DES 加密
Returns:加密后字符串16进制 Returns:加密后字符串16进制
""" """
secret_key = self.KEY # 密码 secret_key = self.KEY # 密码
iv = secret_key # 偏移 iv = secret_key # 偏移
# secret_key:加密密钥CBC:加密模式iv:偏移, padmode:填充 # secret_key:加密密钥CBC:加密模式iv:偏移, padmode:填充
des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5) des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
# 返回为字节 # 返回为字节
secret_bytes = des_obj.encrypt(self.text.encode("utf-8"), padmode=PAD_PKCS5) secret_bytes = des_obj.encrypt(self.text.encode("utf-8"), padmode=PAD_PKCS5)
# 返回为16进制 # 返回为16进制
return binascii.b2a_hex(secret_bytes) return binascii.b2a_hex(secret_bytes)
def des_decrypt(self): def des_decrypt(self):
""" """
DES 解密 DES 解密
Returns:解密后的字符串 Returns:解密后的字符串
""" """
secret_key = self.KEY secret_key = self.KEY
iv = secret_key iv = secret_key
des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5) des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
decrypt_str = des_obj.decrypt(binascii.a2b_hex(self.text), padmode=PAD_PKCS5) decrypt_str = des_obj.decrypt(binascii.a2b_hex(self.text), padmode=PAD_PKCS5)
return bytes.decode(decrypt_str) # bytes.decode() 将bit转为str return bytes.decode(decrypt_str) # bytes.decode() 将bit转为str
def add_to_16(text: str): def add_to_16(text: str):
""" """
使用空格补足16位数 使用空格补足16位数
Args: Args:
text:源字符串 text:源字符串
Returns:补位后字符串 Returns:补位后字符串
""" """
b_text = text.encode("utf-8") b_text = text.encode("utf-8")
add = 0 add = 0
# 计算需要补的位数 # 计算需要补的位数
if len(b_text) % 16: if len(b_text) % 16:
add = 16 - len(b_text) % 16 add = 16 - len(b_text) % 16
return b_text + b'\0' * add return b_text + b'\0' * add
# class AesEcb: # class AesEcb:
# #

View File

@ -3,7 +3,6 @@
# @Author : kira # @Author : kira
# @Email : 262667641@qq.com # @Email : 262667641@qq.com
# @File : analysis_json.py # @File : analysis_json.py
# @Project : risk_api_project
""" """
接口返回的数据是 列表字典 接口返回的数据是 列表字典
新建两个函数 A B函数 A 处理字典数据被调用后判断传循环嵌套 格式的通过一个 key 获取到被包裹了多层的目标数据 新建两个函数 A B函数 A 处理字典数据被调用后判断传循环嵌套 格式的通过一个 key 获取到被包裹了多层的目标数据

View File

@ -3,7 +3,6 @@
# @Author : kira # @Author : kira
# @Email : 262667641@qq.com # @Email : 262667641@qq.com
# @File : assert_dict.py # @File : assert_dict.py
# @Project : risk_api_project
import sys import sys
sys.path.append("../") sys.path.append("../")
@ -14,103 +13,103 @@ from common.utils.singleton import singleton
@singleton @singleton
class AssertDict(object): class AssertDict(object):
@staticmethod @staticmethod
def is_contain(expect_result, response_result): def is_contain(expect_result, response_result):
""" """
Args: Args:
response_result: response_result:
expect_result: expect_result:
expect_result: expect_result:
""" """
assert expect_result.items() <= response_result.items() assert expect_result.items() <= response_result.items()
@staticmethod @staticmethod
def assert_value(expect_result, response_result): def assert_value(expect_result, response_result):
""" """
:param expect_result: 预期结果 :param expect_result: 预期结果
:param response_result: 响应结果 :param response_result: 响应结果
:return: :return:
""" """
contain_expect_key_dict = [] # 所有预期结果的字典key contain_expect_key_dict = [] # 所有预期结果的字典key
expect_value_list = [] # 所有预期结果的字典value expect_value_list = [] # 所有预期结果的字典value
tmp_list = [] tmp_list = []
need_search_key = [] need_search_key = []
res_list = {} res_list = {}
for key, value in expect_result.items(): for key, value in expect_result.items():
expect_value_list.append(value) expect_value_list.append(value)
need_search_key.append(key) need_search_key.append(key)
for expect_value in need_search_key: for expect_value in need_search_key:
# 接收由预期key在实际响应中的所有值,返回的是一个[] # 接收由预期key在实际响应中的所有值,返回的是一个[]
try: try:
contain_expect_key_dict = (AnalysisJson().get_target_value( contain_expect_key_dict = (AnalysisJson().get_target_value(
expect_value, response_result, tmp_list)) expect_value, response_result, tmp_list))
except Exception as identifier: except Exception as identifier:
print("查找值异常:{}".format(contain_expect_key_dict)) print("查找值异常:{}".format(contain_expect_key_dict))
raise identifier raise identifier
for each_value in expect_value_list: for each_value in expect_value_list:
# 判断是否每一个由预期结果组成的列表中每一个值都存在由预期key组成的实际结果列表中 # 判断是否每一个由预期结果组成的列表中每一个值都存在由预期key组成的实际结果列表中
try: try:
if each_value in contain_expect_key_dict: if each_value in contain_expect_key_dict:
res_list["${}".format(each_value)] = True res_list["${}".format(each_value)] = True
else: else:
res_list["${}".format(each_value)] = False res_list["${}".format(each_value)] = False
except Exception as e: except Exception as e:
print("字典的key异常{}".format(each_value)) print("字典的key异常{}".format(each_value))
raise e raise e
if False in res_list.values(): if False in res_list.values():
flag = 0 flag = 0
else: else:
flag = 1 flag = 1
return flag, res_list return flag, res_list
if __name__ == '__main__': if __name__ == '__main__':
first = { first = {
"data": [{ "data": [{
"saleRatio": "14.29", "saleRatio": "14.29",
"weekDate": "2021-04-15" "weekDate": "2021-04-15"
}, { }, {
"weekDate": "2021-04-16", "weekDate": "2021-04-16",
"saleRatio": "14.29" "saleRatio": "14.29"
}, { }, {
"weekDate": "2021-04-17", "weekDate": "2021-04-17",
"saleRatio": "14.29" "saleRatio": "14.29"
}, { }, {
"weekDate": "2021-04-18", "weekDate": "2021-04-18",
"saleRatio": "14.29" "saleRatio": "14.29"
}, { }, {
"weekDate": "2021-04-19", "weekDate": "2021-04-19",
"saleRatio": "14.29" "saleRatio": "14.29"
}, { }, {
"weekDate": "2021-04-20", "weekDate": "2021-04-20",
"saleRatio": "14.29" "saleRatio": "14.29"
}, { }, {
"weekDate": "2021-04-21", "weekDate": "2021-04-21",
"saleRatio": "14.29" "saleRatio": "14.29"
}], }],
"status": 200 "status": 200
} }
second = {"data": [{ second = {"data": [{
"weekDate": "2021-04-19", "weekDate": "2021-04-19",
"saleRatio": "14.29" "saleRatio": "14.29"
}], "status": 200} }], "status": 200}
expect = { expect = {
"status": "success", "status": "success",
"code": 200, "code": 200,
"message": "OK" "message": "OK"
} }
response = { response = {
"status": "success", "status": "success",
"code": 200, "code": 200,
"message": "OK", "message": "OK",
"data": { "data": {
"id": 123, "id": 123,
"name": "John" "name": "John"
} }
} }
print(AssertDict().assert_value(second, first)) print(AssertDict().assert_value(second, first))
print(AssertDict().assert_value(expect, response)) print(AssertDict().assert_value(expect, response))

View File

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
""" """
Time: 2020/6/1/001 15:29 Time: 2020/6/1/001 15:29
Author: 陈勇志 Author: kira
Email:262667641@qq.com Email:262667641@qq.com
Project:api_project Project:api_project
""" """
@ -15,135 +15,137 @@ from jsonpath_ng import parse
from common.variables import Variables from common.variables import Variables
from common.data_extraction import logger from common.data_extraction import logger
# from common.http_client.http_client import Pyt
REPLACE_DICT = { REPLACE_DICT = {
"null": None, "null": None,
"True": True, "True": True,
"false": False "false": False
} }
# d = Variables()
class DataExtractor(Variables): class DataExtractor(Variables):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
# self.PATTERN = getattr(Variables, "PATTERN") # 预编译正则表达式 @logger.log_decorator("提取参数出现了意想不到的错误!!")
def substitute_data(self, response, regex=None, keys=None, deps=None, jp_dict=None):
@logger.log_decorator("提取参数出现了意想不到的错误!!") """
def substitute_data(self, response, regex=None, keys=None, deps=None, jp_dict=None): 方法接收一个正则表达式 regex 和一个关联参数表 deps用于从接口返回的数据中提取关联参数
""" 它会从接口返回的数据中使用正则表达式 regex 和正则表达式返回结果的键列表 keys 提取数据并将其更新到关联参数表中
方法接收一个正则表达式 regex 和一个关联参数表 deps用于从接口返回的数据中提取关联参数 然后它会使用 subs_deps subs_lists 方法提取更多的关联参数最后它将更新后的关联参数表设置为 Variables 类的静态变量并将其返回
它会从接口返回的数据中使用正则表达式 regex 和正则表达式返回结果的键列表 keys 提取数据并将其更新到关联参数表中 Args:
然后它会使用 subs_deps subs_lists 方法提取更多的关联参数最后它将更新后的关联参数表设置为 Variables 类的静态变量并将其返回 response: 被提取数据对象
Args: regex: 正则表达式 r'"id": (\d+), "name": "(\w+)",'
response: 被提取数据对象 keys: 接收正则表达式返回结果的key ["a", "b"]
regex: 正则表达式 r'"id": (\d+), "name": "(\w+)",' deps: "name=data[0].name;ok=data[0].id;an=data[0].age[3].a"
keys: 接收正则表达式返回结果的key ["a", "b"] jp_dict: jsonpath 提取方式入参{"k": "$.data", "x": "$.data[0].age[3].a"}
deps: "name=data[0].name;ok=data[0].id;an=data[0].age[3].a" Returns:
jp_dict: jsonpath 提取方式入参{"k": "$.data", "x": "$.data[0].age[3].a"} """
Returns:
""" response = response
if not isinstance(response, (dict, str, list)):
response = response logger.error(f"被提取对象非字典、非字符串、非列表不执行jsonpath提取被提取对象: {response}")
if not isinstance(response, (dict, str, list)): return {}
logger.error(f"被提取对象非字典、非字符串、非列表不执行jsonpath提取被提取对象: {response}") if regex and keys:
return {} self.substitute_regex(response, regex, keys)
if regex and keys: response = response if isinstance(response, (dict, list)) else json.loads(response)
self.substitute_regex(response, regex, keys) if deps:
response = response if isinstance(response, (dict, list)) else json.loads(response) self.substitute_route(response, deps)
if deps: if jp_dict:
self.substitute_route(response, deps) self.substitute_jsonpath(response, jp_dict)
if jp_dict:
self.substitute_jsonpath(response, jp_dict) def substitute_regex(self, response, regex, keys):
"""
def substitute_regex(self, response, regex, keys): 方法用于使用正则表达式 regex 和正则表达式返回结果的键列表 keys 从接口返回的数据中提取数据并将其更新到关联参数表中
""" Args:
方法用于使用正则表达式 regex 和正则表达式返回结果的键列表 keys 从接口返回的数据中提取数据并将其更新到关联参数表中 response:
Args: regex: 正则表达式r'"id": (\d+), "name": "(\w+)",'
response: keys:结果键列表["a", "b"],
regex: 正则表达式r'"id": (\d+), "name": "(\w+)",' Returns:
keys:结果键列表["a", "b"],
Returns: """
response = json.dumps(response) if isinstance(response, (dict, list)) else response
""" match = re.search(regex, response)
response = json.dumps(response) if isinstance(response, (dict, list)) else response if not match:
match = re.search(regex, response) return {}
if not match: groups = match.groups()
return {} for i, key in enumerate(keys):
groups = match.groups() try:
for i, key in enumerate(keys): self.update_variable(key, groups[i])
try: except:
self.update_variable(key, groups[i]) self.update_variable(key, None)
except:
self.update_variable(key, None) def substitute_route(self, response, route_str):
"""
def substitute_route(self, response, route_str): 想字典一样取值:name=data[0].name;ok=data[0].id;an=data[0].age
deps_list = re.sub(f"[\r\n]+", "", route_str).split(";") Args:
for dep_item in deps_list: response:
key, value_path = dep_item.split("=") route_str:
value_path_parts = re.findall(r'\w+', value_path)
temp = response Returns:
for part in value_path_parts:
if isinstance(temp, dict): """
temp = temp.get(part) deps_list = re.sub(f"[\r\n]+", "", route_str).split(";")
elif isinstance(temp, list): for dep_item in deps_list:
if part.isdigit(): key, value_path = dep_item.split("=")
index = int(part) value_path_parts = re.findall(r'\w+', value_path)
if index < len(temp): temp = response
temp = temp[index] for part in value_path_parts:
else: if isinstance(temp, dict):
temp = None temp = temp.get(part)
break elif isinstance(temp, list):
else: if part.isdigit():
temp = None index = int(part)
break if index < len(temp):
else: temp = temp[index]
temp = None else:
break temp = None
if isinstance(temp, (dict, list)): break
continue else:
else: temp = None
break break
if temp is not None: else:
self.update_variable(key, temp) temp = None
break
def substitute_jsonpath(self, response, json_path_dict): if isinstance(temp, (dict, list)):
""" continue
jsonpath 提取参数 else:
Args: break
response: 响应结果 if temp is not None:
json_path_dict: {"k": "$.data", "x": "$.data[0].age[3].a"} self.update_variable(key, temp)
Returns: 字符串或者list def substitute_jsonpath(self, response, json_path_dict):
"""
""" jsonpath 提取参数
Args:
json_path_dict = json_path_dict if isinstance(json_path_dict, dict) else json.loads(json_path_dict) response: 响应结果
for key, expression in json_path_dict.items(): json_path_dict: {"k": "$.data", "x": "$.data[0].age[3].a"}
try:
parsed_expression = parse(expression) Returns: 字符串或者list
data = response
# 使用解析器对象进行匹配和提取 """
match = parsed_expression.find(data)
result = [m.value for m in match] json_path_dict = json_path_dict if isinstance(json_path_dict, dict) else json.loads(json_path_dict)
self.update_variable(key, result[0]) if len(result) == 1 else self.update_variable(key, for key, expression in json_path_dict.items():
result) try:
except Exception as e: parsed_expression = parse(expression)
logger.error(f"jsonpath表达式错误'{expression}': {e}") data = response
# 使用解析器对象进行匹配和提取
match = parsed_expression.find(data)
result = [m.value for m in match]
self.update_variable(key, result[0]) if len(result) == 1 else self.update_variable(key,
result)
except Exception as e:
logger.error(f"jsonpath表达式错误'{expression}': {e}")
if __name__ == '__main__': if __name__ == '__main__':
# 测试subs函数 # 测试subs函数
res = '{"code": 1,"data": [{"id": 1, "name": "Alice", "age": [20, 21, 22, {"a": "b"}]}]}' res = '{"code": 1,"data": [{"id": 1, "name": "Alice", "age": [20, 21, 22, {"a": "b"}]}]}'
lists = {"k": "$..code", "x": "$.data[0].age[3].a"} lists = {"k": "$..code", "x": "$.data[0].age[3].a"}
dep_str = "name=data[0].name;ok=data[0].id;an=data[0].age" dep_str = "name=data[0].name;ok=data[0].id;an=data[0].age"
regex_str = r'"id": (\d+), "name": "(\w+)",' regex_str = r'"id": (\d+), "name": "(\w+)",'
regex_key = ["a", "b"] regex_key = ["a", "b"]
t = DataExtractor() t = DataExtractor()
t.substitute_data(res, regex=regex_str, keys=regex_key, deps=dep_str, jp_dict=lists) t.substitute_data(res, regex=regex_str, keys=regex_key, deps=dep_str, jp_dict=lists)
print("-------->res:", t.get_variable()) print("-------->res:", t.get_variable())

View File

@ -3,60 +3,59 @@
# @Author : kira # @Author : kira
# @Email : 262667641@qq.com # @Email : 262667641@qq.com
# @File : dict_get.py # @File : dict_get.py
# @Project : api_project
def dict_get(dic, locators, default=None): def dict_get(dic, locators, default=None):
""" """
以参数形式获取字典中特定的值 以参数形式获取字典中特定的值
:param dic: 输入需要在其中取值的原始字典 <dict> :param dic: 输入需要在其中取值的原始字典 <dict>
:param locators: 输入取值定位器, :['result', 'msg', '-1', 'status'] <list> :param locators: 输入取值定位器, :['result', 'msg', '-1', 'status'] <list>
:param default: 进行取值中报错时所返回的默认值 (default: None) :param default: 进行取值中报错时所返回的默认值 (default: None)
:return: 返回根据参数locators找出的值 :return: 返回根据参数locators找出的值
""" """
if not isinstance(dic, dict) or not isinstance(locators, list): if not isinstance(dic, dict) or not isinstance(locators, list):
return default return default
value = None value = None
for locator in locators: for locator in locators:
if not type(value) in [dict, list] and isinstance(locator, str) and not can_convert_to_int(locator): if not type(value) in [dict, list] and isinstance(locator, str) and not can_convert_to_int(locator):
try: try:
value = dic[locator] value = dic[locator]
except KeyError: except KeyError:
return default return default
continue continue
if isinstance(value, dict): if isinstance(value, dict):
try: try:
value = dict_get(value, [locator]) value = dict_get(value, [locator])
except KeyError: except KeyError:
return default return default
continue continue
if isinstance(value, list) and can_convert_to_int(locator): if isinstance(value, list) and can_convert_to_int(locator):
try: try:
value = value[int(locator)] value = value[int(locator)]
except IndexError: except IndexError:
return default return default
continue continue
return value return value
def can_convert_to_int(input_s): def can_convert_to_int(input_s):
try: try:
int(input_s) int(input_s)
return True return True
except Exception: except Exception:
return False return False
if __name__ == '__main__': if __name__ == '__main__':
# dict_test = {"result": {"code": "110002", "msg": [{'status': 'ok'}, {'status': 'failed'}]}} # dict_test = {"result": {"code": "110002", "msg": [{'status': 'ok'}, {'status': 'failed'}]}}
# result = dict_get(dict_test, ['result', 'msg', '-1', 'status']) # result = dict_get(dict_test, ['result', 'msg', '-1', 'status'])
dict_test = { dict_test = {
"data": {"result": [{"taskId": 1, "taskName": "2020-01-23 调研任务", "taskStatus": 2}], "totalCount": 1, "data": {"result": [{"taskId": 1, "taskName": "2020-01-23 调研任务", "taskStatus": 2}], "totalCount": 1,
"pageSize": 20}, "taskId": 2, "msg": "操作成功!", "status": 200} "pageSize": 20}, "taskId": 2, "msg": "操作成功!", "status": 200}
result = dict_get(dict_test, ['data', 'result', 0, 'taskId']) result = dict_get(dict_test, ['data', 'result', 0, 'taskId'])
print(result) print(result)

View File

@ -8,43 +8,42 @@ from common.database import logger
@logger.log_decorator() @logger.log_decorator()
def execute_sql_files(sql_path, db_config): def execute_sql_files(sql_path, db_config):
""" """
批量执行sql语句 批量执行sql语句
Args: Args:
sql_path:文件夹 sql_path:文件夹
db_config: 数据库配置 db_config: 数据库配置
Returns: Returns:
""" """
connection = pymysql.connect(**db_config) connection = pymysql.connect(**db_config)
try: try:
with connection.cursor() as cur: with connection.cursor() as cur:
# 获取指定目录下的所有SQL文件 # 获取指定目录下的所有SQL文件
sql_files = glob.glob(os.path.join(sql_path, "*.sql")) sql_files = glob.glob(os.path.join(sql_path, "*.sql"))
for file in sql_files: for file in sql_files:
with open(file, "r", encoding="utf-8") as f: with open(file, "r", encoding="utf-8") as f:
sql_statements = f.read().strip().split(";") sql_statements = f.read().strip().split(";")
for sql_statement in sql_statements: for sql_statement in sql_statements:
if sql_statement: if sql_statement:
cur.execute(sql_statement) cur.execute(sql_statement)
connection.commit()
connection.commit()
finally:
finally: connection.close()
connection.close()
if __name__ == '__main__': if __name__ == '__main__':
config = { config = {
"host": "xxxx.xxx.xxx.xx", "host": "xxxx.xxx.xxx.xx",
"port": 3306, "port": 3306,
"database": "db_name", "database": "db_name",
"user": "root", "user": "root",
"password": "xxxx" "password": "xxxx"
} }
execute_sql_files('./sql.sql', config) execute_sql_files('./sql.sql', config)

View File

@ -19,151 +19,144 @@ from common.utils.singleton import singleton
@singleton @singleton
class MysqlClient: class MysqlClient:
def __init__(self, db_config): def __init__(self, db_config):
""" """
初始化连接配置 初始化连接配置
Args: Args:
db_config: 数据库连接配置字典 db_config: 数据库连接配置字典
{ """
"host": "xxxx.xxx.xxx.xx", if not db_config:
"port": 3306, return
"database": "db_name",
"user": "root", try:
"password": "xxxx" self.db_base = db_config if isinstance(db_config, dict) else json.loads(db_config)
} self.pool = PooledDB(creator=pymysql, maxconnections=10, **self.db_base)
""" except Exception as e:
if not db_config: logger.error(f"数据库链接失败: {e}")
return raise
try: @logger.log_decorator()
self.db_base = db_config if isinstance(db_config, dict) else json.loads(db_config) def execute_sql(self, sql):
self.pool = PooledDB(creator=pymysql, maxconnections=10, **self.db_base) """
except Exception as e: 执行 SQL 语句
logger.error(f"数据库链接失败: {e}")
raise Args:
sql: SQL 语句字典
@logger.log_decorator() {
def execute_sql(self, sql): "delete": {
""" "sql_name": "DELETE FROM table_name WHERE condition"
执行 SQL 语句 },
"update": {
Args: "sql_name": "UPDATE table_name SET column1=value1 WHERE condition"
sql: SQL 语句字典 },
{ "insert": {
"delete": { "sql_name": "INSERT INTO table_name (column1, column2) VALUES (value1, value2)"
"sql_name": "DELETE FROM table_name WHERE condition" },
}, "select": {
"update": { "sql_name": "SELECT * FROM table_name WHERE condition"
"sql_name": "UPDATE table_name SET column1=value1 WHERE condition" }
}, }
"insert": {
"sql_name": "INSERT INTO table_name (column1, column2) VALUES (value1, value2)" Returns:
}, 执行结果字典
"select": { {
"sql_name": "SELECT * FROM table_name WHERE condition" "sql_name": [result1, result2, ...]
} }
} """
if not sql:
Returns: return
执行结果字典
{ try:
"sql_name": [result1, result2, ...] conn = self.pool.connection()
} cur = conn.cursor(DictCursor)
"""
if not sql: result = {}
return for method, sql_data in sql.items():
execute_method = getattr(self, f"_execute_{method}", None)
try: if not execute_method:
conn = self.pool.connection() logger.error("sql字典集编写格式不符合规范")
cur = conn.cursor(DictCursor) raise ValueError("Invalid SQL method")
result = {} execute_method(cur, sql_data, result)
for method, sql_data in sql.items():
execute_method = getattr(self, f"_execute_{method}", None) cur.close()
if not execute_method: conn.close()
logger.error("sql字典集编写格式不符合规范")
raise ValueError("Invalid SQL method") return result
execute_method(cur, sql_data, result) except Exception as e:
logger.error(f"数据库操作异常: {e}")
cur.close() raise
conn.close()
def _execute_delete(self, cursor, sql_data, result):
return result """
执行 DELETE 语句
except Exception as e: """
logger.error(f"数据库操作异常: {e}") for sql_name, sql_ in sql_data.items():
raise try:
cursor.execute(str(sql_))
def _execute_delete(self, cursor, sql_data, result): except Exception as err:
""" logger.error(f"执行 SQL 异常: {sql_}")
执行 DELETE 语句 raise err
""" cursor.connection.commit()
for sql_name, sql_ in sql_data.items():
try: def _execute_update(self, cursor, sql_data, result):
cursor.execute(str(sql_)) """
except Exception as err: 执行 UPDATE 语句
logger.error(f"执行 SQL 异常: {sql_}") """
raise err self.execute_delete(cursor, sql_data, result)
cursor.connection.commit()
def _execute_insert(self, cursor, sql_data, result):
def _execute_update(self, cursor, sql_data, result): """
""" 执行 INSERT 语句
执行 UPDATE 语句 """
""" self.execute_delete(cursor, sql_data, result)
self.execute_delete(cursor, sql_data, result)
def _execute_select(self, cursor, sql_data, result):
def _execute_insert(self, cursor, sql_data, result): """
""" 执行 SELECT 语句
执行 INSERT 语句
""" Args:
self.execute_delete(cursor, sql_data, result) cursor: 数据库游标
sql_data: SQL 语句数据字典
def _execute_select(self, cursor, sql_data, result): {
""" "sql_name": "SELECT * FROM table_name WHERE condition"
执行 SELECT 语句 }
result: 字典结果
Args:
cursor: 数据库游标 Raises:
sql_data: SQL 语句数据字典 Exception: 执行异常
{ """
"sql_name": "SELECT * FROM table_name WHERE condition" for sql_name, sql_ in sql_data.items():
} try:
result: 字典结果 cursor.execute(sql_)
result[sql_name] = cursor.fetchall()
Raises: except Exception as err:
Exception: 执行异常 logger.error(f"查询异常 sql: {sql_}")
""" raise err
for sql_name, sql_ in sql_data.items():
try:
cursor.execute(sql_)
result[sql_name] = cursor.fetchall()
except Exception as err:
logger.error(f"查询异常 sql: {sql_}")
raise err
if __name__ == '__main__': if __name__ == '__main__':
sql_2 = { sql_2 = {
"select": "select":
{ {
"select_sale": "select count(1) total, (case when t1.status = 1 then '待整改' when t1.status = 2 then '待复查' when t1.status = 3 then '整改完成' else '未知类型' end) orderStatus from ibs_ai_iot.ai_rectification_main t1 left join ibs_ai_iot.work_order t3 on t1.id = t3.rectification_id where t1.project_id = 103672 and t1.delete_flag = 0 and t3.is_delete = 0 group by t1.status order by orderStatus desc;", "select_sale": "select count(1) total, (case when t1.status = 1 then '待整改' when t1.status = 2 then '待复查' when t1.status = 3 then '整改完成' else '未知类型' end) orderStatus from ibs_ai_iot.ai_rectification_main t1 left join ibs_ai_iot.work_order t3 on t1.id = t3.rectification_id where t1.project_id = 103672 and t1.delete_flag = 0 and t3.is_delete = 0 group by t1.status order by orderStatus desc;",
"select_sale_1": "select count(1) total, (case when t1.status = 1 then '待整改' when t1.status = 2 then '待复查' when t1.status = 3 then '整改完成' else '未知类型' end) orderStatus from ibs_ai_iot.ai_rectification_main t1 left join ibs_ai_iot.work_order t3 on t1.id = t3.rectification_id where t1.project_id = 103672 and t1.delete_flag = 0 and t3.is_delete = 0 group by t1.status order by orderStatus desc;" "select_sale_1": "select count(1) total, (case when t1.status = 1 then '待整改' when t1.status = 2 then '待复查' when t1.status = 3 then '整改完成' else '未知类型' end) orderStatus from ibs_ai_iot.ai_rectification_main t1 left join ibs_ai_iot.work_order t3 on t1.id = t3.rectification_id where t1.project_id = 103672 and t1.delete_flag = 0 and t3.is_delete = 0 group by t1.status order by orderStatus desc;"
} }
} }
database_2 = { database_2 = {
"host": "10.8.203.25", "host": "10.10.10.10",
"port": 3306, "port": 3306,
"database": "ibs_lms_base", "database": "base",
"user": "root", "user": "root",
"password": "gd1234" "password": "roottttttttttttttttttttest"
} }
res = MysqlClient(database_2).execute_sql(sql_2) res = MysqlClient(database_2).execute_sql(sql_2)
print("数据执行结果", res) print("数据执行结果", res)
from common.data_extraction.data_extractor import DataExtractor from common.data_extraction.data_extractor import DataExtractor
from common.variables import Variables from common.variables import Variables
t = DataExtractor() t = DataExtractor()
t.substitute_data(res, jp_dict={"total": "$.select_sale[0].total", "total_1": "$..total"}) t.substitute_data(res, jp_dict={"total": "$.select_sale[0].total", "total_1": "$..total"})
print(Variables.get_variable()) print(Variables.get_variable())

View File

@ -8,83 +8,87 @@ import redis
class RedisClient: class RedisClient:
def __init__(self): """
self.redis = redis.Redis(host='10.8.203.25', port=6379, password='test2020') redis数据库
"""
def set_data(self, key, value, expire_time=None):
self.redis.set(key, value) def __init__(self):
if expire_time is not None: self.redis = redis.Redis(host='1.1.3.5', port=6379, password='test')
self.redis.expire(key, expire_time)
def set_data(self, key, value, expire_time=None):
def get_data(self, key): self.redis.set(key, value)
return self.redis.get(key) if expire_time is not None:
self.redis.expire(key, expire_time)
def delete_data(self, key):
self.redis.delete(key) def get_data(self, key):
return self.redis.get(key)
def hash_set_field(self, key, field, value):
self.redis.hset(key, field, value) def delete_data(self, key):
self.redis.delete(key)
def hash_get_field(self, key, field):
return self.redis.hget(key, field) def hash_set_field(self, key, field, value):
self.redis.hset(key, field, value)
def hash_delete_field(self, key, field):
self.redis.hdel(key, field) def hash_get_field(self, key, field):
return self.redis.hget(key, field)
def hash_delete_field(self, key, field):
self.redis.hdel(key, field)
if __name__ == '__main__': if __name__ == '__main__':
# r = redis.Redis(host='10.8.203.25', port=6379, password='test2020') # r = redis.Redis(host='10.8.203.25', port=6379, password='test2020')
# print(r.select(1)) # 切数据库1 # print(r.select(1)) # 切数据库1
# print(r.dbsize()) # 看 db 大小 # print(r.dbsize()) # 看 db 大小
# #
# # 设置键为"key1"的字符串值为"Hello, Redis!" # # 设置键为"key1"的字符串值为"Hello, Redis!"
# r.set('key1', 'Hello, Redis!') # r.set('key1', 'Hello, Redis!')
# #
# # 获取键为"key1"的字符串值 # # 获取键为"key1"的字符串值
# value = r.get('key1') # value = r.get('key1')
# print(value) # 输出: b'Hello, Redis!' # print(value) # 输出: b'Hello, Redis!'
# #
# # 向名为"list1"的列表左侧插入元素 # # 向名为"list1"的列表左侧插入元素
# r.lpush('list1', 'item1') # r.lpush('list1', 'item1')
# r.lpush('list1', 'item2') # r.lpush('list1', 'item2')
# r.lpush('list1', 'item3') # r.lpush('list1', 'item3')
# #
# # 获取名为"list1"的列表所有元素 # # 获取名为"list1"的列表所有元素
# items = r.lrange('list1', 0, -1) # items = r.lrange('list1', 0, -1)
# print(items) # 输出: [b'item3', b'item2', b'item1'] # print(items) # 输出: [b'item3', b'item2', b'item1']
# #
# # 设置名为"hash1"的哈希表字段和值 # # 设置名为"hash1"的哈希表字段和值
# r.hset('hash1', 'field1', 'value1') # r.hset('hash1', 'field1', 'value1')
# r.hset('hash1', 'field2', 'value2') # r.hset('hash1', 'field2', 'value2')
# #
# # 获取名为"hash1"的哈希表字段和值 # # 获取名为"hash1"的哈希表字段和值
# value1 = r.hget('hash1', 'field1') # value1 = r.hget('hash1', 'field1')
# value2 = r.hget('hash1', 'field2') # value2 = r.hget('hash1', 'field2')
# values = r.hgetall('hash1') # values = r.hgetall('hash1')
# print(value1, value2) # 输出: b'value1' b'value2 # print(value1, value2) # 输出: b'value1' b'value2
# print(values) # 输出:{b'field1': b'value1', b'field2': b'value2'} # print(values) # 输出:{b'field1': b'value1', b'field2': b'value2'}
# #
# # 向名为"set1"的集合添加元素 # # 向名为"set1"的集合添加元素
# r.sadd('set1', 'item1') # r.sadd('set1', 'item1')
# r.sadd('set1', 'item2') # r.sadd('set1', 'item2')
# r.sadd('set1', 'item3') # r.sadd('set1', 'item3')
# #
# # 获取名为"set1"的集合所有元素 # # 获取名为"set1"的集合所有元素
# items = r.smembers('set1') # items = r.smembers('set1')
# print(items) # 输出: {b'item1', b'item2', b'item3'} # print(items) # 输出: {b'item1', b'item2', b'item3'}
redis_client = RedisClient() redis_client = RedisClient()
redis_client.set_data('user1', '100', 3600) redis_client.set_data('user1', '100', 3600)
def get_user_info(user_id): def get_user_info(user_id):
cache_key = f'user1:{user_id}' cache_key = f'user1:{user_id}'
user_info = redis_client.get_data(cache_key) user_info = redis_client.get_data(cache_key)
if not user_info: if not user_info:
print("--") print("--")
print(f'{user_info}') print(f'{user_info}')
get_user_info(100) get_user_info(100)

View File

@ -29,36 +29,10 @@ class DoExcel:
# def __exit__(self, exc_type, exc_val, exc_tb): # def __exit__(self, exc_type, exc_val, exc_tb):
# self.wb.save(self.file_name) # self.wb.save(self.file_name)
# self.wb.close() # self.wb.close()
@logger.log_decorator()
def do_excel(self):
"""
通过 title 定位单元格获取所有测试数据
Returns: 读取每一条测试用用例分别保存到字典中然后再将所有用例保存到列表中[{用例1},{用例2},{用例3}]
[{"":""},{},{}]
"""
sheets = eval(self.get_excel_init().get("sheets"))
test_data = []
for sheet_name in sheets: # 遍历存在配置文件里面的字典sheet_name == 每一个 excel 中的 sheetName
sheet = self.wb[sheet_name] # 获取所有 sheet 句柄
max_row = sheet.max_row # 获取最大行
max_column = sheet.max_column # 获取最大列
fist_header = [] # 获取第一行标题所有值
for i in range(1, max_column + 1):
fist_header.append(sheet.cell(1, i).value)
# 定位单元格
for i in range(2, max_row + 1):
sub_data = {} # 列表内的字典(也就是测试数据)
for k in range(1, max_column + 1):
sub_data[fist_header[k - 1]] = sheet.cell(i, k).value
sub_data["sheet"] = sheet_name
test_data.append(sub_data) # 将所有单元格 title 对应的值组成字典添加到列表中。
return test_data
# @logger.log_decorator()
def do_excel_yield(self): def do_excel_yield(self):
""" """
读取excel数据的生成器 读取excel数据
Returns: Returns:
""" """

View File

@ -8,10 +8,8 @@ import json
import os import os
import sys import sys
# 把当前目录加入到系统环境变量中
sys.path.append(os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]) sys.path.append(os.path.split(os.path.dirname(os.path.abspath(__file__)))[0])
sys.path.append("../..") sys.path.append("../..")
# sys.path.append('venv/Lib/site-packages')
from openpyxl import load_workbook, Workbook from openpyxl import load_workbook, Workbook
from common.file_handling import logger from common.file_handling import logger

View File

@ -16,156 +16,156 @@ import yaml
class FileUtils: class FileUtils:
@staticmethod @staticmethod
def get_all_path(open_file_path): def get_all_path(open_file_path):
""" """
递归获取目录下所有的文件的路径 递归获取目录下所有的文件的路径
Args: Args:
open_file_path: 指定目录路径 open_file_path: 指定目录路径
Returns: Returns:
包含所有文件路径的列表 包含所有文件路径的列表
""" """
path_list = [] path_list = []
for root, dirs, files in os.walk(open_file_path): for root, dirs, files in os.walk(open_file_path):
path_list.extend([os.path.join(root, file) for file in files]) path_list.extend([os.path.join(root, file) for file in files])
return path_list return path_list
@staticmethod @staticmethod
def get_files_in_folder(folder_path): def get_files_in_folder(folder_path):
""" """
获取指定文件夹内的所有文件 获取指定文件夹内的所有文件
Args: Args:
folder_path: 指定文件夹路径 folder_path: 指定文件夹路径
Returns: Returns:
包含所有文件名的列表 包含所有文件名的列表
""" """
if not os.path.isdir(folder_path): if not os.path.isdir(folder_path):
raise ValueError("Invalid folder path") raise ValueError("Invalid folder path")
file_list = [] file_list = []
for filename in os.listdir(folder_path): for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename) file_path = os.path.join(folder_path, filename)
if os.path.isfile(file_path): if os.path.isfile(file_path):
file_list.append(filename) file_list.append(filename)
return file_list return file_list
@staticmethod @staticmethod
def get_folders_in_path(dir_path): def get_folders_in_path(dir_path):
""" """
获取指定路径下的所有文件夹 获取指定路径下的所有文件夹
Args: Args:
dir_path: 指定路径 dir_path: 指定路径
Returns: Returns:
包含所有文件夹名的列表 包含所有文件夹名的列表
""" """
if not os.path.isdir(dir_path): if not os.path.isdir(dir_path):
raise ValueError("Invalid directory path") raise ValueError("Invalid directory path")
folder_list = [] folder_list = []
for foldername in os.listdir(dir_path): for foldername in os.listdir(dir_path):
folder_path = os.path.join(dir_path, foldername) folder_path = os.path.join(dir_path, foldername)
if os.path.isdir(folder_path): if os.path.isdir(folder_path):
folder_list.append(foldername) folder_list.append(foldername)
return folder_list return folder_list
@staticmethod @staticmethod
def read_file(file_path): def read_file(file_path):
""" """
读取文件内容 读取文件内容
Args: Args:
file_path: 文件路径 file_path: 文件路径
Returns: Returns:
文件内容的字符串 文件内容的字符串
""" """
if not os.path.isfile(file_path): if not os.path.isfile(file_path):
raise ValueError("Invalid file path") raise ValueError("Invalid file path")
with open(file_path, "r", encoding="utf-8") as f: with open(file_path, "r", encoding="utf-8") as f:
return f.read() return f.read()
@staticmethod @staticmethod
def read_json_file(file_path): def read_json_file(file_path):
""" """
读取 JSON 文件 读取 JSON 文件
Args: Args:
file_path: JSON 文件路径 file_path: JSON 文件路径
Returns: Returns:
解析后的 JSON 数据 解析后的 JSON 数据
""" """
content = FileUtils.read_file(file_path) content = FileUtils.read_file(file_path)
try: try:
return json.loads(content) return json.loads(content)
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
raise ValueError("Invalid JSON file: {}".format(e)) raise ValueError("Invalid JSON file: {}".format(e))
@staticmethod @staticmethod
def read_yaml_file(file_path): def read_yaml_file(file_path):
""" """
读取 YAML 文件 读取 YAML 文件
Args: Args:
file_path: YAML 文件路径 file_path: YAML 文件路径
Returns: Returns:
解析后的 YAML 数据 解析后的 YAML 数据
""" """
with open(file_path, "r", encoding="utf-8") as f: with open(file_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f) return yaml.safe_load(f)
@staticmethod @staticmethod
def get_value_from_dict(data, key_path): def get_value_from_dict(data, key_path):
""" """
从嵌套字典中获取指定键路径的值 从嵌套字典中获取指定键路径的值
Args: Args:
data: 嵌套字典 data: 嵌套字典
key_path: 键路径可以是用点分隔的字符串或字符串列表 key_path: 键路径可以是用点分隔的字符串或字符串列表
Returns: Returns:
指定键路径的值如果路径不存在则返回 None 指定键路径的值如果路径不存在则返回 None
""" """
if isinstance(key_path, str): if isinstance(key_path, str):
key_path = key_path.split('.') key_path = key_path.split('.')
for key in key_path: for key in key_path:
if isinstance(data, dict) and key in data: if isinstance(data, dict) and key in data:
data = data[key] data = data[key]
else: else:
return None return None
return data return data
@staticmethod @staticmethod
def read_config_data(file_path, section, option): def read_config_data(file_path, section, option):
""" """
读取配置文件中的数据 读取配置文件中的数据
Args: Args:
file_path: 配置文件路径 file_path: 配置文件路径
section: 文件中的 section section: 文件中的 section
option: 文件中的 option option: 文件中的 option
Returns: Returns:
配置文件中指定数据的值 配置文件中指定数据的值
""" """
cf = RawConfigParser() cf = RawConfigParser()
cf.read(file_path, encoding="UTF-8") cf.read(file_path, encoding="UTF-8")
return eval(cf.get(section, option)) return eval(cf.get(section, option))
@staticmethod @staticmethod
def read_json_data(file_path): def read_json_data(file_path):
""" """
读取 JSON 文件中的数据 读取 JSON 文件中的数据
Args: Args:
file_path: JSON 文件路径 file_path: JSON 文件路径
Returns: Returns:
JSON 文件中的数据 JSON 文件中的数据
""" """
with open(file_path, "r", encoding="utf-8") as fb: with open(file_path, "r", encoding="utf-8") as fb:
return json.load(fb) return json.load(fb)
if __name__ == '__main__': if __name__ == '__main__':
fu = FileUtils() fu = FileUtils()
rest = fu.read_yaml_file(r'../../config.yaml') rest = fu.read_yaml_file(r'../../config.yaml')
print(rest) print(rest)

View File

@ -1,37 +0,0 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: get_init.py
@time: 2023/3/16 10:33
@desc:
"""
from common.file_handling.do_excel import DoExcel
from common.utils.logger import MyLog
@MyLog().decorator_log("读取excel中初始化数据异常")
def get_init(test_file):
"""
Returns:返回初始化数据及测试用例
"""
MyLog().my_log(f"读取测试用例excel文件{test_file}", "info")
excel_handle = DoExcel(test_file) # 实例化对象
try:
excel_handle.clear_date() # 清空 excel 中实际结果列的数据
# test_case = excel_handle.do_excel() # 获取 excel 中的测试用例
test_case = excel_handle.do_excel_yield() # 获取 excel 中的测试用例
init_data = excel_handle.get_excel_init() # 获取初始化基本数据
MyLog().my_log(f"如下是初始化得到得数据:{init_data}", "info")
except Exception as e:
raise e
return excel_handle, init_data, test_case
if __name__ == '__main__':
from common.config import Config
init = get_init(Config.test_case)
print(init)

View File

@ -10,90 +10,79 @@ sys.path.append("../")
sys.path.append("./common") sys.path.append("./common")
from common.http_client import logger from common.http_client import logger
# from common.data_extraction.data_extractor import DataExtractor
# from common.data_extraction.dependent_parameter import DependentParameter
from common.validation.load_modules_from_folder import LoadModulesFromFolder from common.validation.load_modules_from_folder import LoadModulesFromFolder
# @singleton
class Pyt(LoadModulesFromFolder): class Pyt(LoadModulesFromFolder):
# 类属性,保存一个会话对象,防止每次都创建一个新的会话,节省资源 # 类属性,保存一个会话对象,防止每次都创建一个新的会话,节省资源
session = requests.Session() session = requests.Session()
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.request = None self.request = None
self.response = None self.response = None
# @staticmethod # @staticmethod
def log_decorator(msg="请求异常"): def log_decorator(msg="请求异常"):
def decorator(func): def decorator(func):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
try: try:
print(f"发送请求的参数: {kwargs}") print(f"发送请求的参数: {kwargs}")
response = func(*args, **kwargs) response = func(*args, **kwargs)
print(f"请求地址 --> {response.request.url}") print(f"请求地址 --> {response.request.url}")
print(f"请求头 --> {response.request.headers}") print(f"请求头 --> {response.request.headers}")
print(f"请求 body --> {response.request.body}") print(f"请求 body --> {response.request.body}")
print(f"接口状态--> {response.status_code}") print(f"接口状态--> {response.status_code}")
print(f"接口耗时--> {response.elapsed}") print(f"接口耗时--> {response.elapsed}")
print(f"接口响应--> {response.text}") print(f"接口响应--> {response.text}")
return response return response
except Exception as e: except Exception as e:
logger.error(f"发送请求失败: {e}") logger.error(f"发送请求失败: {e}")
return return
return wrapper return wrapper
return decorator return decorator
# @log_decorator() # @log_decorator()
def http_client(self, host, url, method, **kwargs): def http_client(self, host, url, method, **kwargs):
""" """
发送 http 请求 发送 http 请求
@param host: 域名 @param host: 域名
@param __url: 接口 __url @param url: 接口 __url
@param method: http 请求方法 @param method: http 请求方法
# @param request_data_type: 请求数据类型 @param kwargs: 接受 requests 原生的关键字参数
# @param headers: 请求头部信息,默认为 None @return: 响应对象
@param kwargs: 接受 requests 原生的关键字参数 """
@return: 响应对象 # 关闭 https 警告信息
""" urllib3.disable_warnings()
# 关闭 https 警告信息
urllib3.disable_warnings() if not url:
raise ValueError("URL cannot be None")
if not url: __url = f'{host}{url}' if not re.match(r"https?", url) else url
raise ValueError("URL cannot be None")
__url = f'{host}{url}' if not re.match(r"https?", url) else url # 增加兼容
# 获取session 中的请求方法 # 处理 headers 参数为字符串类型的情况
# func = getattr(session, method.lower()) if 'headers' in kwargs and isinstance(kwargs['headers'], str):
kwargs['headers'] = json.loads(kwargs['headers'])
# 增加兼容
# 处理 headers 参数为字符串类型的情况 # 处理 json 参数为字符串类型的情况
if 'headers' in kwargs and isinstance(kwargs['headers'], str): if 'json' in kwargs and isinstance(kwargs['json'], str):
kwargs['headers'] = json.loads(kwargs['headers']) kwargs['json'] = json.loads(kwargs['json'])
# 处理 json 参数为字符串类型的情况 # 发送请求
if 'json' in kwargs and isinstance(kwargs['json'], str): self.request = requests.Request(method, __url, **kwargs)
kwargs['json'] = json.loads(kwargs['json']) self.response = self.session.send(self.request.prepare(), timeout=30, verify=True)
# 发送请求 return self.response
# return func(__url, verify=True, timeout=30, **kwargs)
self.request = requests.Request(method, __url, **kwargs)
self.response = self.session.send(self.request.prepare(), timeout=30, verify=True)
return self.response
if __name__ == '__main__': if __name__ == '__main__':
hst = 'https://ibs-test.bzlrobot.com' hst = 'https://baidu.com'
url = '/api/ibs-auth/ibs_platform/login?t=168672334' url = '/login?t=168672334'
method = 'post' method = 'post'
kwargs = { kwargs = {
'json': '{"account": "luoshunwen005", "grantType": "password", "isBip": "false","password": "o+t2SnEEylblxlfIspJUvGFa0gCDNrU2dC34LjVFqIiTmxa855YDBE/6J7eRVBGaQwR7mozSKComk9n6kjSNRjSX1m574dRZdESIeYsmM/xk2Nt5n5dqB268qCMivJMXpHQMygpT4RpDiYoOiEqlOi9eG5G7v/5rixHiZ9xv98m34xVD1VdlaCbphoB9JI7T9HmVFJniSWt01ruC5t+aFUvfxLjOpRmYmfz8GwtSd5XXKaKr29ce1C39Fg+PtqOkQ3cOLVS9hXgzz6s2zud0++T4vwgVtrHx86aMrrozhCdKzrQuWPEO1cSsaEaNVdSUsT54je+4O+xKzxkJhoGMnQ=="}', 'json': '{"account": "kira","password": "9999999"}',
'headers': None} 'headers': None}
pyt = Pyt() pyt = Pyt()
pyt.http_client(hst, url, method, **kwargs) pyt.http_client(hst, url, method, **kwargs)
# print(pyt.request.json)
# print(pyt.request.headers)
# print(pyt.response.text)

View File

@ -1,124 +0,0 @@
# -*- coding: utf-8 -*-
import json
import re
import sys
import requests
import urllib3
sys.path.append("../")
sys.path.append("./common")
from common.http_client import logger
# from common.data_extraction.data_extractor import DataExtractor
# from common.data_extraction.dependent_parameter import DependentParameter
from common.validation.load_modules_from_folder import LoadModulesFromFolder
# @singleton
class Pyt(LoadModulesFromFolder):
# 类属性,保存一个会话对象,防止每次都创建一个新的会话,节省资源
session = requests.Session()
def __init__(self):
super().__init__()
self.request = None
self.response = None
# @staticmethod
def log_decorator(msg="请求异常"):
def decorator(func):
def wrapper(*args, **kwargs):
try:
print(f"发送请求的参数: {kwargs}")
response = func(*args, **kwargs)
print(f"请求地址 --> {response.request.url}")
print(f"请求头 --> {response.request.headers}")
print(f"请求 body --> {response.request.body}")
print(f"接口状态--> {response.status_code}")
print(f"接口耗时--> {response.elapsed}")
print(f"接口响应--> {response.text}")
return response
except Exception as e:
logger.error(f"发送请求失败: {e}")
return
return wrapper
return decorator
def before_request(self, request, **kwargs):
item = kwargs.get("item")
# 拼接动态代码段文件
prepost_script = f"prepost_script_{item.get('sheet')}_{item.get('iid')}.py"
item = self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "setup", item)
# 替换 URL, PARAMETERS, HEADER,期望值
item = self.action.replace_dependent_parameter(item)
url, query_str, request_data, headers, expected, request_data_type = self.__request_info(item)
# 提取请求参数信息
self.action.substitute_data(request_data, jp_dict=jp_dict)
headers, request_data = self.action.encrypt.encrypts(headers_crypto, headers, request_crypto, request_data)
result_tuple = None
result = "PASS"
response = None
# 执行请求操作
kwargs = {
request_data_type: request_data,
'headers': headers
}
# @log_decorator()
def http_client(self, host, url, method, **kwargs):
"""
发送 http 请求
@param host: 域名
@param __url: 接口 __url
@param method: http 请求方法
# @param request_data_type: 请求数据类型
# @param headers: 请求头部信息,默认为 None
@param kwargs: 接受 requests 原生的关键字参数
@return: 响应对象
"""
# 关闭 https 警告信息
urllib3.disable_warnings()
if not url:
raise ValueError("URL cannot be None")
__url = f'{host}{url}' if not re.match(r"https?", url) else url
# 获取session 中的请求方法
# func = getattr(session, method.lower())
# 增加兼容
# 处理 headers 参数为字符串类型的情况
if 'headers' in kwargs and isinstance(kwargs['headers'], str):
kwargs['headers'] = json.loads(kwargs['headers'])
# 处理 json 参数为字符串类型的情况
if 'json' in kwargs and isinstance(kwargs['json'], str):
kwargs['json'] = json.loads(kwargs['json'])
# 发送请求
# return func(__url, verify=True, timeout=30, **kwargs)
self.request = requests.Request(method, __url, **kwargs)
self.response = self.session.send(self.request.prepare(), timeout=30, verify=True)
return self.response
if __name__ == '__main__':
hst = 'https://ibs-test.bzlrobot.com'
url = '/api/ibs-auth/ibs_platform/login?t=168672334'
method = 'post'
kwargs = {
'json': '{"account": "luoshunwen005", "grantType": "password", "isBip": "false","password": "o+t2SnEEylblxlfIspJUvGFa0gCDNrU2dC34LjVFqIiTmxa855YDBE/6J7eRVBGaQwR7mozSKComk9n6kjSNRjSX1m574dRZdESIeYsmM/xk2Nt5n5dqB268qCMivJMXpHQMygpT4RpDiYoOiEqlOi9eG5G7v/5rixHiZ9xv98m34xVD1VdlaCbphoB9JI7T9HmVFJniSWt01ruC5t+aFUvfxLjOpRmYmfz8GwtSd5XXKaKr29ce1C39Fg+PtqOkQ3cOLVS9hXgzz6s2zud0++T4vwgVtrHx86aMrrozhCdKzrQuWPEO1cSsaEaNVdSUsT54je+4O+xKzxkJhoGMnQ=="}',
'headers': None}
pyt = Pyt()
pyt.http_client(hst, url, method, **kwargs)
# print(pyt.request.json)
# print(pyt.request.headers)
# print(pyt.response.text)

View File

@ -1,55 +0,0 @@
import re
import requests
import urllib3
from common.http_client.request_hooks import Hooks
hooks = Hooks()
def req(host, url, method, **kwargs):
"""
发送 http 请求
@param host: 域名
@param url: 接口 url
@param method: http 请求方法
@param kwargs: 接受 requests 原生的关键字参数
@return: 响应对象
"""
# 关闭 https 警告信息
urllib3.disable_warnings()
session = requests.Session()
if not url:
raise ValueError("URL 不能为 None")
url = f'{host}{url}' if not re.match(r"https?", url) else url
# 执行 before_request 钩子函数
request = requests.Request(method, url, **kwargs)
request = hooks.run_before_request_funcs(request)
# 发送请求
prepared_request = session.prepare_request(request)
response = session.send(prepared_request)
# 执行 after_request 钩子函数
response = hooks.run_after_request_funcs(response)
return response
if __name__ == '__main__':
url = "https://ibs-test.bzlrobot.com/api/ibs-auth/ibs_platform/login?t=1686740475000"
payload = {
"grantType": "password",
"account": "luoshunwen005",
"password": "TTdNRuVHxmOI7P8G2yjrfRBaMyQzmy8XGzS1rvbV8X/WqQuJpTAVgTqTAkIswJ0xbGpA2rvoVRnsW3Dg+vmtiJrm/hNUmd7nRV42tMltWDzFAgCC4KOFBC1b+mRkACby+nuiS+N7J6xEAieXJXh6Ml5jWy9qbt2rziteB8npxsMsOygiuRpUmoSkHz8wshQGtqOAr9uQRhglNLJdLWzZtas6TQvypeOMOGSatA2arJ7ipGE3oW+AiATyDu22Eh+PBO+eR7wLWOyO2XxeWhK+5EGiiIVmKRyaMY3JedVHSjpnWmnZ1Vj9pZjUaenJQfCgSS5CBnxLX/AoxB5TvJmMEA==",
"isBip": False
}
headers = {
'Content-Type': 'application/json'
}
kg = {'json': payload, "headers": headers}
res = req("", url, 'post', **kg)
print(res, res.json())

View File

@ -8,7 +8,6 @@ class Hooks:
注册 before_request 钩子函数将其添加到 before_request_funcs 列表中 注册 before_request 钩子函数将其添加到 before_request_funcs 列表中
""" """
self.before_request_funcs.append(func) self.before_request_funcs.append(func)
print(self.before_request_funcs)
return func return func
def after_request(self, func): def after_request(self, func):
@ -16,7 +15,6 @@ class Hooks:
注册 after_request 钩子函数将其添加到 after_request_funcs 列表中 注册 after_request 钩子函数将其添加到 after_request_funcs 列表中
""" """
self.after_request_funcs.append(func) self.after_request_funcs.append(func)
print(self.after_request_funcs)
return func return func
def run_before_request_funcs(self, request): def run_before_request_funcs(self, request):

View File

@ -1,64 +0,0 @@
from common.data_extraction.dependent_parameter import DependentParameter
from common.crypto.encryption_main import do_encrypt
from common.http_client.request_hooks import Hooks
from common.utils.mylogger import MyLogger
dep_par = DependentParameter() # 参数提取类实例化
logger = MyLogger()
hooks = Hooks()
@logger.log_decorator()
@hooks.before_request
def update_url(request):
"""更新url"""
request.url = dep_par.replace_dependent_parameter(request.url)
print(request.url)
return request
@logger.log_decorator()
@hooks.before_request
def update_header(request):
"""更新请求头"""
request.headers = dep_par.replace_dependent_parameter(request.headers)
print(request.headers)
return request
@logger.log_decorator()
@hooks.before_request
def update_body(request):
"""更新请求参数"""
if request.json:
request.json = dep_par.replace_dependent_parameter(request.json)
if request.encryption:
request.data = do_encrypt(request.encryption, request.json) # 数据加密MD5  
else:
request.data = dep_par.replace_dependent_parameter(request.data)
if request.encryption:
request.data = do_encrypt(request.encryption, request.data) # 数据加密MD5  
return request
@logger.log_decorator()
@hooks.before_request
def update_expected(request):
"""更新预期结果"""
request.expected = dep_par.replace_dependent_parameter(request.expected)
print(request.expected)
return request
@logger.log_decorator()
@hooks.after_request
def parse_json(response):
"""
尝试将响应中的内容解析为 JSON 格式
"""
try:
response.json_data = response.json()
except ValueError:
response.json_data = None
return response

View File

@ -23,8 +23,7 @@ class WxWorkSms:
self.send_url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key}" self.send_url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key}"
self.up_url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key={key}&type=file" self.up_url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key={key}&type=file"
def send_markdown(self, project_name, project_port, total_cases, pass_rate, success_cases, fail_cases, def send_markdown(self, project_name, project_port, total_cases, pass_rate, success_cases, fail_cases, skip_cases,
skip_cases,
error_cases, report_url): error_cases, report_url):
""" """
发送markdown 请求 发送markdown 请求
@ -107,4 +106,4 @@ class WxWorkSms:
if __name__ == '__main__': if __name__ == '__main__':
dirs = r'D:\apk_api\api-test-project\OutPut\Reports' dirs = r'D:\apk_api\api-test-project\OutPut\Reports'
WxWorkSms('8b1647d4-dc32-447c-b524-548acf18a938').send_main(dirs, 2, 3, 4, 5, 6, 7, 8, 9, 10) WxWorkSms('8b1647d4-dc32-447c-b524-548acf18a938').send_main(dirs, 2, 3, 4, 5, 6, 7, 8, 9, 10)
# WxWorkSms('8b1647d4-dc32-447c-b524-548acf18a938').send_markdown(1, 2, 3, 4, 5, 6, 7, 8, 9) # WxWorkSms('8b1647d4-dc32-447c-b524-548acf18a938').send_markdown(1, 2, 3, 4, 5, 6, 7, 8, 9)

View File

@ -1,13 +0,0 @@
import time
from functools import wraps
def fn_time(func):
def inner(*args, **kwargs):
t0 = time.time()
func(*args, **kwargs)
t1 = time.time()
print(f"{func.__name__}总共运行:{str(t1 - t0)}")
# return func(*args, **kwargs)
return inner

View File

@ -17,14 +17,15 @@ class ScriptNotFoundError(Exception):
class LoadScript: class LoadScript:
# @logger.log_decorator() # @logger.log_decorator()
def load_script(self, script_path): def load_script(self, script_path):
""" """
加载脚本文件并返回模块对象 加载脚本文件并返回模块对象
Args: Args:
script_path (str): 脚本文件的路径 script_path (str): 脚本文件的路径
Returns: Returns:
module: 脚本文件对应的模块对象 module: 脚本文件对应的模块对象
""" """
try: try:
spec = importlib.util.spec_from_file_location(os.path.basename(script_path), script_path) spec = importlib.util.spec_from_file_location(os.path.basename(script_path), script_path)
@ -33,17 +34,17 @@ class LoadScript:
return script_module return script_module
except FileNotFoundError: except FileNotFoundError:
raise ScriptNotFoundError(script_path) raise ScriptNotFoundError(script_path)
@logger.log_decorator() @logger.log_decorator()
def load_and_execute_script(self, script_directory, script_name, method_name, request): def load_and_execute_script(self, script_directory, script_name, method_name, request):
""" """
加载并执行脚本文件中的指定方法 加载并执行脚本文件中的指定方法
Args: Args:
request: 请求数据 request: 请求数据
script_directory (str): 脚本文件所在的目录 script_directory (str): 脚本文件所在的目录
script_name (str): 脚本文件的名称 script_name (str): 脚本文件的名称
method_name (str): 要执行的方法的名称 method_name (str): 要执行的方法的名称
""" """
script_path = os.path.join(script_directory, script_name) script_path = os.path.join(script_directory, script_name)
try: try:
@ -57,7 +58,7 @@ class LoadScript:
if __name__ == '__main__': if __name__ == '__main__':
from common.config import Config from common.config import Config
SCRIPTS_DIR = Config.SCRIPTS_DIR SCRIPTS_DIR = Config.SCRIPTS_DIR
load_and_exe_s = LoadScript() load_and_exe_s = LoadScript()
load_and_exe_s.load_and_execute_script(SCRIPTS_DIR, 'request_script_sheetname_id.py', 'setup', {"y": "z"}) load_and_exe_s.load_and_execute_script(SCRIPTS_DIR, 'request_script_sheetname_id.py', 'setup', {"y": "z"})

View File

@ -21,7 +21,7 @@ class MyLog:
"error": logging.ERROR, "error": logging.ERROR,
"critic": logging.CRITICAL "critic": logging.CRITICAL
} # 日志级别关系映射 } # 日志级别关系映射
def my_log(self, msg, level="error", when="D", back_count=10): def my_log(self, msg, level="error", when="D", back_count=10):
""" """
实例化 TimeRotatingFileHandler 实例化 TimeRotatingFileHandler
@ -34,10 +34,10 @@ class MyLog:
midnight 每天凌晨 midnight 每天凌晨
""" """
file_name = Config.log_path file_name = Config.log_path
my_logger = logging.getLogger() # 定义日志收集器 my_logger my_logger = logging.getLogger() # 定义日志收集器 my_logger
my_logger.setLevel(self.level_relations.get(level)) # 设置日志级别 my_logger.setLevel(self.level_relations.get(level)) # 设置日志级别
format_str = logging.Formatter( format_str = logging.Formatter(
"%(asctime)s-%(levelname)s-%(filename)s-[ line:%(lineno)d ] - 日志信息:%(message)s") # 设置日志格式 "%(asctime)s-%(levelname)s-%(filename)s-[ line:%(lineno)d ] - 日志信息:%(message)s") # 设置日志格式
# 创建输出渠道 # 创建输出渠道
@ -45,19 +45,16 @@ class MyLog:
sh.setFormatter(format_str) # 设置屏幕上显示的格式 sh.setFormatter(format_str) # 设置屏幕上显示的格式
current = time.strftime("%Y-%m-%d", time.localtime()) # 设置当前日期 current = time.strftime("%Y-%m-%d", time.localtime()) # 设置当前日期
if level == "error": if level == "error":
th = handlers.TimedRotatingFileHandler(filename=f'{file_name}/{current}_{level}.logger', th = handlers.TimedRotatingFileHandler(filename=f'{file_name}/{current}_{level}.logger', when=when,
when=when,
backupCount=back_count, encoding="utf-8") backupCount=back_count, encoding="utf-8")
else: else:
th = handlers.TimedRotatingFileHandler(filename=file_name + "/{}_info.logger".format(current), th = handlers.TimedRotatingFileHandler(filename=file_name + "/{}_info.logger".format(current), when=when,
when=when, backupCount=back_count, encoding="utf-8") # 往文件里写日志
backupCount=back_count,
encoding="utf-8") # 往文件里写日志
th.setFormatter(format_str) # 设置文件里写入的格式 th.setFormatter(format_str) # 设置文件里写入的格式
my_logger.addHandler(sh) # 将对象加入logger里 my_logger.addHandler(sh) # 将对象加入logger里
my_logger.addHandler(th) my_logger.addHandler(th)
if level == "debug": if level == "debug":
my_logger.debug(msg) my_logger.debug(msg)
elif level == "error": elif level == "error":
@ -68,11 +65,11 @@ class MyLog:
my_logger.warning(msg) my_logger.warning(msg)
else: else:
my_logger.critical(msg) my_logger.critical(msg)
my_logger.removeHandler(sh) my_logger.removeHandler(sh)
my_logger.removeHandler(th) my_logger.removeHandler(th)
logging.shutdown() logging.shutdown()
def decorator_log(self, msg=None): def decorator_log(self, msg=None):
def warp(fun): def warp(fun):
def inner(*args, **kwargs): def inner(*args, **kwargs):
@ -80,9 +77,9 @@ class MyLog:
return fun(*args, **kwargs) return fun(*args, **kwargs)
except Exception as e: except Exception as e:
self.my_log(f"{msg}: {e}", "error") self.my_log(f"{msg}: {e}", "error")
return inner return inner
return warp return warp
@ -94,6 +91,6 @@ if __name__ == '__main__':
def add(): def add():
print("试一下") print("试一下")
raise "不好使,异常了。" raise "不好使,异常了。"
add() add()

View File

@ -1,7 +1,5 @@
import json import json
from common.utils import logger
# @logger.log_decorator() # @logger.log_decorator()
def parsing_openapi(file_path): def parsing_openapi(file_path):
@ -13,30 +11,30 @@ def parsing_openapi(file_path):
for path, methods in paths.items(): for path, methods in paths.items():
for method, details in methods.items(): for method, details in methods.items():
test_case = { test_case = {
"id": count, "Id": count,
"name": "openapi", "Name": "openapi",
"description": details.get("summary"), "Description": details.get("summary"),
"Run": "yes", "Run": "yes",
"Time": "0.1", "Time": "0.1",
'method': method, 'Method': method,
'url': path, 'Url': path,
'headers': json.dumps(extract_parameters(details.get('parameters', []), 'header')), 'Headers': json.dumps(extract_parameters(details.get('parameters', []), 'header')),
'Headers是否加密': "", 'Headers Crypto': "",
'params': json.dumps(extract_parameters(details.get('parameters', []), 'query')), 'Query Str': json.dumps(extract_parameters(details.get('parameters', []), 'query')),
'request_data_type': determine_request_type(details.get('requestBody')), 'Request Data Type': determine_request_type(details.get('requestBody')),
'request_data': json.dumps(extract_request_body(details.get('requestBody'))), 'Request Data': json.dumps(extract_request_body(details.get('requestBody'))),
'请求参数是否加密': '', 'Request Data Crypto': '',
'提取请求参数': '', 'Extract Request Data': '',
'Jsonpath': '', 'Jsonpath': '',
'正则表达式': '', 'Regex': '',
'正则变量': '', 'Regex Params List': '',
'绝对路径表达式': '', 'Retrieve Value': '',
'SQL': '', 'SQL': '',
'sql变量': '', 'Sql Params Dict': '',
'预期结果': '', 'Expected': '',
'响应结果': '', 'Response': '',
'断言结果': '', 'Assertion': '',
'报错日志': ''} 'Error Log': ''}
test_cases.append(test_case) test_cases.append(test_case)
count += 1 count += 1
@ -105,3 +103,9 @@ if __name__ == '__main__':
file = f'../../cases/temporary_file/openapi.json' file = f'../../cases/temporary_file/openapi.json'
res = parsing_openapi(file) res = parsing_openapi(file)
print(res) print(res)
from common.file_handling.excel import DoExcel
from common.config import Config
templates = Config.templates # 使用标准模板
ex = DoExcel(templates)
ex.do_main("openapi.xlsx", *res)

View File

@ -8,7 +8,7 @@ result = []
def parsing_postman(path): def parsing_postman(path):
""" """
解析postman到处的json文件 解析postman导出的json文件 转为excel测试用例
Args: Args:
path: path:
@ -29,9 +29,9 @@ def parsing_postman(path):
_parse_api(content=content.get('item')) _parse_api(content=content.get('item'))
elif 'request' in content.keys(): elif 'request' in content.keys():
id_count += 1 id_count += 1
api['id'] = id_count api['Id'] = id_count
api['name'] = 'postman' api['Name'] = 'postman'
api['description'] = content.get('name') api['Description'] = content.get('name')
request = content.get('request') request = content.get('request')
api['Run'] = 'yes' api['Run'] = 'yes'
api['Time'] = 0.5 api['Time'] = 0.5
@ -39,14 +39,12 @@ def parsing_postman(path):
# api请求方法 # api请求方法
api['Method'] = request.get('method', 'GET').upper() api['Method'] = request.get('method', 'GET').upper()
header = request.get('header') header = request.get('header')
header = {item.get('key'): item.get('value') for item in header = {item.get('key'): item.get('value') for item in header} if header else {}
header} if header else {}
auth = request.get('auth') auth = request.get('auth')
if auth: if auth:
auth_type = auth.get('type') auth_type = auth.get('type')
if auth.get(auth_type): if auth.get(auth_type):
auth_value = {item.get('key'): item.get('value') for item in auth_value = {item.get('key'): item.get('value') for item in auth.get(auth_type) if
auth.get(auth_type) if
(item and item.get('key'))} (item and item.get('key'))}
header.update(auth_value) header.update(auth_value)
# api 请求地址 # api 请求地址
@ -63,51 +61,46 @@ def parsing_postman(path):
# [item.get('key') + '=' + (item.get('value') or '') for item in url.get('query') if item]) # [item.get('key') + '=' + (item.get('value') or '') for item in url.get('query') if item])
# api请求头 # api请求头
api['Headers'] = json.dumps(header, ensure_ascii=False) api['Headers'] = json.dumps(header, ensure_ascii=False)
api['Headers是否加密'] = '' api['Headers Crypto'] = ''
api['params'] = '' api['Query Str'] = ''
body = request.get('body') body = request.get('body')
if body: if body:
# api接口请求参数类型 # api接口请求参数类型
request_mode = body.get('mode') request_mode = body.get('mode')
if 'raw' == request_mode: if 'raw' == request_mode:
api['request_data_type'] = 'json' api['Request Data Type'] = 'json'
elif 'formdata' == request_mode: elif 'formdata' == request_mode:
api['request_data_type'] = 'data' api['Request Data Type'] = 'data'
elif 'urlencoded' == request_mode: elif 'urlencoded' == request_mode:
api['request_data_type'] = 'data' api['Request Data Type'] = 'data'
# api接口请求参数 # api接口请求参数
request_data = body.get(request_mode) request_data = body.get(request_mode)
api['Request Data'] = {} api['Request Data'] = {}
if request_data and 'raw' == request_mode: if request_data and 'raw' == request_mode:
api['Request Data'].update( api['Request Data'].update(
json.loads(request_data.replace('\t', '').replace('\n', json.loads(request_data.replace('\t', '').replace('\n', '').replace('\r', '')))
'').replace(
'\r', '')))
elif request_data and 'formdata' == request_mode: elif request_data and 'formdata' == request_mode:
if isinstance(request_data, list): if isinstance(request_data, list):
for item in request_data: for item in request_data:
if item.get("type") == "text": if item.get("type") == "text":
api['Request Data'].update({item.get( api['Request Data'].update({item.get('key'): item.get("value", "")})
'key'): item.get("value", "")})
elif item.get("type") == "file": elif item.get("type") == "file":
api["Request Data"].update({item.get( api["Request Data"].update({item.get('key'): item.get("src", "")})
'key'): item.get("src", "")}) api["Request Data Type"] = "files"
api["request_data_type"] = "files" api["Request Data"] = json.dumps(api["Request Data"], ensure_ascii=False)
api["Request Data"] = json.dumps(api["Request Data"], api['Request Data Crypto'] = ''
ensure_ascii=False) api['Extract Request Data'] = ''
api['请求参数是否加密'] = ''
api['提取请求参数'] = ''
api['Jsonpath'] = '' api['Jsonpath'] = ''
api['正则表达式'] = '' api['Regex'] = ''
api['正则变量'] = '' api['Regex Params List'] = ''
api['绝对路径表达式'] = '' api['Retrieve Value'] = ''
api['SQL'] = '' api['SQL'] = ''
api['sql变量'] = '' api['Sql Params Dict'] = ''
api['预期结果'] = '' api['Expected'] = ''
api['响应结果'] = '' api['Response'] = ''
api['断言结果'] = '' api['Assertion'] = ''
api['报错日志'] = '' api['Error Log'] = ''
result.append(api) result.append(api)
@ -117,7 +110,7 @@ def parsing_postman(path):
if __name__ == '__main__': if __name__ == '__main__':
pat = r'E:\apitest\cases\temporary_file\postman.json' pat = r'..\..\cases\temporary_file\postman.json'
res = parsing_postman(pat) res = parsing_postman(pat)
from common.file_handling.excel import DoExcel from common.file_handling.excel import DoExcel
from common.config import Config from common.config import Config

View File

@ -1,21 +0,0 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: retry.py
@time: 2023/3/15 11:15
@desc:
"""
def retry(func):
"函数重跑"
def run_again(*args, **kwargs):
try:
func(*args, **kwargs)
except:
pass
return run_again

View File

@ -12,12 +12,9 @@ from functools import wraps
def singleton(cls): def singleton(cls):
""" """
单例模式类装饰器
Args: Args:
cls:被装饰类 cls:被装饰类
Returns: Returns:
""" """
instance = {} instance = {}

View File

@ -5,43 +5,44 @@ from dataclasses import dataclass
@dataclass @dataclass
class Variables: class Variables:
variables = {} # 定义依赖表 variables = {} # 定义依赖表
pattern_l = re.compile(r"{{\s*([^}\s]+)\s*}}(?:\[(\d+)\])?") # 预编译正则表达式
PATTERN = re.compile(r"{{(.*?)}}") # 预编译正则表达式 pattern_l = re.compile(r"{{\s*([^}\s]+)\s*}}(?:\[(\d+)\])?")
pattern = re.compile(r'({)') PATTERN = re.compile(r"{{(.*?)}}")
pattern_fun = re.compile(r"{{(\w+\(\))}}") pattern = re.compile(r'({)')
pattern_fun = re.compile(r"{{(\w+\(\))}}")
@classmethod
def update_variable(cls, key, value): @classmethod
"""更新依赖表""" def update_variable(cls, key, value):
cls.variables[f"{{{{{key}}}}}"] = value """更新依赖表"""
cls.variables[f"{{{{{key}}}}}"] = value
@classmethod
def get_variable(cls, key=None): @classmethod
"""获取依赖表 或 依赖表中key对应的值""" def get_variable(cls, key=None):
return cls.variables if not key else cls.variables.get(key) """获取依赖表 或 依赖表中key对应的值"""
return cls.variables if not key else cls.variables.get(key)
@classmethod
def set_variable(cls, value): @classmethod
"""设置依赖表""" def set_variable(cls, value):
cls.variables = value """设置依赖表"""
cls.variables = value
@classmethod
def reset(cls): @classmethod
"""重置""" def reset(cls):
cls.variables.clear() """重置"""
cls.request = None cls.variables.clear()
cls.response = None cls.request = None
cls.response = None
if __name__ == '__main__': if __name__ == '__main__':
from common.file_handling.get_excel_init import get_init # from common.file_handling.get_excel_init import get_init
from common.config import Config from common.config import Config
test_file = Config.test_case test_file = Config.test_case
excel_handle, init_data, test_case = get_init(test_file) # excel_handle, init_data, test_case = get_init(test_file)
initialize_data = eval(init_data.get("initialize_data")) # initialize_data = eval(init_data.get("initialize_data"))
print(initialize_data) # print(initialize_data)
d = Variables # d = Variables
d.set_variable(initialize_data) # 初始化依赖表 # d.set_variable(initialize_data)
print("--------------------->", d.get_variable()) # print("--------------------->", d.get_variable())

View File

@ -1,17 +0,0 @@
# decorator_test.py
def my_decorator(func):
print("Decorator function called.")
def wrapper(*args, **kwargs):
print("Wrapper function called.")
return func(*args, **kwargs)
return wrapper
@my_decorator
def my_function():
print("Original function called.")
# print("Module imported.")

View File

@ -1,35 +0,0 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: depr.py
@time: 2023/6/19 17:51
@desc:
"""
import requests
from common.database.redis_client import RedisClient
redis_client = RedisClient()
# 第一个接口,设置依赖数据
def first_api():
response = requests.get('https://api.example.com/first')
data = response.json()
redis_client.set_data('key', data['value'])
def second_api():
# 获取依赖数据
dependency_data = redis_client.get_data('key')
response = requests.post('https://api.example.com/second', data={'data': dependency_data})
result = response.json()
# 处理接口响应结果
if __name__ == '__main__':
first_api()
second_api()

View File

@ -1,38 +0,0 @@
import gc
# 引用计数示例
# a = [1, 2, 3]
# b = a
# print(sys.getrefcount(a)-1) # 输出2a和b都引用了该对象
# b = None
# print(sys.getrefcount(a)-1) # 输出1只有a引用了该对象
#
# # 标记-清除算法示例
class Node:
def __init__(self):
self.next = None
node1 = Node()
node2 = Node()
node1.next = node2
node2.next = node1
res = gc.collect() # 执行垃圾回收,循环引用的对象会被清除
# # 分代回收示例
# a = [1, 2, 3]
# gc.collect()
# print(gc.get_count()) # 输出(0, 0, 0)第0代对象计数为1
# b = [4, 5, 6]
# c = [7, 8, 9]
# gc.collect()
# print(gc.get_count()) # 输出(1, 0, 0)第0代对象计数为0第1代对象计数为2
# d = [10, 11, 12]
# e = [13, 14, 15]
# gc.collect()
# print(gc.get_count()) # 输出(2, 0, 0)第0代对象计数为0第1代对象计数为0第2代对象计数为2
#
# # 对象的代信息
# print(gc.get_objects()) # 输出对象的代信息

View File

@ -1,16 +0,0 @@
def sum(x, y):
return x + y
def generate():
for i in range(4):
yield i
res = generate()
for n in [0, 1, 2, 3]:
base =(sum(i, n) for i in res)
print(base)

View File

@ -1,59 +0,0 @@
# !/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: rt.py
@time: 2023/6/19 17:15
@desc:
"""
import concurrent.futures
import requests
from common.database.redis_client import RedisClient
# 创建 Redis 客户端
redis_client = RedisClient()
def get_user_info(user_id):
cache_key = f'user:{user_id}'
user_info = redis_client.get_data(cache_key)
if not user_info:
# 调用接口获取用户信息
response = requests.get(f'http://127.0.0.1:5000/?user_id={user_id}')
if response.status_code == 200:
user_info = response.text
print(user_info)
redis_client.set_data(cache_key, user_info, expire_time=3600)
else:
print(f"Failed to retrieve user info for user_id: {user_id}. Status code: {response.status_code}")
return user_info
# 并发测试函数
def run_concurrent_test(user_ids):
with concurrent.futures.ThreadPoolExecutor() as executor:
# 提交任务到线程池
future_to_user_id = {executor.submit(get_user_info, user_id): user_id for user_id in user_ids}
# 处理返回结果
for future in concurrent.futures.as_completed(future_to_user_id):
user_id = future_to_user_id[future]
try:
user_info = future.result()
print(f"user_id: {user_id}; user_info: {user_info}")
except Exception as e:
print(f"Error occurred for user_id: {user_id}, Error: {str(e)}")
if __name__ == '__main__':
u_ids = [i for i in range(10, 99)]
run_concurrent_test(u_ids)
# u_ids = [i for i in range(1000, 99999)]
# for i in u_ids:
# response = requests.get(f'http://127.0.0.1:5000/?user_id={i}')
# print(response.text)

View File

@ -1,39 +0,0 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: test_single_class.py
@time: 2023/6/21 17:03
@desc:
"""
from functools import wraps
def single(cls):
instance = {}
@wraps(cls)
def decortator(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return decortator
class A:
pass
@single
class B(A):
pass
class C(B):
pass
if __name__ == '__main__':
C()

View File

@ -2,8 +2,8 @@ import os.path
from common.config import Config from common.config import Config
from common.file_handling.excel import DoExcel from common.file_handling.excel import DoExcel
from common.utils.parsing_postman import parsing_postman
from common.utils.parsing_openapi import parsing_openapi from common.utils.parsing_openapi import parsing_openapi
from common.utils.parsing_postman import parsing_postman
class ExcelConverter: class ExcelConverter:
@ -37,10 +37,8 @@ class ExcelConverter:
if __name__ == '__main__': if __name__ == '__main__':
postman_to_json = r'.\data\temporary_file\postman.json' # postman导出的json文件 postman_to_json = r'.\data\temporary_file\postman.json' # postman导出的json文件
postman_out_file = os.path.join(Config.base_path, 'cases', 'test_cases', postman_out_file = os.path.join(Config.base_path, 'cases', 'test_cases', 'test_postman_cases.xlsx') # 转化后的文件保存的位置
'test_postman_cases.xlsx') # 转化后的文件保存的位置
openapi_to_json = r'.\data\temporary_file\openapi.json' # postman导出的json文件 openapi_to_json = r'.\data\temporary_file\openapi.json' # postman导出的json文件
openapi_out_file = os.path.join(Config.base_path, 'cases', 'test_cases', openapi_out_file = os.path.join(Config.base_path, 'cases', 'test_cases', 'test_openapi_cases.xlsx') # 转化后的文件保存的位置
'test_openapi_cases.xlsx') # 转化后的文件保存的位置
ExcelConverter('postman', postman_to_json, postman_out_file).main() ExcelConverter('postman', postman_to_json, postman_out_file).main()
ExcelConverter('postman', openapi_to_json, openapi_out_file).main() ExcelConverter('postman', openapi_to_json, openapi_out_file).main()

View File

@ -11,5 +11,7 @@
__all__ = ["online_function"] __all__ = ["online_function"]
# 用户自定义扩展函数文件。
def online_function(): def online_function():
pass pass

View File

@ -20,45 +20,45 @@ from extensions import logger
@logger.log_decorator() @logger.log_decorator()
def md5_sign(data: dict): def md5_sign(data: dict):
""" """
数据加签 数据加签
Args: Args:
**data:需要加钱的数据 **data:需要加钱的数据
Returns: Returns:
""" """
sorted_list = [] sorted_list = []
for key, value in data.items(): for key, value in data.items():
try: try:
sorted_params = str(key) + str(value) sorted_params = str(key) + str(value)
sorted_list.append(sorted_params) sorted_list.append(sorted_params)
except Exception: except Exception:
raise raise
sort = natsorted(sorted_list) # 列表自然排序 sort = natsorted(sorted_list) # 列表自然排序
argument = "加签所需要的密钥" argument = "加签所需要的密钥"
keystore = argument + ("".join(sort)) # 生成加带密钥的新字符串 keystore = argument + ("".join(sort)) # 生成加带密钥的新字符串
sign_value = md5(keystore) sign_value = md5(keystore)
return {**data, **{"sign": sign_value}} return {**data, **{"sign": sign_value}}
@logger.log_decorator() @logger.log_decorator()
def sha1_sign(post_data: dict): def sha1_sign(post_data: dict):
timestamp = int(round(time.time() * 1000)) # 毫秒级时间戳 timestamp = int(round(time.time() * 1000)) # 毫秒级时间戳
argument = {"secretKey": "", "timestamp": timestamp} # 加密加盐参数 argument = {"secretKey": "", "timestamp": timestamp} # 加密加盐参数
res = {**post_data, **argument} res = {**post_data, **argument}
sorted_list = [] sorted_list = []
for key, value in res.items(): for key, value in res.items():
try: try:
value = json.dumps(value, ensure_ascii=False) if isinstance(value, list) or isinstance(value, value = json.dumps(value, ensure_ascii=False) if isinstance(value, list) or isinstance(value,
dict) else str( dict) else str(
value) value)
sorted_params = str(key) + "=" + value sorted_params = str(key) + "=" + value
sorted_list.append(sorted_params) sorted_list.append(sorted_params)
except Exception as e: except Exception as e:
raise e raise e
sort = natsorted(sorted_list) # 列表自然排序 返回[(key,value),(key,value)] sort = natsorted(sorted_list) # 列表自然排序 返回[(key,value),(key,value)]
splicing_str = "&".join(sort) # 排序结果 key=value&key=value 拼接 splicing_str = "&".join(sort) # 排序结果 key=value&key=value 拼接
encrypted_str = sha1_secret_str(splicing_str) # sha1加密 encrypted_str = sha1_secret_str(splicing_str) # sha1加密
sign = {"signature": encrypted_str} sign = {"signature": encrypted_str}
return {**res, **sign} # request 中使用json入参则传dict return {**res, **sign} # request 中使用json入参则传dict

View File

@ -1,8 +0,0 @@
# -*- coding: utf-8 -*-
# @Time : 2019/11/18 10:15
# @Author : kira
# @Email : 262667641@qq.com
# @File : __init__.py.py
# @Project : risk_api_project

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +0,0 @@
import json
import requests
class Hooks:
def __init__(self):
self.before_request_funcs = {}
self.after_request_funcs = {}
def before_request(self, func):
"""
注册 before_request 钩子函数
"""
self.before_request_funcs[func.__name__] = func
return func
def after_request(self, func):
"""
注册 after_request 钩子函数
"""
self.after_request_funcs[func.__name__] = func
return func
def run_before_request_hooks(self, func_names, request, json_data):
"""
执行 before_request 钩子函数
"""
for func_name in func_names:
if func_name in self.before_request_funcs:
func = self.before_request_funcs[func_name]
json_data = func(request, json_data)
return json_data
def run_after_request_hooks(self, func_names, response):
"""
执行 after_request 钩子函数
"""
for func_name in func_names:
if func_name in self.after_request_funcs:
func = self.after_request_funcs[func_name]
response = func(response)
return response
hooks = Hooks()
session = requests.Session()
def req(url, method, **kwargs):
"""
发送请求并返回响应对象
"""
before_hooks = kwargs.pop('before_hooks', [])
after_hooks = kwargs.pop('after_hooks', [])
json_data = kwargs.pop('json', {})
request = requests.Request(method=method, url=url, **kwargs)
prepared_request = session.prepare_request(request)
json_data = hooks.run_before_request_hooks(before_hooks, prepared_request, json_data)
prepared_request.body = json.dumps(json_data)
response = session.send(prepared_request)
response = hooks.run_after_request_hooks(after_hooks, response)
return response
@hooks.before_request
def add_authentication_headers(request, json_data):
"""
添加认证头信息
"""
print("前置钩子函数,添加认证头信息", request)
request.headers["Authorization"] = "Bearer YOUR_AUTH_TOKEN"
return json_data
@hooks.before_request
def handle_dependent_parameters(request, json_data):
"""
处理依赖参数
"""
print("前置钩子函数,处理依赖参数", request)
json_data["verification_code"] = get_verification_code()
return json_data
def get_verification_code():
# 实现获取验证码的逻辑
return "YOUR_VERIFICATION_CODE"
@hooks.after_request
def after_dependent_parameters(request, json_data):
"""
处理后置
"""
print("后置钩子函数,处理依赖参数", request)
return json_data
def test_user_registration():
url = "http://jsonplaceholder.typicode.com/posts"
data = {
"userId": "testuser",
"title": "password123",
"body": "测试玩家勇哥"
}
headers = {
"Content-Type": "application/json"
}
before_hooks = [add_authentication_headers.__name__, handle_dependent_parameters.__name__]
after_hooks = [after_dependent_parameters.__name__]
kwargs = {"json": data, "headers": headers}
return req(url, "post", before_hooks=before_hooks, after_hooks=after_hooks, **kwargs)
# assert response.status_code == 200
# assert response.json()["success"] is True
if __name__ == "__main__":
res = test_user_registration()
print(res, res.text)

View File

@ -1,29 +0,0 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: hooks_decorator.py
@time: 2023/6/16 17:03
@desc:
"""
from temp.extent.hooks import Hooks
hooks = Hooks()
def before_decorator(func):
def wrapper(*args, **kwargs):
# hooks.execute_hooks(*args, **kwargs)
return func(*args, **kwargs)
return wrapper
def after_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
# hooks.execute_hooks(*args, **kwargs)
return result
return wrapper

View File

@ -1,23 +0,0 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: run.py
@time: 2023/6/16 16:52
@desc:
"""
import requests
from temp.extent.hooks_decorator import before_decorator, after_decorator
@after_decorator
@before_decorator
def test_user_registration(url, method, **kwargs):
requests.request(method, url, **kwargs)
if __name__ == "__main__":
kwg = {}
test_user_registration("http://jsonplaceholder.typicode.com/posts/2", "get", **kwg)

View File

@ -1,125 +0,0 @@
import json
import requests
class Hooks:
def __init__(self):
self.before_request_funcs = {}
self.after_request_funcs = {}
def before_request(self, func):
"""
注册 before_request 钩子函数
"""
self.before_request_funcs[func.__name__] = func
return func
def after_request(self, func):
"""
注册 after_request 钩子函数
"""
self.after_request_funcs[func.__name__] = func
return func
def run_before_request_hooks(self, func_names, request, json_data):
"""
执行 before_request 钩子函数
"""
for func_name in func_names:
if func_name in self.before_request_funcs:
func = self.before_request_funcs[func_name]
json_data = func(request, json_data)
return json_data
def run_after_request_hooks(self, func_names, request, response):
"""
执行 after_request 钩子函数
"""
for func_name in func_names:
if func_name in self.after_request_funcs:
func = self.after_request_funcs[func_name]
response = func(request, response)
return response
hooks = Hooks()
session = requests.Session()
def req(url, method, **kwargs):
"""
发送请求并返回响应对象
"""
before_hooks = kwargs.pop('before_hooks', [])
after_hooks = kwargs.pop('after_hooks', [])
json_data = kwargs.pop('json', {})
request = requests.Request(method=method, url=url, **kwargs)
prepared_request = session.prepare_request(request)
json_data = hooks.run_before_request_hooks(before_hooks, prepared_request, json_data)
prepared_request.body = json.dumps(json_data)
response = session.send(prepared_request)
response = hooks.run_after_request_hooks(after_hooks, prepared_request, response)
return response
@hooks.before_request
def add_authentication_headers(request, json_data):
"""
添加认证头信息
"""
print("前置钩子函数,添加认证头信息", request)
request.headers["Authorization"] = "Bearer YOUR_AUTH_TOKEN"
return json_data
@hooks.before_request
def handle_dependent_parameters(request, json_data):
"""
处理依赖参数
"""
print("前置钩子函数,处理依赖参数", request)
json_data["verification_code"] = get_verification_code()
return json_data
def get_verification_code():
# 实现获取验证码的逻辑
return "YOUR_VERIFICATION_CODE"
@hooks.after_request
def after_dependent_parameters(request, response):
"""
处理后置
"""
print("发送请求后执行", request, "后置钩子函数,处理依赖参数", response)
return response
def test_user_registration():
url = "http://www.baidu.com"
# url = "http://jsonplaceholder.typicode.com/posts"
data = {
"userId": "testuser",
"title": "password123",
"body": "测试玩家勇哥"
}
headers = {
"Content-Type": "application/json"
}
before_hooks = [add_authentication_headers.__name__, handle_dependent_parameters.__name__]
after_hooks = [after_dependent_parameters.__name__]
kwargs = {"json": data, "headers": headers}
return req(url, "post", before_hooks=before_hooks, after_hooks=after_hooks, **kwargs)
if __name__ == "__main__":
res = test_user_registration()
print("最终打印:----->", res)

View File

@ -42,3 +42,23 @@ class Hooks:
response = func(response) response = func(response)
return response return response
hooks = Hooks()
def before_decorator(func):
def wrapper(*args, **kwargs):
# hooks.execute_hooks(*args, **kwargs)
return func(*args, **kwargs)
return wrapper
def after_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
# hooks.execute_hooks(*args, **kwargs)
return result
return wrapper

View File

@ -1,12 +1,4 @@
#!/usr/bin/env python # !/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: prepost_script.py
@time: 2023/6/16 16:58
@desc:
""" # !/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
""" """
@author: kira @author: kira
@ -15,7 +7,7 @@
@time: 2023/6/16 16:58 @time: 2023/6/16 16:58
@desc: @desc:
""" """
from temp.extent.hooks_decorator import hooks # 导入hooks对象 from temp.hooks import hooks
@hooks.before_request @hooks.before_request

View File

@ -4,8 +4,8 @@ import unittest
from ddt import ddt, data from ddt import ddt, data
from common import bif_functions from common import bif_functions
from common.config import Config
from common.action import Action from common.action import Action
from common.config import Config
from common.database.mysql_client import MysqlClient from common.database.mysql_client import MysqlClient
from common.file_handling.do_excel import DoExcel from common.file_handling.do_excel import DoExcel
from common.utils.mylogger import MyLogger from common.utils.mylogger import MyLogger
@ -36,8 +36,7 @@ class TestProjectApi(unittest.TestCase):
def test_api(self, item): def test_api(self, item):
# f"""用例:{item.get("name")}_{item.get("desc")}""" # f"""用例:{item.get("name")}_{item.get("desc")}"""
sheet, iid, condition, st, name, desc, headers_crypto, request_crypto, method = self.__base_info( sheet, iid, condition, st, name, desc, headers_crypto, request_crypto, method = self.__base_info(item)
item)
regex, keys, deps, jp_dict, extract_request_data = self.__extractor_info(item) regex, keys, deps, jp_dict, extract_request_data = self.__extractor_info(item)
if self.__is_run(condition): if self.__is_run(condition):
@ -70,10 +69,7 @@ class TestProjectApi(unittest.TestCase):
try: try:
# 执行请求操作 # 执行请求操作
kwargs = { kwargs = {request_data_type: request_data, 'headers': headers}
request_data_type: request_data,
'headers': headers
}
response = self.action.http_client(host, url, method, **kwargs) response = self.action.http_client(host, url, method, **kwargs)
# 执行后置代码片段 # 执行后置代码片段
self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "teardown", response) self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "teardown", response)

View File

@ -1,206 +0,0 @@
import time
import unittest
from ddt import ddt, data
from common import bif_functions
from common.action import Action
from common.config import Config
from common.database.mysql_client import MysqlClient
from common.file_handling.do_excel import DoExcel
from common.utils.mylogger import MyLogger
test_file = Config.test_case # 获取 excel 文件路径
excel = DoExcel(test_file)
init_data, test_case = excel.get_excel_init_and_cases()
databases = init_data.get('databases') # 获取数据库配置信息
mysql = MysqlClient(databases) # 初始化 mysql 链接
logger = MyLogger()
initialize_data = eval(init_data.get("initialize_data"))
host = init_data.get('host', "") + init_data.get("path", "")
@ddt
class TestProjectApi(unittest.TestCase):
maxDiff = None
action = Action()
@classmethod
def setUpClass(cls) -> None:
cls.action.set_variable(initialize_data) # 加载初始化数据
cls.action.set_bif_fun(bif_functions) # 加载内置方法
@data(*test_case)
def test_api(self, item):
# f"""用例:{item.get("name")}_{item.get("desc")}"""
sheet, iid, condition, st, name, desc, headers_crypto, request_crypto, method = self.__base_info(
item)
regex, keys, deps, jp_dict, extract_request_data = self.__extractor_info(item)
if self.__is_run(condition):
return
self.__pause_execution(st)
sql, sql_params_dict = self.__sql_info(item)
# 首先执行sql替换,将sql替换为正确的sql语句
sql = self.action.replace_dependent_parameter(sql)
self.__exc_sql(sql, sql_params_dict, method)
# 拼接动态代码段文件
prepost_script = f"prepost_script_{sheet}_{iid}.py"
item = self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "setup", item)
# 替换 URL, PARAMETERS, HEADER,期望值
item = self.action.replace_dependent_parameter(item)
url, query_str, request_data, headers, expected, request_data_type = self.__request_info(item)
# 提取请求参数信息
self.action.substitute_data(request_data, jp_dict=jp_dict)
headers, request_data = self.action.encrypt.encrypts(headers_crypto, headers, request_crypto, request_data)
result_tuple = None
result = "PASS"
response = None
try:
# 执行请求操作
kwargs = {
"sheet": sheet,
"iid": iid,
"item": item,
"jp_dict": jp_dict,
request_data_type: request_data,
'headers': headers
}
response = self.action.http_client(host, url, method, **kwargs)
# 执行后置代码片段
self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "teardown", response)
result_tuple = self.action.run_validate(expected, response.json()) # 执行断言 返回结果元组
self.assertNotIn("FAIL", result_tuple, "FAIL 存在结果元组中")
try:
# 提取响应
self.action.substitute_data(response.json(), regex=regex, keys=keys, deps=deps, jp_dict=jp_dict)
except Exception as err:
logger.error(f"提取响应失败:{sheet}_{iid}_{name}_{desc}"
f"\nregex={regex};"
f" \nkeys={keys};"
f"\ndeps={deps};"
f"\njp_dict={jp_dict}"
f"\n{err}")
except Exception as e:
result = "FAIL"
logger.error(f'异常用例: {sheet}_{iid}_{name}_{desc}\n{e}')
raise e
finally:
response = response.text if response is not None else str(response)
assert_log = str(result_tuple)
# 响应结果及测试结果回写 excel
excel.write_back(sheet_name=sheet, i=iid, response=response, test_result=result, assert_log=assert_log)
@classmethod
def tearDownClass(cls) -> None:
logger.info(f"所有用例执行完毕")
@staticmethod
def __base_info(item):
"""
获取基础信息
Args:
item:
Returns:
"""
sheet = item.pop("sheet")
item_id = item.pop("Id")
condition = item.pop("Run")
sleep_time = item.pop("Time")
name = item.pop("Name")
desc = item.pop("Description")
headers_crypto = item.pop("Headers Crypto")
request_data_crypto = item.pop("Request Data Crypto")
method = item.pop("Method")
return sheet, item_id, condition, sleep_time, name, desc, headers_crypto, request_data_crypto, method
@staticmethod
def __sql_info(item):
sql = item.pop("SQL")
sql_params_dict = item.pop("Sql Params Dict")
return sql, sql_params_dict
@staticmethod
def __extractor_info(item):
"""
获取提取参数的基本字段信息
Args:
item:
Returns:
"""
regex = item.pop("Regex")
keys = item.pop("Regex Params List")
deps = item.pop("Retrieve Value")
jp_dict = item.pop("Jsonpath")
extract_request_data = item.pop("Extract Request Data")
return regex, keys, deps, jp_dict, extract_request_data
@staticmethod
def __request_info(item):
"""
请求数据
Args:
item:
Returns:
"""
url = item.pop("Url")
query_str = item.pop("Query Str")
request_data = item.pop("Request Data")
headers = item.pop("Headers")
expected = item.pop("Expected")
request_data_type = item.pop("Request Data Type") if item.get("Request Data Type") else 'params'
return url, query_str, request_data, headers, expected, request_data_type
@staticmethod
def __is_run(condition):
is_run = condition
if not is_run or is_run.upper() != "YES":
return True
@staticmethod
def __pause_execution(sleep_time):
if sleep_time:
try:
time.sleep(sleep_time)
except Exception as e:
logger.error("暂时时间必须是数字")
raise e
def __exc_sql(self, sql, sql_params_dict, method):
if sql:
try:
execute_sql_results = mysql.do_mysql(sql)
if execute_sql_results and sql_params_dict:
self.action.extract_request_data(execute_sql_results, jp_dict=sql_params_dict)
if method == "SQL" and mysql:
return None
except Exception as e:
logger.error(f'执行 sql 失败:{sql},异常信息:{e}')
raise e
return sql
if __name__ == '__main__':
unittest.main()

View File

@ -1,86 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/10/12 11:12
# @Author : kira
# -*- coding: utf-8 -*-
# @Time : 2021/7/6 15:31
# @Author : kira
# @Email : 262667641@qq.com
# @File : test_wifi_upload_file.py
# @Project : api-test-project
import os
import random
import sys
import jsonpath
from common.file_handling.file_utils import FileUtils
sys.path.append("../../")
sys.path.append("../../common")
from common.http_client.http_client import Pyt
from common.config import Config
from common.random_tools.names import name
from common.random_tools.phone_numbers import phone
from common.random_tools.identification import idcard
pyt = Pyt()
def test_labor_register(cases):
host = 'https://bimuse.bzlrobot.com/bsp/test/user/ugs'
headers = {"BSP_APP_ID": "8d1f5bdc9c6648af84a98e2c017846c5",
"BSP_TOKEN": "32c9fd9ccc0565d0281b89b5fa198008",
"BSP_USER_ENV_ID": "f8e334ea85df45ed99a311ed022c2973",
"BSP_USER_ID": "216684145642752200",
"BSP_USER_TENANT": "216856950236843913",
"bzlrobot-authorization": "bearer 32c9fd9ccc0565d0281b89b5fa198008",
"projectId": "99000022",
"projectName": "%E4%BD%9B%E5%B1%B1%E9%99%88%E6%9D%91%E6%97%A7%E6%94%B9%E9%A1%B9%E7%9B%AE"
}
sex_id = random.randint(0, 1)
user_sex = "F" if sex_id == 0 else "M"
user_name = name.get_girl() if sex_id == 0 else name.get_boy()
user_id_card = idcard.get_generate_id(sex=sex_id)
user_birthday = idcard.get_birthday(user_id_card)
user_mobile = phone.get_mobile_number()
# 请求工种接口,获取所有工种
url = f"/ibs/api/ibs-lms-base/work-kind/page/list?t=1636702597000&current=1&size=1000&projectId={cases['projectId']}&key=&supplyId=&status=0&enabled=1"
kwargs = {
"headers": headers
}
res = pyt.http_client(host, url, "GET", **kwargs).json()
codes = jsonpath.jsonpath(res, "$.data..code")
names = jsonpath.jsonpath(res, "$.data..name")
work_kinds = dict(zip(codes, names))
work_code = random.choice(list(work_kinds.keys()))
cases["name"] = user_name
cases["idCard"]["name"] = user_name
cases["idCard"]["cardNo"] = user_id_card
cases["phone"] = user_mobile
cases["idCard"]["sex"] = user_sex
cases["idCard"]["birthday"] = user_birthday
cases['workKindCode'] = str(work_code)
cases['workKindName'] = work_kinds[str(work_code)]
if "positionName" in cases:
url = "/ibs/api/ibs-lms-member/manager/register?t=1634607524000"
else:
url = "/ibs/api/ibs-lms-member/labor/register?t=1633743835000"
try:
kwargs.update({"json": cases})
res = pyt.http_client(host, url, "POST", **kwargs)
assert res.status_code == 200
except Exception as e:
raise e
if __name__ == '__main__':
# 测试数据路径
test_case_path = os.path.join(Config.base_path, 'cases', 'cases', "labor.json")
test_case = FileUtils().read_json_file(test_case_path)
for i in range(500):
test_labor_register(test_case)