pytest-api-framework-alpha 0.3.23__tar.gz → 0.3.24__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.23 → pytest_api_framework_alpha-0.3.24}/PKG-INFO +29 -29
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/base_class.py +27 -26
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/conftest.py +56 -25
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/global_attribute.py +17 -4
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/http_client.py +7 -5
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/common.py +15 -4
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/pytest_api_framework_alpha.egg-info/PKG-INFO +29 -29
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/setup.cfg +4 -4
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/setup.py +1 -1
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/__init__.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/assert_webhook.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/db/__init__.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/db/mysql_db.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/db/redis_db.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/exceptions.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/exit_code.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/extract.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/render_data.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/report.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/retry_assert.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/script.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/startapp.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/__init__.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/date_util.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/encrypt.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/lark_util.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/log_util.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/mock_util.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/yaml_util.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/validate.py +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/pytest_api_framework_alpha.egg-info/SOURCES.txt +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/pytest_api_framework_alpha.egg-info/dependency_links.txt +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/pytest_api_framework_alpha.egg-info/requires.txt +0 -0
- {pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/pytest_api_framework_alpha.egg-info/top_level.txt +0 -0
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pytest-api-framework-alpha
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Author: alpha
|
|
5
|
-
Author-email:
|
|
6
|
-
Requires-Python: >=3.6
|
|
7
|
-
Requires-Dist: allure-pytest==2.13.1
|
|
8
|
-
Requires-Dist: allure-python-commons==2.13.1
|
|
9
|
-
Requires-Dist: cn2an==0.5.19
|
|
10
|
-
Requires-Dist: DBUtils==3.1.0
|
|
11
|
-
Requires-Dist: Faker==18.3.2
|
|
12
|
-
Requires-Dist: jsonpath==0.82
|
|
13
|
-
Requires-Dist: pytest==7.2.2
|
|
14
|
-
Requires-Dist: python-dotenv==1.0.1
|
|
15
|
-
Requires-Dist: PyYAML==6.0.1
|
|
16
|
-
Requires-Dist: python-box==7.2.0
|
|
17
|
-
Requires-Dist: pycryptodome==3.21.0
|
|
18
|
-
Requires-Dist: pyotp==2.9.0
|
|
19
|
-
Requires-Dist: pytest-order==1.3.0
|
|
20
|
-
Requires-Dist: PyMySQL==1.1.0
|
|
21
|
-
Requires-Dist: redis==3.5.3
|
|
22
|
-
Requires-Dist: requests==2.25.1
|
|
23
|
-
Requires-Dist: requests-toolbelt==1.0.0
|
|
24
|
-
Requires-Dist: retry==0.9.2
|
|
25
|
-
Requires-Dist: dill==0.3.8
|
|
26
|
-
Requires-Dist: simplejson==3.20.1
|
|
27
|
-
Dynamic: author
|
|
28
|
-
Dynamic: requires-dist
|
|
29
|
-
Dynamic: requires-python
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-api-framework-alpha
|
|
3
|
+
Version: 0.3.24
|
|
4
|
+
Author: alpha
|
|
5
|
+
Author-email:
|
|
6
|
+
Requires-Python: >=3.6
|
|
7
|
+
Requires-Dist: allure-pytest==2.13.1
|
|
8
|
+
Requires-Dist: allure-python-commons==2.13.1
|
|
9
|
+
Requires-Dist: cn2an==0.5.19
|
|
10
|
+
Requires-Dist: DBUtils==3.1.0
|
|
11
|
+
Requires-Dist: Faker==18.3.2
|
|
12
|
+
Requires-Dist: jsonpath==0.82
|
|
13
|
+
Requires-Dist: pytest==7.2.2
|
|
14
|
+
Requires-Dist: python-dotenv==1.0.1
|
|
15
|
+
Requires-Dist: PyYAML==6.0.1
|
|
16
|
+
Requires-Dist: python-box==7.2.0
|
|
17
|
+
Requires-Dist: pycryptodome==3.21.0
|
|
18
|
+
Requires-Dist: pyotp==2.9.0
|
|
19
|
+
Requires-Dist: pytest-order==1.3.0
|
|
20
|
+
Requires-Dist: PyMySQL==1.1.0
|
|
21
|
+
Requires-Dist: redis==3.5.3
|
|
22
|
+
Requires-Dist: requests==2.25.1
|
|
23
|
+
Requires-Dist: requests-toolbelt==1.0.0
|
|
24
|
+
Requires-Dist: retry==0.9.2
|
|
25
|
+
Requires-Dist: dill==0.3.8
|
|
26
|
+
Requires-Dist: simplejson==3.20.1
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/base_class.py
RENAMED
|
@@ -20,7 +20,7 @@ from framework.utils.date_util import DateUtil
|
|
|
20
20
|
from framework.retry_assert import RetryAssert
|
|
21
21
|
from framework.assert_webhook import AssertWebhook
|
|
22
22
|
from framework.http_client import ResponseUtil, HttpClient
|
|
23
|
-
from framework.utils.encrypt import b64_encode
|
|
23
|
+
from framework.utils.encrypt import b64_encode
|
|
24
24
|
from framework.utils.common import snake_to_pascal, SingletonFaker
|
|
25
25
|
from framework.global_attribute import GlobalAttribute, _FRAMEWORK_CONTEXT, CONTEXT
|
|
26
26
|
from framework.exceptions import ValidateException, RenderException, RequestException, GetAccountError, GetAppHttpError
|
|
@@ -67,8 +67,8 @@ class BaseTestCase(ExtendBaseTestCase):
|
|
|
67
67
|
app_http = getattr(self.http, app)
|
|
68
68
|
except AttributeError as e:
|
|
69
69
|
raise GetAppHttpError(e)
|
|
70
|
-
domain = self.context.get(app).get("domain")
|
|
71
70
|
data = RenderData(data).render()
|
|
71
|
+
domain = self.context.get(app).get("domain")
|
|
72
72
|
data.request.url = self.replace_domain(data.request.url, domain)
|
|
73
73
|
try:
|
|
74
74
|
self.response = getattr(app_http, account, HttpClient()).request(data=data, **kwargs)
|
|
@@ -112,29 +112,30 @@ class BaseTestCase(ExtendBaseTestCase):
|
|
|
112
112
|
traceback.print_exc()
|
|
113
113
|
pytest.fail(str(e))
|
|
114
114
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
115
|
+
def _request(self, method, app, account, url, **kwargs) -> ResponseUtil:
|
|
116
|
+
request = {"method": method, "url": url, "headers": {}, **kwargs}
|
|
117
|
+
if app:
|
|
118
|
+
domain = self.context.get(app).get("domain")
|
|
119
|
+
request["url"] = urljoin(domain, url)
|
|
120
|
+
return self.request(app=app, account=account, data=Box({"request": request}))
|
|
121
|
+
|
|
122
|
+
# 不需要token发送请求的
|
|
123
|
+
data = RenderData(Box({"request": request})).render()
|
|
124
|
+
del kwargs["data"]
|
|
125
|
+
self.response = HttpClient().request(data=data, **kwargs)
|
|
126
|
+
return self.response
|
|
127
|
+
|
|
128
|
+
def get(self, app=None, *, account, url, params=None, **kwargs) -> ResponseUtil:
|
|
129
|
+
return self._request("get", app, account, url, params=params, **kwargs)
|
|
130
|
+
|
|
131
|
+
def post(self, app=None, *, account="", url, data=None, json=None, **kwargs):
|
|
132
|
+
return self._request("post", app, account, url, data=data, json=json, **kwargs)
|
|
133
|
+
|
|
134
|
+
def put(self, app=None, *, account, url, data=None, json=None, **kwargs) -> ResponseUtil:
|
|
135
|
+
return self._request("put", app, account, url, data=data, json=json, **kwargs)
|
|
136
|
+
|
|
137
|
+
def delete(self, app=None, *, account, url, **kwargs) -> ResponseUtil:
|
|
138
|
+
return self._request("delete", app, account, url, **kwargs)
|
|
138
139
|
|
|
139
140
|
def mysql_conn(self, db, app=None) -> MysqlDB:
|
|
140
141
|
try:
|
|
@@ -366,4 +367,4 @@ class BaseTestCase(ExtendBaseTestCase):
|
|
|
366
367
|
"expiry": 0
|
|
367
368
|
}
|
|
368
369
|
)
|
|
369
|
-
assert self.response.code == 200
|
|
370
|
+
assert self.response.code == 200
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/conftest.py
RENAMED
|
@@ -2,7 +2,6 @@ import os
|
|
|
2
2
|
import re
|
|
3
3
|
import sys
|
|
4
4
|
import copy
|
|
5
|
-
import time
|
|
6
5
|
import platform
|
|
7
6
|
import threading
|
|
8
7
|
import importlib
|
|
@@ -14,8 +13,9 @@ from collections import OrderedDict
|
|
|
14
13
|
from datetime import datetime, timedelta
|
|
15
14
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
16
15
|
|
|
17
|
-
import dill
|
|
18
16
|
import json
|
|
17
|
+
|
|
18
|
+
import requests
|
|
19
19
|
import retry
|
|
20
20
|
import allure
|
|
21
21
|
import pytest
|
|
@@ -32,7 +32,7 @@ from framework.utils.lark_util import LarkUtil
|
|
|
32
32
|
from framework.utils.yaml_util import CachedYamlLoader
|
|
33
33
|
from framework.exceptions import MysqlDBError, RedisDBError
|
|
34
34
|
from framework.global_attribute import CONTEXT, CONFIG, _FRAMEWORK_CONTEXT
|
|
35
|
-
from framework.utils.common import snake_to_pascal, get_apps, convert_numbers_to_decimal
|
|
35
|
+
from framework.utils.common import snake_to_pascal, get_apps, convert_numbers_to_decimal, get_short_timestamp,now_iso8601
|
|
36
36
|
|
|
37
37
|
all_app = get_apps()
|
|
38
38
|
module = importlib.import_module("test_case.conftest")
|
|
@@ -159,6 +159,7 @@ def pytest_generate_tests(metafunc):
|
|
|
159
159
|
case_data["_scenario"] = {"data": {}}
|
|
160
160
|
case_data["_belong_app"] = belong_app
|
|
161
161
|
metafunc.parametrize("data", [case_data, ], ids=[f'{case_data.get("title", "")}#'], scope="function")
|
|
162
|
+
logger.info(f"{node_id}")
|
|
162
163
|
return
|
|
163
164
|
if case_data.get("request") is None:
|
|
164
165
|
case_data["request"] = dict()
|
|
@@ -389,7 +390,7 @@ def pytest_sessionfinish(session, exitstatus):
|
|
|
389
390
|
|
|
390
391
|
|
|
391
392
|
def pytest_runtest_setup(item):
|
|
392
|
-
allure.dynamic.sub_suite(item
|
|
393
|
+
allure.dynamic.sub_suite(getattr(item,"allure_suite_mark"))
|
|
393
394
|
if item.funcargs.get("first"):
|
|
394
395
|
test_object = item.instance
|
|
395
396
|
test_object.context = CONTEXT
|
|
@@ -418,8 +419,23 @@ def pytest_runtest_call(item):
|
|
|
418
419
|
:param item:
|
|
419
420
|
:return:
|
|
420
421
|
"""
|
|
422
|
+
# 获取原始测试数据
|
|
421
423
|
origin_data = item.funcargs.get("data")
|
|
422
424
|
ignore_failed = origin_data.get("_ignore_failed")
|
|
425
|
+
# 函数式测试用例添加参数data, belong_app
|
|
426
|
+
http = item.funcargs.get("http")
|
|
427
|
+
item.funcargs["data"] = item.instance.data = Box(origin_data)
|
|
428
|
+
item.funcargs["scenario"] = item.instance.scenario = Box(json.loads(json.dumps(
|
|
429
|
+
convert_numbers_to_decimal(origin_data.get("_scenario")))))
|
|
430
|
+
_belong_app = origin_data.get("_belong_app")
|
|
431
|
+
item.funcargs["belong_app"] = item.instance.belong_app = _belong_app
|
|
432
|
+
item.funcargs["config"] = item.instance.config = CONFIG
|
|
433
|
+
item.funcargs["context"] = item.instance.context = CONTEXT
|
|
434
|
+
item.funcargs["retry_assert"] = item.instance.retry_assert = RetryAssert.eventually
|
|
435
|
+
# 类式测试用例添加参数http,data, belong_app
|
|
436
|
+
item.instance.http = http
|
|
437
|
+
logger.info(f"执行用例: {item.nodeid}")
|
|
438
|
+
|
|
423
439
|
if not ignore_failed:
|
|
424
440
|
# setup方法执行失败,则主动标记用例执行失败,不会执行用例
|
|
425
441
|
if item.funcargs.get("setup_success") is False:
|
|
@@ -428,10 +444,14 @@ def pytest_runtest_call(item):
|
|
|
428
444
|
index = item.session.items.index(item)
|
|
429
445
|
pattern = re.compile(r'^(?P<prefix>.*)::[^:\[\]]+\[.*#(?P<index>\d+)\]$')
|
|
430
446
|
current_match = pattern.match(item.nodeid)
|
|
447
|
+
if not current_match:
|
|
448
|
+
return
|
|
431
449
|
current_cls_name = current_match.group('prefix')
|
|
432
450
|
current_index = current_match.group('index')
|
|
433
451
|
prev_item = item.session.items[index - 1]
|
|
434
452
|
prev_match = pattern.match(prev_item.nodeid)
|
|
453
|
+
if not prev_match:
|
|
454
|
+
return
|
|
435
455
|
prev_cls_name = prev_match.group("prefix")
|
|
436
456
|
prev_index = prev_match.group("index")
|
|
437
457
|
# 确保是同一个类,并且索引相同
|
|
@@ -446,22 +466,6 @@ def pytest_runtest_call(item):
|
|
|
446
466
|
elif status == "failed":
|
|
447
467
|
pytest.skip("the previous method execute failed")
|
|
448
468
|
|
|
449
|
-
# 获取原始测试数据
|
|
450
|
-
origin_data = item.funcargs.get("data")
|
|
451
|
-
logger.info(f"执行用例: {item.nodeid}")
|
|
452
|
-
# 函数式测试用例添加参数data, belong_app
|
|
453
|
-
http = item.funcargs.get("http")
|
|
454
|
-
item.funcargs["data"] = item.instance.data = Box(origin_data)
|
|
455
|
-
item.funcargs["scenario"] = item.instance.scenario = Box(json.loads(json.dumps(
|
|
456
|
-
convert_numbers_to_decimal(origin_data.get("_scenario")))))
|
|
457
|
-
_belong_app = origin_data.get("_belong_app")
|
|
458
|
-
item.funcargs["belong_app"] = item.instance.belong_app = _belong_app
|
|
459
|
-
item.funcargs["config"] = item.instance.config = CONFIG
|
|
460
|
-
item.funcargs["context"] = item.instance.context = CONTEXT
|
|
461
|
-
item.funcargs["retry_assert"] = item.instance.retry_assert = RetryAssert.eventually
|
|
462
|
-
# 类式测试用例添加参数http,data, belong_app
|
|
463
|
-
item.instance.http = http
|
|
464
|
-
|
|
465
469
|
# 判断token是否过期,过期则重新登录
|
|
466
470
|
expire_time = _FRAMEWORK_CONTEXT.get(app=_belong_app, key="expire_time")
|
|
467
471
|
if expire_time:
|
|
@@ -516,14 +520,16 @@ def pytest_runtest_makereport(item, call):
|
|
|
516
520
|
item.status = report.outcome # 'passed', 'failed', or 'skipped'
|
|
517
521
|
|
|
518
522
|
|
|
519
|
-
def
|
|
520
|
-
|
|
521
|
-
stats = terminalreporter.stats
|
|
522
|
-
|
|
523
|
+
def pytest_sessionfinish(session, exitstatus):
|
|
524
|
+
terminalreporter = session.config.pluginmanager.get_plugin("terminalreporter")
|
|
525
|
+
stats = terminalreporter.stats if terminalreporter else {}
|
|
526
|
+
|
|
523
527
|
passed = len(stats.get("passed", []))
|
|
524
528
|
failed = len(stats.get("failed", []))
|
|
529
|
+
error = len(stats.get("error", []))
|
|
525
530
|
skipped = len(stats.get("skipped", []))
|
|
526
531
|
total = passed + failed + skipped
|
|
532
|
+
|
|
527
533
|
try:
|
|
528
534
|
pass_rate = round(passed / (total - skipped) * 100, 2)
|
|
529
535
|
except ZeroDivisionError:
|
|
@@ -560,6 +566,31 @@ def pytest_terminal_summary(terminalreporter, exitstatus, config):
|
|
|
560
566
|
job_name=CONTEXT.get("mark"),
|
|
561
567
|
env=CONTEXT.get("env")
|
|
562
568
|
)
|
|
569
|
+
try:
|
|
570
|
+
requests.request(
|
|
571
|
+
method="POST",
|
|
572
|
+
url=settings.REPORT_URL,
|
|
573
|
+
headers={"Content-Type": "application/json", "Authorization": f"Token {settings.TOKEN}"},
|
|
574
|
+
json={
|
|
575
|
+
"total": total,
|
|
576
|
+
"passed": passed,
|
|
577
|
+
"failed": failed,
|
|
578
|
+
"skipped": skipped,
|
|
579
|
+
"pass_rate": pass_rate,
|
|
580
|
+
"env": CONTEXT.get("env"),
|
|
581
|
+
"mark": CONTEXT.get("mark"),
|
|
582
|
+
"command": CONTEXT.get("command"),
|
|
583
|
+
"start_time": CONTEXT.get("start_time"),
|
|
584
|
+
"start_time_format": CONTEXT.get("start_time_format"),
|
|
585
|
+
"end_time": get_short_timestamp(),
|
|
586
|
+
"end_time_format": now_iso8601(),
|
|
587
|
+
"duration": int(get_short_timestamp()) - int(CONTEXT.get("start_time"))
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
)
|
|
591
|
+
except:
|
|
592
|
+
logger.error("报告同步失败")
|
|
593
|
+
|
|
563
594
|
|
|
564
595
|
|
|
565
596
|
def pytest_exception_interact(node, call, report):
|
|
@@ -877,4 +908,4 @@ def sort(case_items):
|
|
|
877
908
|
|
|
878
909
|
all_item_list += item_list
|
|
879
910
|
|
|
880
|
-
return all_item_list
|
|
911
|
+
return all_item_list
|
|
@@ -52,10 +52,8 @@ class GlobalAttribute(object):
|
|
|
52
52
|
|
|
53
53
|
def get(self, key, app=None):
|
|
54
54
|
if app:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
obj = self
|
|
58
|
-
value = getattr(obj, key, None)
|
|
55
|
+
return self.get_by_chain(f"{app}.{key}")
|
|
56
|
+
value = getattr(self, key, None)
|
|
59
57
|
return Box(value) if isinstance(value, dict) else self.list2box(value) if isinstance(value, list) else value
|
|
60
58
|
|
|
61
59
|
def set(self, key, value, app=None):
|
|
@@ -66,6 +64,21 @@ class GlobalAttribute(object):
|
|
|
66
64
|
|
|
67
65
|
setattr(self, key, value)
|
|
68
66
|
|
|
67
|
+
def get_by_chain(self, key_chain, default=None):
|
|
68
|
+
"""
|
|
69
|
+
链式格式的key进行get
|
|
70
|
+
:param key_chain: 链式key,例如 "app.module.key"
|
|
71
|
+
:param default: 找不到时的默认值
|
|
72
|
+
:return:
|
|
73
|
+
"""
|
|
74
|
+
keys = key_chain.split(".")
|
|
75
|
+
obj = self
|
|
76
|
+
for key in keys:
|
|
77
|
+
obj = getattr(obj, key, None)
|
|
78
|
+
if obj is None:
|
|
79
|
+
return default
|
|
80
|
+
return Box(obj) if isinstance(obj, dict) else self.list2box(obj) if isinstance(obj, list) else obj
|
|
81
|
+
|
|
69
82
|
def set_by_chain(self, key_chain, value):
|
|
70
83
|
"""
|
|
71
84
|
链式格式的key进行set
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/http_client.py
RENAMED
|
@@ -18,7 +18,7 @@ from framework.utils.log_util import logger
|
|
|
18
18
|
from framework.global_attribute import CONTEXT
|
|
19
19
|
from config.settings import CONSOLE_DETAILED_LOG
|
|
20
20
|
from framework.utils.common import convert_numbers_to_decimal
|
|
21
|
-
from framework.exceptions import RequestException
|
|
21
|
+
from framework.exceptions import RequestException, ValidateException
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ResponseUtil(object):
|
|
@@ -197,24 +197,26 @@ class HttpClient(object):
|
|
|
197
197
|
try:
|
|
198
198
|
data["request"]["headers"].update(kwargs.get("headers", {}))
|
|
199
199
|
return self.__send_request(data)
|
|
200
|
+
except ValidateException as e:
|
|
201
|
+
raise ValidateException(e)
|
|
200
202
|
except Exception as e:
|
|
201
203
|
raise RequestException(e)
|
|
202
204
|
|
|
203
205
|
return ResponseUtil(requests.request(headers=self.headers, **kwargs))
|
|
204
206
|
|
|
205
|
-
def post(self, app
|
|
207
|
+
def post(self, app=None,*, url, data=None, json=None, **kwargs):
|
|
206
208
|
return self.request(method="post", url=urljoin(CONTEXT.get(app=app, key="domain"), url), data=data,
|
|
207
209
|
json=json, **kwargs)
|
|
208
210
|
|
|
209
|
-
def get(self, app
|
|
211
|
+
def get(self, app=None,*, url, params=None, **kwargs):
|
|
210
212
|
return self.request(method="get", url=urljoin(CONTEXT.get(app=app, key="domain"), url), params=params,
|
|
211
213
|
**kwargs)
|
|
212
214
|
|
|
213
|
-
def put(self, app
|
|
215
|
+
def put(self, app=None,*, url, data=None, **kwargs):
|
|
214
216
|
return self.request(method="put", url=urljoin(CONTEXT.get(app=app, key="domain"), url), data=data,
|
|
215
217
|
**kwargs)
|
|
216
218
|
|
|
217
|
-
def delete(self, app
|
|
219
|
+
def delete(self, app=None,*, url, **kwargs):
|
|
218
220
|
return self.request(method="delete", url=urljoin(CONTEXT.get(app=app, key="domain"), url), **kwargs)
|
|
219
221
|
|
|
220
222
|
def update_headers(self, headers):
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/common.py
RENAMED
|
@@ -2,10 +2,11 @@ import decimal
|
|
|
2
2
|
import re
|
|
3
3
|
import os
|
|
4
4
|
import time
|
|
5
|
+
import base64
|
|
5
6
|
import binascii
|
|
6
7
|
from typing import Any
|
|
7
8
|
from decimal import Decimal
|
|
8
|
-
from datetime import datetime
|
|
9
|
+
from datetime import datetime,timezone,timedelta
|
|
9
10
|
from urllib.parse import unquote, quote, quote_plus, unquote_plus
|
|
10
11
|
|
|
11
12
|
import pyotp
|
|
@@ -147,10 +148,16 @@ def valid_b64_format(s):
|
|
|
147
148
|
:param s:
|
|
148
149
|
:return:
|
|
149
150
|
"""
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
"""
|
|
152
|
+
校验字符串是否为合法 base64
|
|
153
|
+
"""
|
|
154
|
+
try:
|
|
155
|
+
if not isinstance(s, str):
|
|
156
|
+
return False
|
|
157
|
+
base64.b64decode(s, validate=True)
|
|
152
158
|
return True
|
|
153
|
-
|
|
159
|
+
except (binascii.Error, ValueError):
|
|
160
|
+
return False
|
|
154
161
|
|
|
155
162
|
|
|
156
163
|
def hex_to_bytes(hex_str):
|
|
@@ -261,3 +268,7 @@ def convert_numbers_to_decimal(obj: Any) -> Any:
|
|
|
261
268
|
def remove_spaces(s: str) -> str:
|
|
262
269
|
"""去掉字符串中的所有空格"""
|
|
263
270
|
return s.replace(" ", "")
|
|
271
|
+
|
|
272
|
+
def now_iso8601(tz_offset_hours: int = 8) -> str:
|
|
273
|
+
tz = timezone(timedelta(hours=tz_offset_hours))
|
|
274
|
+
return datetime.now(tz).isoformat(timespec='seconds')
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pytest-api-framework-alpha
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Author: alpha
|
|
5
|
-
Author-email:
|
|
6
|
-
Requires-Python: >=3.6
|
|
7
|
-
Requires-Dist: allure-pytest==2.13.1
|
|
8
|
-
Requires-Dist: allure-python-commons==2.13.1
|
|
9
|
-
Requires-Dist: cn2an==0.5.19
|
|
10
|
-
Requires-Dist: DBUtils==3.1.0
|
|
11
|
-
Requires-Dist: Faker==18.3.2
|
|
12
|
-
Requires-Dist: jsonpath==0.82
|
|
13
|
-
Requires-Dist: pytest==7.2.2
|
|
14
|
-
Requires-Dist: python-dotenv==1.0.1
|
|
15
|
-
Requires-Dist: PyYAML==6.0.1
|
|
16
|
-
Requires-Dist: python-box==7.2.0
|
|
17
|
-
Requires-Dist: pycryptodome==3.21.0
|
|
18
|
-
Requires-Dist: pyotp==2.9.0
|
|
19
|
-
Requires-Dist: pytest-order==1.3.0
|
|
20
|
-
Requires-Dist: PyMySQL==1.1.0
|
|
21
|
-
Requires-Dist: redis==3.5.3
|
|
22
|
-
Requires-Dist: requests==2.25.1
|
|
23
|
-
Requires-Dist: requests-toolbelt==1.0.0
|
|
24
|
-
Requires-Dist: retry==0.9.2
|
|
25
|
-
Requires-Dist: dill==0.3.8
|
|
26
|
-
Requires-Dist: simplejson==3.20.1
|
|
27
|
-
Dynamic: author
|
|
28
|
-
Dynamic: requires-dist
|
|
29
|
-
Dynamic: requires-python
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-api-framework-alpha
|
|
3
|
+
Version: 0.3.24
|
|
4
|
+
Author: alpha
|
|
5
|
+
Author-email:
|
|
6
|
+
Requires-Python: >=3.6
|
|
7
|
+
Requires-Dist: allure-pytest==2.13.1
|
|
8
|
+
Requires-Dist: allure-python-commons==2.13.1
|
|
9
|
+
Requires-Dist: cn2an==0.5.19
|
|
10
|
+
Requires-Dist: DBUtils==3.1.0
|
|
11
|
+
Requires-Dist: Faker==18.3.2
|
|
12
|
+
Requires-Dist: jsonpath==0.82
|
|
13
|
+
Requires-Dist: pytest==7.2.2
|
|
14
|
+
Requires-Dist: python-dotenv==1.0.1
|
|
15
|
+
Requires-Dist: PyYAML==6.0.1
|
|
16
|
+
Requires-Dist: python-box==7.2.0
|
|
17
|
+
Requires-Dist: pycryptodome==3.21.0
|
|
18
|
+
Requires-Dist: pyotp==2.9.0
|
|
19
|
+
Requires-Dist: pytest-order==1.3.0
|
|
20
|
+
Requires-Dist: PyMySQL==1.1.0
|
|
21
|
+
Requires-Dist: redis==3.5.3
|
|
22
|
+
Requires-Dist: requests==2.25.1
|
|
23
|
+
Requires-Dist: requests-toolbelt==1.0.0
|
|
24
|
+
Requires-Dist: retry==0.9.2
|
|
25
|
+
Requires-Dist: dill==0.3.8
|
|
26
|
+
Requires-Dist: simplejson==3.20.1
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[egg_info]
|
|
2
|
-
tag_build =
|
|
3
|
-
tag_date = 0
|
|
4
|
-
|
|
1
|
+
[egg_info]
|
|
2
|
+
tag_build =
|
|
3
|
+
tag_date = 0
|
|
4
|
+
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/__init__.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/assert_webhook.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/db/__init__.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/db/mysql_db.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/db/redis_db.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/exceptions.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/exit_code.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/extract.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/render_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/retry_assert.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/startapp.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/__init__.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/date_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/encrypt.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/lark_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/log_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/mock_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/utils/yaml_util.py
RENAMED
|
File without changes
|
{pytest_api_framework_alpha-0.3.23 → pytest_api_framework_alpha-0.3.24}/framework/validate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|