pytest-api-framework-alpha 0.3.9__tar.gz → 0.3.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/PKG-INFO +1 -1
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/conftest.py +25 -19
- pytest_api_framework_alpha-0.3.10/framework/utils/lark_util.py +87 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/pytest_api_framework_alpha.egg-info/PKG-INFO +1 -1
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/setup.py +1 -1
- pytest_api_framework_alpha-0.3.9/framework/utils/lark_util.py +0 -70
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/__init__.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/base_class.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/db/__init__.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/db/mysql_db.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/db/redis_db.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/exceptions.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/exit_code.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/extract.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/global_attribute.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/http_client.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/render_data.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/report.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/script.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/startapp.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/__init__.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/common.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/date_util.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/encrypt.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/log_util.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/mock_util.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/yaml_util.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/validate.py +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/pytest_api_framework_alpha.egg-info/SOURCES.txt +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/pytest_api_framework_alpha.egg-info/dependency_links.txt +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/pytest_api_framework_alpha.egg-info/requires.txt +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/pytest_api_framework_alpha.egg-info/top_level.txt +0 -0
- {pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/setup.cfg +0 -0
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/conftest.py
RENAMED
|
@@ -207,14 +207,14 @@ def pytest_generate_tests(metafunc):
|
|
|
207
207
|
if scenarios:
|
|
208
208
|
ids = list()
|
|
209
209
|
for index, item in enumerate(scenarios):
|
|
210
|
-
if item.get("scenario").get("ignore"):
|
|
211
|
-
continue
|
|
212
|
-
if func_name in item.get("scenario").get("exclude", list()):
|
|
213
|
-
continue
|
|
214
210
|
scenario = item.get("scenario")
|
|
215
211
|
level = scenario.get("level", settings.DEFAULT_CASE_LEVEL).lower()
|
|
216
|
-
|
|
217
212
|
case_data["level"] = level
|
|
213
|
+
if scenario.get("ignore"):
|
|
214
|
+
continue
|
|
215
|
+
if func_name in scenario.get("exclude", list()):
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
218
|
new_marks = marks.copy()
|
|
219
219
|
new_marks.append(level)
|
|
220
220
|
# mark标记
|
|
@@ -247,11 +247,10 @@ def pytest_generate_tests(metafunc):
|
|
|
247
247
|
logger.error(f"scenario参数化格式不正确:{e}")
|
|
248
248
|
traceback.print_exc()
|
|
249
249
|
pytest.exit(ExitCode.SCENARIO_FORMAT_ERROR)
|
|
250
|
+
if case_data_list:
|
|
251
|
+
metafunc.parametrize("data", case_data_list, ids=ids, scope="function")
|
|
250
252
|
|
|
251
|
-
metafunc.parametrize("data", case_data_list, ids=ids, scope="function")
|
|
252
253
|
else:
|
|
253
|
-
if case_common.get("ignore"):
|
|
254
|
-
return
|
|
255
254
|
case_data["_scenario"] = {"data": {}}
|
|
256
255
|
case_data["_ignore_failed"] = case_common.get("ignore_failed", settings.GLOBAL_IGNORE_FAILED)
|
|
257
256
|
level = case_data.get("level", settings.DEFAULT_CASE_LEVEL)
|
|
@@ -524,13 +523,18 @@ def pytest_terminal_summary(terminalreporter, exitstatus, config):
|
|
|
524
523
|
terminalreporter.write(f"跳过用例数: {skipped}\n", yellow=True, bold=True)
|
|
525
524
|
terminalreporter.write(f"用例通过率: {pass_rate}%\n", green=True, bold=True)
|
|
526
525
|
terminalreporter.write("====================================\n", blue=True, bold=True)
|
|
527
|
-
if
|
|
528
|
-
|
|
526
|
+
if settings.ONLY_LINUX_NOTIFICATION:
|
|
527
|
+
if "linux" not in platform.platform().lower():
|
|
528
|
+
return
|
|
529
|
+
for webhook in settings.LARK_WEBHOOKS:
|
|
530
|
+
LarkUtil(webhook).send_test_report(
|
|
529
531
|
total=total,
|
|
530
532
|
passed=passed,
|
|
531
533
|
failed=failed,
|
|
532
534
|
skipped=skipped,
|
|
533
|
-
report_url=os.environ.get("ALLURE_REPORT_URL")
|
|
535
|
+
report_url=os.environ.get("ALLURE_REPORT_URL"),
|
|
536
|
+
job_name=os.environ.get("JOB_NAME"),
|
|
537
|
+
env=CONTEXT.get("env")
|
|
534
538
|
)
|
|
535
539
|
|
|
536
540
|
|
|
@@ -811,28 +815,30 @@ def sort(case_items):
|
|
|
811
815
|
|
|
812
816
|
# 根据组数 创建各组的数组 并插入第一个case
|
|
813
817
|
case_dict = dict()
|
|
814
|
-
|
|
815
|
-
|
|
818
|
+
|
|
819
|
+
for i in range(case_suite_num):
|
|
820
|
+
try:
|
|
816
821
|
item = ori_name_list[i][1]
|
|
817
822
|
id = item.callspec.id
|
|
818
823
|
|
|
819
824
|
first_part = id.split('#', 1)[-1]
|
|
820
825
|
index = first_part.split(']')[0]
|
|
821
826
|
case_dict[index] = [item]
|
|
822
|
-
|
|
823
|
-
|
|
827
|
+
except Exception as e:
|
|
828
|
+
continue
|
|
824
829
|
|
|
825
830
|
new_start_index = case_suite_num
|
|
826
831
|
# 以new_start_index为起点 重新遍历items
|
|
827
|
-
|
|
828
|
-
|
|
832
|
+
|
|
833
|
+
for i in range(new_start_index, len(non_custom_scope_items)):
|
|
834
|
+
try:
|
|
829
835
|
item = non_custom_scope_items[i]
|
|
830
836
|
id = item.callspec.id
|
|
831
837
|
first_part = id.split('#', 1)[-1]
|
|
832
838
|
index = first_part.split(']')[0]
|
|
833
839
|
case_dict.get(index).append(item)
|
|
834
|
-
|
|
835
|
-
|
|
840
|
+
except Exception as e:
|
|
841
|
+
continue
|
|
836
842
|
|
|
837
843
|
index = 0
|
|
838
844
|
for id in case_dict:
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import hmac
|
|
3
|
+
import hashlib
|
|
4
|
+
import time
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LarkUtil:
|
|
12
|
+
def __init__(self, webhook: dict):
|
|
13
|
+
self.webhook = webhook
|
|
14
|
+
self.url = self.webhook.get("url")
|
|
15
|
+
self.secret = self.webhook.get("secret")
|
|
16
|
+
self.at_ids = self.webhook.get("open_ids") or None
|
|
17
|
+
self.headers = {"Content-Type": "application/json"}
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def gen_sign(timestamp, secret):
|
|
21
|
+
"""生成HMAC签名"""
|
|
22
|
+
# 拼接timestamp和secret
|
|
23
|
+
string_to_sign = '{}\n{}'.format(timestamp, secret)
|
|
24
|
+
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
|
|
25
|
+
# 对结果进行base64处理
|
|
26
|
+
sign = base64.b64encode(hmac_code).decode('utf-8')
|
|
27
|
+
return sign
|
|
28
|
+
|
|
29
|
+
def send_text(self, text: str, at_ids: list[str] = None):
|
|
30
|
+
data = {
|
|
31
|
+
"msg_type": "text",
|
|
32
|
+
"content": {"text": text},
|
|
33
|
+
}
|
|
34
|
+
if at_ids:
|
|
35
|
+
data["at"] = {"open_ids": at_ids}
|
|
36
|
+
if self.secret:
|
|
37
|
+
timestamp = str(int(time.time()))
|
|
38
|
+
data["sign"] = LarkUtil.gen_sign(timestamp, self.secret)
|
|
39
|
+
data["timestamp"] = timestamp
|
|
40
|
+
|
|
41
|
+
return requests.post(self.url, data=json.dumps(data), headers=self.headers)
|
|
42
|
+
|
|
43
|
+
def send_markdown(self, title: str, markdown_text: str, at_ids: list[str] = None):
|
|
44
|
+
"""发送 Markdown 消息"""
|
|
45
|
+
|
|
46
|
+
data = {
|
|
47
|
+
"msg_type": "interactive",
|
|
48
|
+
"card": {
|
|
49
|
+
"header": {
|
|
50
|
+
"template": "blue",
|
|
51
|
+
"title": {"tag": "plain_text", "content": title}
|
|
52
|
+
},
|
|
53
|
+
"elements": [
|
|
54
|
+
{
|
|
55
|
+
"tag": "markdown",
|
|
56
|
+
"content": markdown_text
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if at_ids:
|
|
62
|
+
data["at"] = {"open_ids": at_ids}
|
|
63
|
+
if self.secret:
|
|
64
|
+
timestamp = str(int(time.time()))
|
|
65
|
+
data["sign"] = LarkUtil.gen_sign(timestamp, self.secret)
|
|
66
|
+
data["timestamp"] = timestamp
|
|
67
|
+
return requests.post(self.url, headers=self.headers, data=json.dumps(data))
|
|
68
|
+
|
|
69
|
+
def send_test_report(self, total: int, passed: int, failed: int, skipped: int, report_url: str = None,
|
|
70
|
+
job_name: str = None, env=None):
|
|
71
|
+
"""自动化测试结果消息(Markdown)"""
|
|
72
|
+
try:
|
|
73
|
+
pass_rate = round(passed / (total - skipped) * 100, 2)
|
|
74
|
+
except ZeroDivisionError:
|
|
75
|
+
pass_rate = 0
|
|
76
|
+
markdown = f"""**执行环境:** {env}
|
|
77
|
+
**执行完成时间:** {datetime.now().strftime("%Y-%m-%d %X")}
|
|
78
|
+
**执行用例总数:** {total}
|
|
79
|
+
**通过用例数:** {passed}
|
|
80
|
+
**失败用例数:** {failed}
|
|
81
|
+
**跳过用例数:** {skipped}
|
|
82
|
+
**用例通过率:** {pass_rate}%
|
|
83
|
+
"""
|
|
84
|
+
if report_url:
|
|
85
|
+
markdown += f"\n**测试报告:** [点击查看测试报告]({report_url})"
|
|
86
|
+
title = f"【自动化测试结果】-{job_name} " if job_name else "【自动化测试结果】"
|
|
87
|
+
return self.send_markdown(title, markdown)
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import json
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
|
|
5
|
-
class LarkUtil:
|
|
6
|
-
def __init__(self, webhook: str):
|
|
7
|
-
self.webhook = webhook
|
|
8
|
-
self.headers = {"Content-Type": "application/json"}
|
|
9
|
-
|
|
10
|
-
def send_text(self, text: str, at_ids=None):
|
|
11
|
-
data = {
|
|
12
|
-
"msg_type": "text",
|
|
13
|
-
"content": {"text": text},
|
|
14
|
-
}
|
|
15
|
-
if at_ids:
|
|
16
|
-
data["at"] = {"open_ids": at_ids}
|
|
17
|
-
return requests.post(self.webhook, data=json.dumps(data), headers=self.headers)
|
|
18
|
-
|
|
19
|
-
def send_markdown(self, title: str, markdown_text: str):
|
|
20
|
-
"""发送 Markdown 消息"""
|
|
21
|
-
|
|
22
|
-
data = {
|
|
23
|
-
"msg_type": "interactive",
|
|
24
|
-
"card": {
|
|
25
|
-
"header": {
|
|
26
|
-
"template": "blue",
|
|
27
|
-
"title": {"tag": "plain_text", "content": title}
|
|
28
|
-
},
|
|
29
|
-
"elements": [
|
|
30
|
-
{
|
|
31
|
-
"tag": "markdown",
|
|
32
|
-
"content": markdown_text
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
resp = requests.post(self.webhook, headers=self.headers, data=json.dumps(data))
|
|
39
|
-
return resp.text
|
|
40
|
-
|
|
41
|
-
def send_test_report(self, total: int, passed: int, failed: int, skipped: int, report_url: str = None):
|
|
42
|
-
"""自动化测试结果消息(Markdown)"""
|
|
43
|
-
try:
|
|
44
|
-
pass_rate = round(passed / (total - skipped) * 100, 2)
|
|
45
|
-
except ZeroDivisionError:
|
|
46
|
-
pass_rate = 0
|
|
47
|
-
markdown = f"""**执行结果统计:**
|
|
48
|
-
**执行用例总数:** {total}
|
|
49
|
-
**通过用例数:** {passed}
|
|
50
|
-
**失败用例数:** {failed}
|
|
51
|
-
**跳过用例数:** {skipped}
|
|
52
|
-
**用例通过率:** {pass_rate}%
|
|
53
|
-
"""
|
|
54
|
-
if report_url:
|
|
55
|
-
markdown += f"\n**测试报告:** 👉 [点击查看测试报告]({report_url})"
|
|
56
|
-
return self.send_markdown(f"自动化测试结果 {datetime.now().strftime("%Y-%m-%d %X")}", markdown)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if __name__ == "__main__":
|
|
60
|
-
# 你的飞书群机器人 Webhook URL
|
|
61
|
-
WEBHOOK = "https://open.larksuite.com/open-apis/bot/v2/hook/27de2bf2-fa0d-49e7-8ff3-a3e3ad8cf2d7"
|
|
62
|
-
bot = LarkUtil(WEBHOOK)
|
|
63
|
-
|
|
64
|
-
bot.send_test_report(
|
|
65
|
-
total=20,
|
|
66
|
-
passed=18,
|
|
67
|
-
failed=1,
|
|
68
|
-
skipped=1,
|
|
69
|
-
report_url="http://your-report/index.html"
|
|
70
|
-
)
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/__init__.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/base_class.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/db/__init__.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/db/mysql_db.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/db/redis_db.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/exceptions.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/exit_code.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/global_attribute.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/http_client.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/render_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/startapp.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/__init__.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/common.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/date_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/encrypt.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/log_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/mock_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/utils/yaml_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.9 → pytest_api_framework_alpha-0.3.10}/framework/validate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|