From be8c053ed8eaf77bee426bc23201e95848be41a7 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Sat, 30 Apr 2022 15:06:31 +0800 Subject: [PATCH] refactor: format code with black --- docs/CHANGELOG.md | 1 + docs/data/api_server.py | 112 +- docs/data/debugtalk.py | 26 +- docs/examples/demo-klook/debugtalk.py | 2 +- .../utils/validators/validators_of_area.py | 10 +- httprunner/api.py | 97 +- httprunner/builtin/comparators.py | 2 +- httprunner/builtin/functions.py | 18 +- httprunner/cli.py | 92 +- httprunner/client.py | 53 +- httprunner/compat.py | 4 +- httprunner/context.py | 19 +- httprunner/exceptions.py | 3 +- httprunner/ext/locusts/cli.py | 57 +- httprunner/ext/locusts/locustfile_template.py | 6 +- httprunner/ext/locusts/utils.py | 2 +- httprunner/ext/uploader/__init__.py | 15 +- httprunner/loader/__init__.py | 8 +- httprunner/loader/buildup.py | 73 +- httprunner/loader/check.py | 41 +- httprunner/loader/load.py | 38 +- httprunner/loader/locate.py | 14 +- httprunner/logger.py | 18 +- httprunner/parser.py | 335 +++--- httprunner/report/__init__.py | 2 +- httprunner/report/html/__init__.py | 5 +- httprunner/report/html/gen_report.py | 17 +- httprunner/report/html/result.py | 29 +- httprunner/report/report.py | 24 +- httprunner/report/stringify.py | 19 +- httprunner/report/summarize.py | 48 +- httprunner/response.py | 68 +- httprunner/runner.py | 47 +- httprunner/utils.py | 192 ++-- httprunner/validator.py | 59 +- tests/api_server.py | 96 +- tests/base.py | 36 +- tests/debugtalk.py | 44 +- tests/test_api.py | 359 +++---- tests/test_apiserver.py | 53 +- tests/test_cli.py | 3 +- tests/test_client.py | 29 +- tests/test_context.py | 97 +- tests/test_extension/test_locusts.py | 6 +- tests/test_loader/test_cases.py | 156 ++- tests/test_loader/test_check.py | 25 +- tests/test_loader/test_load.py | 79 +- tests/test_loader/test_locate.py | 14 +- tests/test_parser.py | 991 ++++++++---------- tests/test_response.py | 196 ++-- tests/test_runner.py | 188 ++-- tests/test_utils.py | 135 +-- 52 files changed, 1809 insertions(+), 2254 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1e3e99fa..8593d3f8 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,7 @@ - fix #1217: reload debugtalk.py if loaded - fix #1246: catch exceptions caused by GA report failure +- refactor: format code with black ## 2.5.8 (2022-03-23) diff --git a/docs/data/api_server.py b/docs/data/api_server.py index bff04ddf..41879c87 100644 --- a/docs/data/api_server.py +++ b/docs/data/api_server.py @@ -37,42 +37,37 @@ token_dict = {} def gen_random_string(str_len): - """ generate random string with specified length - """ - return ''.join( - random.choice(string.ascii_letters + string.digits) for _ in range(str_len)) + """generate random string with specified length""" + return "".join( + random.choice(string.ascii_letters + string.digits) for _ in range(str_len) + ) + def get_sign(*args): - content = ''.join(args).encode('ascii') - sign_key = SECRET_KEY.encode('ascii') + content = "".join(args).encode("ascii") + sign_key = SECRET_KEY.encode("ascii") sign = hmac.new(sign_key, content, hashlib.sha1).hexdigest() return sign + def gen_md5(*args): - return hashlib.md5("".join(args).encode('utf-8')).hexdigest() + return hashlib.md5("".join(args).encode("utf-8")).hexdigest() def validate_request(func): - @wraps(func) def wrapper(*args, **kwargs): - device_sn = request.headers.get('device_sn', "") - token = request.headers.get('token', "") + device_sn = request.headers.get("device_sn", "") + token = request.headers.get("token", "") if not device_sn or not token: - result = { - 'success': False, - 'msg': "device_sn or token is null." - } + result = {"success": False, "msg": "device_sn or token is null."} response = make_response(json.dumps(result), 401) response.headers["Content-Type"] = "application/json" return response if token_dict.get(device_sn) != token: - result = { - 'success': False, - 'msg': "Authorization failed!" - } + result = {"success": False, "msg": "Authorization failed!"} response = make_response(json.dumps(result), 403) response.headers["Content-Type"] = "application/json" return response @@ -82,107 +77,89 @@ def validate_request(func): return wrapper -@app.route('/') +@app.route("/") def index(): return "Hello World!" -@app.route('/api/get-token', methods=['POST']) + +@app.route("/api/get-token", methods=["POST"]) def get_token(): - device_sn = request.headers.get('device_sn', "") - os_platform = request.headers.get('os_platform', "") - app_version = request.headers.get('app_version', "") + device_sn = request.headers.get("device_sn", "") + os_platform = request.headers.get("os_platform", "") + app_version = request.headers.get("app_version", "") data = request.get_json() - sign = data.get('sign', "") + sign = data.get("sign", "") expected_sign = get_sign(device_sn, os_platform, app_version) if expected_sign != sign: - result = { - 'success': False, - 'msg': "Authorization failed!" - } + result = {"success": False, "msg": "Authorization failed!"} response = make_response(json.dumps(result), 403) else: token = gen_random_string(16) token_dict[device_sn] = token - result = { - 'success': True, - 'token': token - } + result = {"success": True, "token": token} response = make_response(json.dumps(result)) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users') + +@app.route("/api/users") @validate_request def get_users(): users_list = [user for uid, user in users_dict.items()] - users = { - 'success': True, - 'count': len(users_list), - 'items': users_list - } + users = {"success": True, "count": len(users_list), "items": users_list} response = make_response(json.dumps(users)) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/reset-all') + +@app.route("/api/reset-all") @validate_request def clear_users(): users_dict.clear() - result = { - 'success': True - } + result = {"success": True} response = make_response(json.dumps(result)) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users/', methods=['POST']) + +@app.route("/api/users/", methods=["POST"]) @validate_request def create_user(uid): user = request.get_json() if uid not in users_dict: - result = { - 'success': True, - 'msg': "user created successfully." - } + result = {"success": True, "msg": "user created successfully."} status_code = 201 users_dict[uid] = user else: - result = { - 'success': False, - 'msg': "user already existed." - } + result = {"success": False, "msg": "user already existed."} status_code = 500 response = make_response(json.dumps(result), status_code) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users/') + +@app.route("/api/users/") @validate_request def get_user(uid): user = users_dict.get(uid, {}) if user: - result = { - 'success': True, - 'data': user - } + result = {"success": True, "data": user} status_code = 200 else: - result = { - 'success': False, - 'data': user - } + result = {"success": False, "data": user} status_code = 404 response = make_response(json.dumps(result), status_code) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users/', methods=['PUT']) + +@app.route("/api/users/", methods=["PUT"]) @validate_request def update_user(uid): user = users_dict.get(uid, {}) @@ -195,15 +172,13 @@ def update_user(uid): success = False status_code = 404 - result = { - 'success': success, - 'data': user - } + result = {"success": success, "data": user} response = make_response(json.dumps(result), status_code) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users/', methods=['DELETE']) + +@app.route("/api/users/", methods=["DELETE"]) @validate_request def delete_user(uid): user = users_dict.pop(uid, {}) @@ -214,10 +189,7 @@ def delete_user(uid): success = False status_code = 404 - result = { - 'success': success, - 'data': user - } + result = {"success": success, "data": user} response = make_response(json.dumps(result), status_code) response.headers["Content-Type"] = "application/json" return response diff --git a/docs/data/debugtalk.py b/docs/data/debugtalk.py index 53b56d02..3fbab973 100644 --- a/docs/data/debugtalk.py +++ b/docs/data/debugtalk.py @@ -6,43 +6,41 @@ import time SECRET_KEY = "DebugTalk" + def gen_random_string(str_len): random_char_list = [] for _ in range(str_len): random_char = random.choice(string.ascii_letters + string.digits) random_char_list.append(random_char) - random_string = ''.join(random_char_list) + random_string = "".join(random_char_list) return random_string + def get_sign(*args): - content = ''.join(args).encode('ascii') - sign_key = SECRET_KEY.encode('ascii') + content = "".join(args).encode("ascii") + sign_key = SECRET_KEY.encode("ascii") sign = hmac.new(sign_key, content, hashlib.sha1).hexdigest() return sign + def gen_user_id(): return int(time.time() * 1000) + def get_user_id(): - return [ - {"user_id": 1001}, - {"user_id": 1002}, - {"user_id": 1003}, - {"user_id": 1004} - ] + return [{"user_id": 1001}, {"user_id": 1002}, {"user_id": 1003}, {"user_id": 1004}] + def get_account(num): accounts = [] - for index in range(1, num+1): + for index in range(1, num + 1): accounts.append( {"username": "user%s" % index, "password": str(index) * 6}, ) return accounts + def get_os_platform(): - return [ - {"os_platform": "ios"}, - {"os_platform": "android"} - ] + return [{"os_platform": "ios"}, {"os_platform": "android"}] diff --git a/docs/examples/demo-klook/debugtalk.py b/docs/examples/demo-klook/debugtalk.py index 7c2e552a..b8aaf032 100644 --- a/docs/examples/demo-klook/debugtalk.py +++ b/docs/examples/demo-klook/debugtalk.py @@ -7,5 +7,5 @@ __all__ = [ klook_len_eq, check_search_area_result, exists_default_group, - teardown_hook_set_encoding + teardown_hook_set_encoding, ] diff --git a/docs/examples/demo-klook/utils/validators/validators_of_area.py b/docs/examples/demo-klook/utils/validators/validators_of_area.py index d91d75b7..8995f78a 100644 --- a/docs/examples/demo-klook/utils/validators/validators_of_area.py +++ b/docs/examples/demo-klook/utils/validators/validators_of_area.py @@ -2,7 +2,7 @@ def check_search_area_result(content, expect_name): print(content, expect_name) found = False for item in content: - if item['fullName'] == expect_name: + if item["fullName"] == expect_name: found = True break assert found @@ -11,8 +11,12 @@ def check_search_area_result(content, expect_name): def exists_default_group(content, expect): found = False for item in content: - if item['defaultGroup']: - print('defaultGroup found, id={}, parentAreaId={}'.format(item['id'], item['parentAreaId'])) + if item["defaultGroup"]: + print( + "defaultGroup found, id={}, parentAreaId={}".format( + item["id"], item["parentAreaId"] + ) + ) found = True break assert found diff --git a/httprunner/api.py b/httprunner/api.py index 70bc9d8f..0da07490 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -1,28 +1,38 @@ import os import unittest -from httprunner import (__version__, exceptions, loader, logger, parser, - report, runner, utils) +from httprunner import ( + __version__, + exceptions, + loader, + logger, + parser, + report, + runner, + utils, +) from httprunner.utils import ga_client class HttpRunner(object): - """ Developer Interface: Main Interface - Usage: + """Developer Interface: Main Interface + Usage: - from httprunner.api import HttpRunner - runner = HttpRunner( - failfast=True, - save_tests=True, - log_level="INFO", - log_file="test.log" - ) - summary = runner.run(path_or_tests) + from httprunner.api import HttpRunner + runner = HttpRunner( + failfast=True, + save_tests=True, + log_level="INFO", + log_file="test.log" + ) + summary = runner.run(path_or_tests) """ - def __init__(self, failfast=False, save_tests=False, log_level="WARNING", log_file=None): - """ initialize HttpRunner. + def __init__( + self, failfast=False, save_tests=False, log_level="WARNING", log_file=None + ): + """initialize HttpRunner. Args: failfast (bool): stop the test run on the first error or failure. @@ -34,10 +44,7 @@ class HttpRunner(object): logger.setup_logger(log_level, log_file) self.exception_stage = "initialize HttpRunner()" - kwargs = { - "failfast": failfast, - "resultclass": report.HtmlTestResult - } + kwargs = {"failfast": failfast, "resultclass": report.HtmlTestResult} self.unittest_runner = unittest.TextTestRunner(**kwargs) self.test_loader = unittest.TestLoader() self.save_tests = save_tests @@ -45,7 +52,7 @@ class HttpRunner(object): self.project_working_directory = None def _add_tests(self, testcases): - """ initialize testcase with Runner() and add to test suite. + """initialize testcase with Runner() and add to test suite. Args: testcases (list): testcases list. @@ -54,9 +61,10 @@ class HttpRunner(object): unittest.TestSuite() """ + def _add_test(test_runner, test_dict): - """ add test to testcase. - """ + """add test to testcase.""" + def test(self): try: test_runner.run_test(test_dict) @@ -89,7 +97,7 @@ class HttpRunner(object): for testcase in testcases: config = testcase.get("config", {}) test_runner = runner.Runner(config) - TestSequense = type('TestSequense', (unittest.TestCase,), {}) + TestSequense = type("TestSequense", (unittest.TestCase,), {}) tests = testcase.get("teststeps", []) for index, test_dict in enumerate(tests): @@ -98,12 +106,13 @@ class HttpRunner(object): times = int(times) except ValueError: raise exceptions.ParamsError( - "times should be digit, given: {}".format(times)) + "times should be digit, given: {}".format(times) + ) for times_index in range(times): # suppose one testcase should not have more than 9999 steps, # and one step should not run more than 999 times. - test_method_name = 'test_{:04}_{:03}'.format(index, times_index) + test_method_name = "test_{:04}_{:03}".format(index, times_index) test_method = _add_test(test_runner, test_dict) setattr(TestSequense, test_method_name, test_method) @@ -116,7 +125,7 @@ class HttpRunner(object): return test_suite def _run_suite(self, test_suite): - """ run tests in test_suite + """run tests in test_suite Args: test_suite: unittest.TestSuite() @@ -140,7 +149,7 @@ class HttpRunner(object): return tests_results def _aggregate(self, tests_results): - """ aggregate results + """aggregate results Args: tests_results (list): list of (testcase, result) @@ -149,16 +158,12 @@ class HttpRunner(object): summary = { "success": True, "stat": { - "testcases": { - "total": len(tests_results), - "success": 0, - "fail": 0 - }, - "teststeps": {} + "testcases": {"total": len(tests_results), "success": 0, "fail": 0}, + "teststeps": {}, }, "time": {}, "platform": report.get_platform(), - "details": [] + "details": [], } for tests_result in tests_results: @@ -174,7 +179,9 @@ class HttpRunner(object): testcase_summary["name"] = testcase.config.get("name") testcase_summary["in_out"] = utils.get_testcase_io(testcase) - report.aggregate_stat(summary["stat"]["teststeps"], testcase_summary["stat"]) + report.aggregate_stat( + summary["stat"]["teststeps"], testcase_summary["stat"] + ) report.aggregate_stat(summary["time"], testcase_summary["time"]) summary["details"].append(testcase_summary) @@ -182,8 +189,7 @@ class HttpRunner(object): return summary def run_tests(self, tests_mapping): - """ run testcase/testsuite data - """ + """run testcase/testsuite data""" ga_client.track_event("RunAPITests", "hrun") project_mapping = tests_mapping.get("project_mapping", {}) self.project_working_directory = project_mapping.get("PWD", os.getcwd()) @@ -231,7 +237,7 @@ class HttpRunner(object): return self._summary def get_vars_out(self): - """ get variables and output + """get variables and output Returns: list: list of variables and output. if tests are parameterized, list items are corresponded to parameters. @@ -254,13 +260,10 @@ class HttpRunner(object): if not self._summary: return None - return [ - summary["in_out"] - for summary in self._summary["details"] - ] + return [summary["in_out"] for summary in self._summary["details"]] def run_path(self, path, dot_env_path=None, mapping=None): - """ run testcase/testsuite file or folder. + """run testcase/testsuite file or folder. Args: path (str): testcase/testsuite file/foler path. @@ -281,7 +284,7 @@ class HttpRunner(object): return self.run_tests(tests_mapping) def run(self, path_or_tests, dot_env_path=None, mapping=None): - """ main interface. + """main interface. Args: path_or_tests: @@ -298,8 +301,12 @@ class HttpRunner(object): if loader.is_test_path(path_or_tests): return self.run_path(path_or_tests, dot_env_path, mapping) elif loader.is_test_content(path_or_tests): - project_working_directory = path_or_tests.get("project_mapping", {}).get("PWD", os.getcwd()) + project_working_directory = path_or_tests.get("project_mapping", {}).get( + "PWD", os.getcwd() + ) loader.init_pwd(project_working_directory) return self.run_tests(path_or_tests) else: - raise exceptions.ParamsError("Invalid testcase path or testcases: {}".format(path_or_tests)) + raise exceptions.ParamsError( + "Invalid testcase path or testcases: {}".format(path_or_tests) + ) diff --git a/httprunner/builtin/comparators.py b/httprunner/builtin/comparators.py index 586a5965..a091dbb6 100644 --- a/httprunner/builtin/comparators.py +++ b/httprunner/builtin/comparators.py @@ -108,4 +108,4 @@ def _cast_to_int(expect_value): try: return int(expect_value) except Exception: - raise AssertionError("%r can't cast to int" % str(expect_value)) \ No newline at end of file + raise AssertionError("%r can't cast to int" % str(expect_value)) diff --git a/httprunner/builtin/functions.py b/httprunner/builtin/functions.py index d5b31c7a..152c1c4a 100644 --- a/httprunner/builtin/functions.py +++ b/httprunner/builtin/functions.py @@ -12,15 +12,14 @@ from httprunner.exceptions import ParamsError def gen_random_string(str_len): - """ generate random string with specified length - """ - return ''.join( - random.choice(string.ascii_letters + string.digits) for _ in range(str_len)) + """generate random string with specified length""" + return "".join( + random.choice(string.ascii_letters + string.digits) for _ in range(str_len) + ) def get_timestamp(str_len=13): - """ get timestamp string, length can only between 0 and 16 - """ + """get timestamp string, length can only between 0 and 16""" if isinstance(str_len, integer_types) and 0 < str_len < 17: return builtin_str(time.time()).replace(".", "")[:str_len] @@ -28,13 +27,10 @@ def get_timestamp(str_len=13): def get_current_date(fmt="%Y-%m-%d"): - """ get current date, default format is %Y-%m-%d - """ + """get current date, default format is %Y-%m-%d""" return datetime.datetime.now().strftime(fmt) def sleep(n_secs): - """ sleep n seconds - """ + """sleep n seconds""" time.sleep(n_secs) - diff --git a/httprunner/cli.py b/httprunner/cli.py index a3389955..ce7bb9f2 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -10,58 +10,63 @@ from httprunner.compat import is_py2 from httprunner.loader import load_cases from httprunner.logger import color_print, log_error from httprunner.report import gen_html_report -from httprunner.utils import (create_scaffold, get_python2_retire_msg, - prettify_json_file, init_sentry_sdk) +from httprunner.utils import ( + create_scaffold, + get_python2_retire_msg, + prettify_json_file, + init_sentry_sdk, +) init_sentry_sdk() def main(): - """ API test: parse command line options and run commands. - """ + """API test: parse command line options and run commands.""" if is_py2: color_print(get_python2_retire_msg(), "YELLOW") parser = argparse.ArgumentParser(description=__description__) parser.add_argument( - '-V', '--version', dest='version', action='store_true', - help="show version") + "-V", "--version", dest="version", action="store_true", help="show version" + ) parser.add_argument( - 'testfile_paths', nargs='*', - help="Specify api/testcase/testsuite file paths to run.") + "testfile_paths", + nargs="*", + help="Specify api/testcase/testsuite file paths to run.", + ) parser.add_argument( - '--log-level', default='INFO', - help="Specify logging level, default is INFO.") + "--log-level", default="INFO", help="Specify logging level, default is INFO." + ) + parser.add_argument("--log-file", help="Write logs to specified file path.") parser.add_argument( - '--log-file', - help="Write logs to specified file path.") + "--dot-env-path", + help="Specify .env file path, which is useful for keeping sensitive data.", + ) + parser.add_argument("--report-template", help="Specify report template path.") + parser.add_argument("--report-dir", help="Specify report save directory.") parser.add_argument( - '--dot-env-path', - help="Specify .env file path, which is useful for keeping sensitive data.") + "--report-file", + help="Specify report file path, this has higher priority than specifying report dir.", + ) parser.add_argument( - '--report-template', - help="Specify report template path.") + "--save-tests", + action="store_true", + default=False, + help="Save loaded/parsed/vars_out/summary json data to JSON files.", + ) parser.add_argument( - '--report-dir', - help="Specify report save directory.") + "--failfast", + action="store_true", + default=False, + help="Stop the test run on the first error or failure.", + ) + parser.add_argument("--startproject", help="Specify new project name.") parser.add_argument( - '--report-file', - help="Specify report file path, this has higher priority than specifying report dir.") - parser.add_argument( - '--save-tests', action='store_true', default=False, - help="Save loaded/parsed/vars_out/summary json data to JSON files.") - parser.add_argument( - '--failfast', action='store_true', default=False, - help="Stop the test run on the first error or failure.") - parser.add_argument( - '--startproject', - help="Specify new project name.") - parser.add_argument( - '--validate', nargs='*', - help="Validate YAML/JSON api/testcase/testsuite format.") - parser.add_argument( - '--prettify', nargs='*', - help="Prettify JSON testcase format.") + "--validate", + nargs="*", + help="Validate YAML/JSON api/testcase/testsuite format.", + ) + parser.add_argument("--prettify", nargs="*", help="Prettify JSON testcase format.") args = parser.parse_args() @@ -99,23 +104,28 @@ def main(): failfast=args.failfast, save_tests=args.save_tests, log_level=args.log_level, - log_file=args.log_file + log_file=args.log_file, ) err_code = 0 try: for path in args.testfile_paths: summary = runner.run(path, dot_env_path=args.dot_env_path) - report_dir = args.report_dir or os.path.join(runner.project_working_directory, "reports") + report_dir = args.report_dir or os.path.join( + runner.project_working_directory, "reports" + ) gen_html_report( summary, report_template=args.report_template, report_dir=report_dir, - report_file=args.report_file + report_file=args.report_file, ) - err_code |= (0 if summary and summary["success"] else 1) + err_code |= 0 if summary and summary["success"] else 1 except Exception as ex: - color_print("!!!!!!!!!! exception stage: {} !!!!!!!!!!".format(runner.exception_stage), "YELLOW") + color_print( + "!!!!!!!!!! exception stage: {} !!!!!!!!!!".format(runner.exception_stage), + "YELLOW", + ) color_print(str(ex), "RED") sentry_sdk.capture_exception(ex) err_code = 1 @@ -123,5 +133,5 @@ def main(): sys.exit(err_code) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/httprunner/client.py b/httprunner/client.py index cbef3a32..9acab9fb 100644 --- a/httprunner/client.py +++ b/httprunner/client.py @@ -5,8 +5,12 @@ import time import requests import urllib3 from requests import Request, Response -from requests.exceptions import (InvalidSchema, InvalidURL, MissingSchema, - RequestException) +from requests.exceptions import ( + InvalidSchema, + InvalidURL, + MissingSchema, + RequestException, +) from httprunner import logger, response from httprunner.utils import lower_dict_keys, omit_long_data @@ -15,18 +19,15 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def get_req_resp_record(resp_obj): - """ get request and response info from Response() object. - """ + """get request and response info from Response() object.""" + def log_print(req_resp_dict, r_type): msg = "\n================== {} details ==================\n".format(r_type) for key, value in req_resp_dict[r_type].items(): msg += "{:<16} : {}\n".format(key, repr(value)) logger.log_debug(msg) - req_resp_dict = { - "request": {}, - "response": {} - } + req_resp_dict = {"request": {}, "response": {}} # record actual request info req_resp_dict["request"]["url"] = resp_obj.request.url @@ -35,9 +36,9 @@ def get_req_resp_record(resp_obj): request_body = resp_obj.request.body if request_body: - request_content_type = lower_dict_keys( - req_resp_dict["request"]["headers"] - ).get("content-type") + request_content_type = lower_dict_keys(req_resp_dict["request"]["headers"]).get( + "content-type" + ) if request_content_type and "multipart/form-data" in request_content_type: # upload file type req_resp_dict["request"]["body"] = "upload file stream (OMITTED)" @@ -83,9 +84,8 @@ def get_req_resp_record(resp_obj): class ApiResponse(Response): - def raise_for_status(self): - if hasattr(self, 'error') and self.error: + if hasattr(self, "error") and self.error: raise self.error Response.raise_for_status(self) @@ -99,35 +99,31 @@ class HttpSession(requests.Session): This is a slightly extended version of `python-request `_'s :py:class:`requests.Session` class and mostly this class works exactly the same. """ + def __init__(self): super(HttpSession, self).__init__() self.init_meta_data() def init_meta_data(self): - """ initialize meta_data, it will store detail data of request and response - """ + """initialize meta_data, it will store detail data of request and response""" self.meta_data = { "name": "", "data": [ { - "request": { - "url": "N/A", - "method": "N/A", - "headers": {} - }, + "request": {"url": "N/A", "method": "N/A", "headers": {}}, "response": { "status_code": "N/A", "headers": {}, "encoding": None, - "content_type": "" - } + "content_type": "", + }, } ], "stat": { "content_size": "N/A", "response_time_ms": "N/A", "elapsed_ms": "N/A", - } + }, } def update_last_req_resp_record(self, resp_obj): @@ -202,26 +198,23 @@ class HttpSession(requests.Session): self.meta_data["stat"] = { "response_time_ms": response_time_ms, "elapsed_ms": response.elapsed.microseconds / 1000.0, - "content_size": content_size + "content_size": content_size, } # record request and response histories, include 30X redirection response_list = response.history + [response] self.meta_data["data"] = [ - get_req_resp_record(resp_obj) - for resp_obj in response_list + get_req_resp_record(resp_obj) for resp_obj in response_list ] try: response.raise_for_status() except RequestException as e: - logger.log_error(u"{exception}".format(exception=str(e))) + logger.log_error("{exception}".format(exception=str(e))) else: logger.log_info( """status_code: {}, response_time(ms): {} ms, response_length: {} bytes\n""".format( - response.status_code, - response_time_ms, - content_size + response.status_code, response_time_ms, content_size ) ) diff --git a/httprunner/compat.py b/httprunner/compat.py index aa2a16ec..f74aaac7 100644 --- a/httprunner/compat.py +++ b/httprunner/compat.py @@ -23,10 +23,10 @@ import sys _ver = sys.version_info #: Python 2.x? -is_py2 = (_ver[0] == 2) +is_py2 = _ver[0] == 2 #: Python 3.x? -is_py3 = (_ver[0] == 3) +is_py3 = _ver[0] == 3 # --------- diff --git a/httprunner/context.py b/httprunner/context.py index c08af242..56a161e5 100644 --- a/httprunner/context.py +++ b/httprunner/context.py @@ -2,7 +2,7 @@ from httprunner import parser, utils class SessionContext(object): - """ HttpRunner session, store runtime variables. + """HttpRunner session, store runtime variables. Examples: >>> variables = {"SECRET_KEY": "DebugTalk"} @@ -16,12 +16,14 @@ class SessionContext(object): def __init__(self, variables=None): variables_mapping = utils.ensure_mapping_format(variables or {}) - self.session_variables_mapping = parser.parse_variables_mapping(variables_mapping) + self.session_variables_mapping = parser.parse_variables_mapping( + variables_mapping + ) self.test_variables_mapping = {} self.init_test_variables() def init_test_variables(self, variables_mapping=None): - """ init test variables, called when each test(api) starts. + """init test variables, called when each test(api) starts. variables_mapping will be evaluated first. Args: @@ -45,20 +47,19 @@ class SessionContext(object): self.test_variables_mapping.update(self.session_variables_mapping) def update_test_variables(self, variable_name, variable_value): - """ update test variables, these variables are only valid in the current test. - """ + """update test variables, these variables are only valid in the current test.""" self.test_variables_mapping[variable_name] = variable_value def update_session_variables(self, variables_mapping): - """ update session with extracted variables mapping. - these variables are valid in the whole running session. + """update session with extracted variables mapping. + these variables are valid in the whole running session. """ variables_mapping = utils.ensure_mapping_format(variables_mapping) self.session_variables_mapping.update(variables_mapping) self.test_variables_mapping.update(self.session_variables_mapping) def eval_content(self, content): - """ evaluate content recursively, take effect on each variable and function in content. - content may be in any data structure, include dict, list, tuple, number, string, etc. + """evaluate content recursively, take effect on each variable and function in content. + content may be in any data structure, include dict, list, tuple, number, string, etc. """ return parser.parse_lazy_data(content, self.test_variables_mapping) diff --git a/httprunner/exceptions.py b/httprunner/exceptions.py index 17bd8ee1..80a57e1d 100644 --- a/httprunner/exceptions.py +++ b/httprunner/exceptions.py @@ -81,5 +81,4 @@ class TestcaseNotFound(NotFoundError): class SummaryEmpty(MyBaseError): - """ test result summary data is empty - """ + """test result summary data is empty""" diff --git a/httprunner/ext/locusts/cli.py b/httprunner/ext/locusts/cli.py index 9c45b9d3..7124b8e1 100644 --- a/httprunner/ext/locusts/cli.py +++ b/httprunner/ext/locusts/cli.py @@ -1,6 +1,7 @@ try: # monkey patch ssl at beginning to avoid RecursionError when running locust. from gevent import monkey + monkey.patch_ssl() from locust import main as locust_main except ImportError: @@ -11,6 +12,7 @@ $ pip install locustio """ print(msg) import sys + sys.exit(0) import io @@ -26,9 +28,9 @@ init_sentry_sdk() def parse_locustfile(file_path): - """ parse testcase file and return locustfile path. - if file_path is a Python file, assume it is a locustfile - if file_path is a YAML/JSON file, convert it to locustfile + """parse testcase file and return locustfile path. + if file_path is a Python file, assume it is a locustfile + if file_path is a YAML/JSON file, convert it to locustfile """ if not os.path.isfile(file_path): logger.color_print("file path invalid, exit.", "RED") @@ -37,7 +39,7 @@ def parse_locustfile(file_path): file_suffix = os.path.splitext(file_path)[1] if file_suffix == ".py": locustfile_path = file_path - elif file_suffix in ['.yaml', '.yml', '.json']: + elif file_suffix in [".yaml", ".yml", ".json"]: locustfile_path = gen_locustfile(file_path) else: # '' or other suffix @@ -48,18 +50,18 @@ def parse_locustfile(file_path): def gen_locustfile(testcase_file_path): - """ generate locustfile from template. - """ - locustfile_path = 'locustfile.py' + """generate locustfile from template.""" + locustfile_path = "locustfile.py" template_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "locustfile_template.py" + os.path.dirname(os.path.realpath(__file__)), "locustfile_template.py" ) - with io.open(template_path, encoding='utf-8') as template: - with io.open(locustfile_path, 'w', encoding='utf-8') as locustfile: + with io.open(template_path, encoding="utf-8") as template: + with io.open(locustfile_path, "w", encoding="utf-8") as locustfile: template_content = template.read() - template_content = template_content.replace("$TESTCASE_FILE", testcase_file_path) + template_content = template_content.replace( + "$TESTCASE_FILE", testcase_file_path + ) locustfile.write(template_content) return locustfile_path @@ -67,6 +69,7 @@ def gen_locustfile(testcase_file_path): def start_locust_main(): from httprunner.utils import ga_client + ga_client.track_event("RunLoadTests", "locust") locust_main.main() @@ -106,10 +109,9 @@ def run_locusts_with_processes(sys_argv, processes_count): def main(): - """ Performance test with locust: parse command line options and run commands. - """ + """Performance test with locust: parse command line options and run commands.""" print("HttpRunner version: {}".format(__version__)) - sys.argv[0] = 'locust' + sys.argv[0] = "locust" if len(sys.argv) == 1: sys.argv.extend(["-h"]) @@ -147,29 +149,36 @@ def main(): sys.argv[testcase_index] = parse_locustfile(testcase_file_path) if "--processes" in sys.argv: - """ locusts -f locustfile.py --processes 4 - """ + """locusts -f locustfile.py --processes 4""" if "--no-web" in sys.argv: logger.log_error("conflict parameter args: --processes & --no-web. \nexit.") sys.exit(1) - processes_index = sys.argv.index('--processes') + processes_index = sys.argv.index("--processes") processes_count_index = processes_index + 1 if processes_count_index >= len(sys.argv): - """ do not specify processes count explicitly - locusts -f locustfile.py --processes + """do not specify processes count explicitly + locusts -f locustfile.py --processes """ processes_count = multiprocessing.cpu_count() - logger.log_warning("processes count not specified, use {} by default.".format(processes_count)) + logger.log_warning( + "processes count not specified, use {} by default.".format( + processes_count + ) + ) else: try: - """ locusts -f locustfile.py --processes 4 """ + """locusts -f locustfile.py --processes 4""" processes_count = int(sys.argv[processes_count_index]) sys.argv.pop(processes_count_index) except ValueError: - """ locusts -f locustfile.py --processes -P 8888 """ + """locusts -f locustfile.py --processes -P 8888""" processes_count = multiprocessing.cpu_count() - logger.log_warning("processes count not specified, use {} by default.".format(processes_count)) + logger.log_warning( + "processes count not specified, use {} by default.".format( + processes_count + ) + ) sys.argv.pop(processes_index) run_locusts_with_processes(sys.argv, processes_count) diff --git a/httprunner/ext/locusts/locustfile_template.py b/httprunner/ext/locusts/locustfile_template.py index 1ad06eb7..84a1c327 100644 --- a/httprunner/ext/locusts/locustfile_template.py +++ b/httprunner/ext/locusts/locustfile_template.py @@ -9,8 +9,8 @@ from httprunner.ext.locusts.utils import prepare_locust_tests from httprunner.runner import Runner logging.getLogger().setLevel(logging.CRITICAL) -logging.getLogger('locust.main').setLevel(logging.INFO) -logging.getLogger('locust.runners').setLevel(logging.INFO) +logging.getLogger("locust.main").setLevel(logging.INFO) +logging.getLogger("locust.runners").setLevel(logging.INFO) class WebPageTasks(TaskSet): @@ -28,7 +28,7 @@ class WebPageTasks(TaskSet): request_type=self.test_runner.exception_request_type, name=self.test_runner.exception_name, response_time=0, - exception=ex + exception=ex, ) diff --git a/httprunner/ext/locusts/utils.py b/httprunner/ext/locusts/utils.py index e1d5d881..b7fd6d8a 100644 --- a/httprunner/ext/locusts/utils.py +++ b/httprunner/ext/locusts/utils.py @@ -2,7 +2,7 @@ from httprunner import loader, parser def prepare_locust_tests(path): - """ prepare locust testcases + """prepare locust testcases Args: path (str): testcase file path. diff --git a/httprunner/ext/uploader/__init__.py b/httprunner/ext/uploader/__init__.py index fb299b1d..800901f8 100644 --- a/httprunner/ext/uploader/__init__.py +++ b/httprunner/ext/uploader/__init__.py @@ -61,7 +61,7 @@ from httprunner.exceptions import ParamsError def prepare_upload_test(test_dict): - """ preprocess for upload test + """preprocess for upload test replace `upload` info with MultipartEncoder Args: @@ -96,14 +96,15 @@ def prepare_upload_test(test_dict): test_dict["variables"]["m_encoder"] = "${multipart_encoder(" + params_str + ")}" test_dict["request"].setdefault("headers", {}) - test_dict["request"]["headers"]["Content-Type"] = "${multipart_content_type($m_encoder)}" + test_dict["request"]["headers"][ + "Content-Type" + ] = "${multipart_content_type($m_encoder)}" test_dict["request"]["data"] = "$m_encoder" def multipart_encoder(**kwargs): - """ initialize MultipartEncoder with uploading fields. - """ + """initialize MultipartEncoder with uploading fields.""" def get_filetype(file_path): file_type = filetype.guess(file_path) @@ -122,6 +123,7 @@ def multipart_encoder(**kwargs): else: # value is not absolute file path, check if it is relative file path from httprunner.loader import get_pwd + _file_path = os.path.join(get_pwd(), value) is_exists_file = os.path.isfile(_file_path) @@ -130,7 +132,7 @@ def multipart_encoder(**kwargs): filename = os.path.basename(_file_path) mime_type = get_filetype(_file_path) # TODO: fix ResourceWarning for unclosed file - file_handler = open(_file_path, 'rb') + file_handler = open(_file_path, "rb") fields_dict[key] = (filename, file_handler, mime_type) else: fields_dict[key] = value @@ -139,6 +141,5 @@ def multipart_encoder(**kwargs): def multipart_content_type(m_encoder): - """ prepare Content-Type for request headers - """ + """prepare Content-Type for request headers""" return m_encoder.content_type diff --git a/httprunner/loader/__init__.py b/httprunner/loader/__init__.py index 022cf410..d46a38c7 100644 --- a/httprunner/loader/__init__.py +++ b/httprunner/loader/__init__.py @@ -9,8 +9,10 @@ HttpRunner loader """ from httprunner.loader.check import is_test_path, is_test_content, JsonSchemaChecker -from httprunner.loader.locate import get_project_working_directory as get_pwd, \ - init_project_working_directory as init_pwd +from httprunner.loader.locate import ( + get_project_working_directory as get_pwd, + init_project_working_directory as init_pwd, +) from httprunner.loader.load import load_csv_file, load_builtin_functions from httprunner.loader.buildup import load_cases, load_project_data @@ -23,5 +25,5 @@ __all__ = [ "load_csv_file", "load_builtin_functions", "load_project_data", - "load_cases" + "load_cases", ] diff --git a/httprunner/loader/buildup.py b/httprunner/loader/buildup.py index 706aa965..87887c52 100644 --- a/httprunner/loader/buildup.py +++ b/httprunner/loader/buildup.py @@ -4,18 +4,22 @@ import sys from httprunner import exceptions, logger, utils from httprunner.loader.check import JsonSchemaChecker -from httprunner.loader.load import load_module_functions, load_file, load_dot_env_file, \ - load_folder_files -from httprunner.loader.locate import init_project_working_directory, get_project_working_directory +from httprunner.loader.load import ( + load_module_functions, + load_file, + load_dot_env_file, + load_folder_files, +) +from httprunner.loader.locate import ( + init_project_working_directory, + get_project_working_directory, +) -tests_def_mapping = { - "api": {}, - "testcases": {} -} +tests_def_mapping = {"api": {}, "testcases": {}} def load_debugtalk_functions(): - """ load project debugtalk.py module functions + """load project debugtalk.py module functions debugtalk.py should be located in project working directory. Returns: @@ -27,8 +31,8 @@ def load_debugtalk_functions(): """ # load debugtalk.py module - if sys.modules.get('debugtalk'): - imported_module = importlib.reload(sys.modules['debugtalk']) + if sys.modules.get("debugtalk"): + imported_module = importlib.reload(sys.modules["debugtalk"]) else: imported_module = importlib.import_module("debugtalk") @@ -36,7 +40,7 @@ def load_debugtalk_functions(): def __extend_with_api_ref(raw_testinfo): - """ extend with api reference + """extend with api reference Raises: exceptions.ApiNotFound: api not found @@ -68,17 +72,13 @@ def __extend_with_api_ref(raw_testinfo): def __extend_with_testcase_ref(raw_testinfo): - """ extend with testcase reference - """ + """extend with testcase reference""" testcase_path = raw_testinfo["testcase"] if testcase_path not in tests_def_mapping["testcases"]: # make compatible with Windows/Linux pwd = get_project_working_directory() - testcase_path = os.path.join( - pwd, - *testcase_path.split("/") - ) + testcase_path = os.path.join(pwd, *testcase_path.split("/")) loaded_testcase = load_file(testcase_path) if isinstance(loaded_testcase, list): @@ -89,7 +89,8 @@ def __extend_with_testcase_ref(raw_testinfo): testcase_dict = load_testcase_v2(loaded_testcase) else: raise exceptions.FileFormatError( - "Invalid format testcase: {}".format(testcase_path)) + "Invalid format testcase: {}".format(testcase_path) + ) tests_def_mapping["testcases"][testcase_path] = testcase_dict else: @@ -99,7 +100,7 @@ def __extend_with_testcase_ref(raw_testinfo): def load_teststep(raw_testinfo): - """ load testcase step content. + """load testcase step content. teststep maybe defined directly, or reference api/testcase. Args: @@ -151,7 +152,7 @@ def load_teststep(raw_testinfo): def load_testcase(raw_testcase): - """ load testcase with api/testcase references. + """load testcase with api/testcase references. Args: raw_testcase (list): raw testcase content loaded from JSON/YAML file: @@ -192,17 +193,16 @@ def load_testcase(raw_testcase): tests.append(load_teststep(test_block)) else: logger.log_warning( - "unexpected block key: {}. block key should only be 'config' or 'test'.".format(key) + "unexpected block key: {}. block key should only be 'config' or 'test'.".format( + key + ) ) - return { - "config": config, - "teststeps": tests - } + return {"config": config, "teststeps": tests} def load_testcase_v2(raw_testcase): - """ load testcase in format version 2. + """load testcase in format version 2. Args: raw_testcase (dict): raw testcase content loaded from JSON/YAML file: @@ -233,15 +233,12 @@ def load_testcase_v2(raw_testcase): """ JsonSchemaChecker.validate_testcase_v2_format(raw_testcase) raw_teststeps = raw_testcase.pop("teststeps") - raw_testcase["teststeps"] = [ - load_teststep(teststep) - for teststep in raw_teststeps - ] + raw_testcase["teststeps"] = [load_teststep(teststep) for teststep in raw_teststeps] return raw_testcase def load_testsuite(raw_testsuite): - """ load testsuite with testcase references. + """load testsuite with testcase references. support two different formats. Args: @@ -315,7 +312,7 @@ def load_testsuite(raw_testsuite): def load_test_file(path): - """ load test file, file maybe testcase/testsuite/api + """load test file, file maybe testcase/testsuite/api Args: path (str): test file path @@ -390,7 +387,7 @@ def load_test_file(path): def load_project_data(test_path, dot_env_path=None): - """ load api, testcases, .env, debugtalk.py functions. + """load api, testcases, .env, debugtalk.py functions. api/testcases folder is relative to project_working_directory Args: @@ -402,7 +399,9 @@ def load_project_data(test_path, dot_env_path=None): environments and debugtalk.py functions. """ - debugtalk_path, project_working_directory = init_project_working_directory(test_path) + debugtalk_path, project_working_directory = init_project_working_directory( + test_path + ) project_mapping = {} @@ -428,7 +427,7 @@ def load_project_data(test_path, dot_env_path=None): def load_cases(path, dot_env_path=None): - """ load testcases from file path, extend and merge with api/testcase definitions. + """load testcases from file path, extend and merge with api/testcase definitions. Args: path (str): testcase/testsuite file/foler path. @@ -481,9 +480,7 @@ def load_cases(path, dot_env_path=None): """ - tests_mapping = { - "project_mapping": load_project_data(path, dot_env_path) - } + tests_mapping = {"project_mapping": load_project_data(path, dot_env_path)} def __load_file_content(path): loaded_content = None diff --git a/httprunner/loader/check.py b/httprunner/loader/check.py index 35560d30..f0fdc3b3 100644 --- a/httprunner/loader/check.py +++ b/httprunner/loader/check.py @@ -15,12 +15,14 @@ testcase_schema_v2_path = os.path.join(schemas_root_dir, "testcase.schema.v2.jso testsuite_schema_v1_path = os.path.join(schemas_root_dir, "testsuite.schema.v1.json") testsuite_schema_v2_path = os.path.join(schemas_root_dir, "testsuite.schema.v2.json") -with io.open(api_schema_path, encoding='utf-8') as f: +with io.open(api_schema_path, encoding="utf-8") as f: api_schema = json.load(f) -with io.open(common_schema_path, encoding='utf-8') as f: +with io.open(common_schema_path, encoding="utf-8") as f: if platform.system() == "Windows": - absolute_base_path = 'file:///' + os.path.abspath(schemas_root_dir).replace("\\", "/") + '/' + absolute_base_path = ( + "file:///" + os.path.abspath(schemas_root_dir).replace("\\", "/") + "/" + ) else: # Linux, Darwin absolute_base_path = "file://" + os.path.abspath(schemas_root_dir) + "/" @@ -28,25 +30,23 @@ with io.open(common_schema_path, encoding='utf-8') as f: common_schema = json.load(f) resolver = jsonschema.RefResolver(absolute_base_path, common_schema) -with io.open(testcase_schema_v1_path, encoding='utf-8') as f: +with io.open(testcase_schema_v1_path, encoding="utf-8") as f: testcase_schema_v1 = json.load(f) -with io.open(testcase_schema_v2_path, encoding='utf-8') as f: +with io.open(testcase_schema_v2_path, encoding="utf-8") as f: testcase_schema_v2 = json.load(f) -with io.open(testsuite_schema_v1_path, encoding='utf-8') as f: +with io.open(testsuite_schema_v1_path, encoding="utf-8") as f: testsuite_schema_v1 = json.load(f) -with io.open(testsuite_schema_v2_path, encoding='utf-8') as f: +with io.open(testsuite_schema_v2_path, encoding="utf-8") as f: testsuite_schema_v2 = json.load(f) class JsonSchemaChecker(object): - @staticmethod def validate_format(content, scheme): - """ check api/testcase/testsuite format if valid - """ + """check api/testcase/testsuite format if valid""" try: jsonschema.validate(content, scheme, resolver=resolver) except jsonschema.exceptions.ValidationError as ex: @@ -57,37 +57,32 @@ class JsonSchemaChecker(object): @staticmethod def validate_api_format(content): - """ check api format if valid - """ + """check api format if valid""" return JsonSchemaChecker.validate_format(content, api_schema) @staticmethod def validate_testcase_v1_format(content): - """ check testcase format v1 if valid - """ + """check testcase format v1 if valid""" return JsonSchemaChecker.validate_format(content, testcase_schema_v1) @staticmethod def validate_testcase_v2_format(content): - """ check testcase format v2 if valid - """ + """check testcase format v2 if valid""" return JsonSchemaChecker.validate_format(content, testcase_schema_v2) @staticmethod def validate_testsuite_v1_format(content): - """ check testsuite format v1 if valid - """ + """check testsuite format v1 if valid""" return JsonSchemaChecker.validate_format(content, testsuite_schema_v1) @staticmethod def validate_testsuite_v2_format(content): - """ check testsuite format v2 if valid - """ + """check testsuite format v2 if valid""" return JsonSchemaChecker.validate_format(content, testsuite_schema_v2) def is_test_path(path): - """ check if path is valid json/yaml file path or a existed directory. + """check if path is valid json/yaml file path or a existed directory. Args: path (str/list/tuple): file path/directory or file path list. @@ -115,7 +110,7 @@ def is_test_path(path): if os.path.isfile(path): # path is a file file_suffix = os.path.splitext(path)[1].lower() - if file_suffix not in ['.json', '.yaml', '.yml']: + if file_suffix not in [".json", ".yaml", ".yml"]: # path is not json/yaml file return False else: @@ -129,7 +124,7 @@ def is_test_path(path): def is_test_content(data_structure): - """ check if data_structure is apis/testcases/testsuites. + """check if data_structure is apis/testcases/testsuites. Args: data_structure (dict): should include keys, apis or testcases or testsuites diff --git a/httprunner/loader/load.py b/httprunner/loader/load.py index 27fe0455..6e78d3b2 100644 --- a/httprunner/loader/load.py +++ b/httprunner/loader/load.py @@ -13,15 +13,14 @@ from httprunner.loader.locate import get_project_working_directory try: # PyYAML version >= 5.1 # ref: https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation - yaml.warnings({'YAMLLoadWarning': False}) + yaml.warnings({"YAMLLoadWarning": False}) except AttributeError: pass def _load_yaml_file(yaml_file): - """ load yaml file and check file content format - """ - with io.open(yaml_file, 'r', encoding='utf-8') as stream: + """load yaml file and check file content format""" + with io.open(yaml_file, "r", encoding="utf-8") as stream: try: yaml_content = yaml.load(stream) except yaml.YAMLError as ex: @@ -32,13 +31,12 @@ def _load_yaml_file(yaml_file): def _load_json_file(json_file): - """ load json file and check file content format - """ - with io.open(json_file, encoding='utf-8') as data_file: + """load json file and check file content format""" + with io.open(json_file, encoding="utf-8") as data_file: try: json_content = json.load(data_file) except exceptions.JSONDecodeError: - err_msg = u"JSONDecodeError: JSON file format error: {}".format(json_file) + err_msg = "JSONDecodeError: JSON file format error: {}".format(json_file) logger.log_error(err_msg) raise exceptions.FileFormatError(err_msg) @@ -46,7 +44,7 @@ def _load_json_file(json_file): def load_csv_file(csv_file): - """ load csv file and check file content format + """load csv file and check file content format Args: csv_file (str): csv file path, csv file content is like below: @@ -80,7 +78,7 @@ def load_csv_file(csv_file): csv_content_list = [] - with io.open(csv_file, encoding='utf-8') as csvfile: + with io.open(csv_file, encoding="utf-8") as csvfile: reader = csv.DictReader(csvfile) for row in reader: csv_content_list.append(row) @@ -93,21 +91,21 @@ def load_file(file_path): raise exceptions.FileNotFound("{} does not exist.".format(file_path)) file_suffix = os.path.splitext(file_path)[1].lower() - if file_suffix == '.json': + if file_suffix == ".json": return _load_json_file(file_path) - elif file_suffix in ['.yaml', '.yml']: + elif file_suffix in [".yaml", ".yml"]: return _load_yaml_file(file_path) elif file_suffix == ".csv": return load_csv_file(file_path) else: # '' or other suffix - err_msg = u"Unsupported file format: {}".format(file_path) + err_msg = "Unsupported file format: {}".format(file_path) logger.log_warning(err_msg) return [] def load_folder_files(folder_path, recursive=True): - """ load folder path, return all files endswith yml/yaml/json in list. + """load folder path, return all files endswith yml/yaml/json in list. Args: folder_path (str): specified folder path to load @@ -132,7 +130,7 @@ def load_folder_files(folder_path, recursive=True): filenames_list = [] for filename in filenames: - if not filename.endswith(('.yml', '.yaml', '.json')): + if not filename.endswith((".yml", ".yaml", ".json")): continue filenames_list.append(filename) @@ -148,7 +146,7 @@ def load_folder_files(folder_path, recursive=True): def load_dot_env_file(dot_env_path): - """ load .env file. + """load .env file. Args: dot_env_path (str): .env file path @@ -172,7 +170,7 @@ def load_dot_env_file(dot_env_path): logger.log_info("Loading environment variables from {}".format(dot_env_path)) env_variables_mapping = {} - with io.open(dot_env_path, 'r', encoding='utf-8') as fp: + with io.open(dot_env_path, "r", encoding="utf-8") as fp: for line in fp: # maxsplit=1 if "=" in line: @@ -189,7 +187,7 @@ def load_dot_env_file(dot_env_path): def load_module_functions(module): - """ load python module functions. + """load python module functions. Args: module: python module @@ -213,7 +211,5 @@ def load_module_functions(module): def load_builtin_functions(): - """ load builtin module functions - """ + """load builtin module functions""" return load_module_functions(builtin) - diff --git a/httprunner/loader/locate.py b/httprunner/loader/locate.py index 5fe7a5b3..fec58266 100644 --- a/httprunner/loader/locate.py +++ b/httprunner/loader/locate.py @@ -7,7 +7,7 @@ project_working_directory = None def locate_file(start_path, file_name): - """ locate filename and return absolute file path. + """locate filename and return absolute file path. searching will be recursive upward until current working directory or system root dir. Args: @@ -34,21 +34,25 @@ def locate_file(start_path, file_name): # current working directory if os.path.abspath(start_dir_path) == os.getcwd(): - raise exceptions.FileNotFound("{} not found in {}".format(file_name, start_path)) + raise exceptions.FileNotFound( + "{} not found in {}".format(file_name, start_path) + ) # system root dir # Windows, e.g. 'E:\\' # Linux/Darwin, '/' parent_dir = os.path.dirname(start_dir_path) if parent_dir == start_dir_path: - raise exceptions.FileNotFound("{} not found in {}".format(file_name, start_path)) + raise exceptions.FileNotFound( + "{} not found in {}".format(file_name, start_path) + ) # locate recursive upward return locate_file(parent_dir, file_name) def locate_debugtalk_py(start_path): - """ locate debugtalk.py file + """locate debugtalk.py file Args: start_path (str): start locating path, @@ -68,7 +72,7 @@ def locate_debugtalk_py(start_path): def init_project_working_directory(test_path): - """ this should be called at startup + """this should be called at startup run test file: run_path -> load_cases -> load_project_data -> init_project_working_directory diff --git a/httprunner/logger.py b/httprunner/logger.py index d16f9a09..f2f0bcca 100644 --- a/httprunner/logger.py +++ b/httprunner/logger.py @@ -11,11 +11,11 @@ LOG_LEVEL = "INFO" LOG_FILE_PATH = "" log_colors_config = { - 'DEBUG': 'cyan', - 'INFO': 'green', - 'WARNING': 'yellow', - 'ERROR': 'red', - 'CRITICAL': 'red', + "DEBUG": "cyan", + "INFO": "green", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "red", } loggers = {} @@ -58,10 +58,10 @@ def get_logger(name=None): handler = logging.StreamHandler(sys.stdout) formatter = ColoredFormatter( - u"%(log_color)s%(bg_white)s%(levelname)-8s%(reset)s %(message)s", + "%(log_color)s%(bg_white)s%(levelname)-8s%(reset)s %(message)s", datefmt=None, reset=True, - log_colors=log_colors_config + log_colors=log_colors_config, ) handler.setFormatter(formatter) _logger.addHandler(handler) @@ -81,8 +81,8 @@ def color_print(msg, color="WHITE"): def log_with_color(level): - """ log with color by different level - """ + """log with color by different level""" + def wrapper(text): color = log_colors_config[level.upper()] _logger = get_logger() diff --git a/httprunner/parser.py b/httprunner/parser.py index f1600d39..72912e6b 100644 --- a/httprunner/parser.py +++ b/httprunner/parser.py @@ -27,7 +27,7 @@ def get_parse_failed_testfiles(): def parse_string_value(str_value): - """ parse string to number if possible + """parse string to number if possible e.g. "123" => 123 "12.2" => 12.3 "abc" => "abc" @@ -43,8 +43,7 @@ def parse_string_value(str_value): def is_var_or_func_exist(content): - """ check if variable or function exist - """ + """check if variable or function exist""" if not isinstance(content, basestring): return False @@ -71,7 +70,7 @@ def is_var_or_func_exist(content): def regex_findall_variables(content): - """ extract all variable names from content, which is in format $variable + """extract all variable names from content, which is in format $variable Args: content (str): string content @@ -96,16 +95,14 @@ def regex_findall_variables(content): try: vars_list = [] for var_tuple in variable_regex_compile.findall(content): - vars_list.append( - var_tuple[0] or var_tuple[1] - ) + vars_list.append(var_tuple[0] or var_tuple[1]) return vars_list except TypeError: return [] def regex_findall_functions(content): - """ extract all functions from string content, which are in format ${fun()} + """extract all functions from string content, which are in format ${fun()} Args: content (str): string content @@ -137,7 +134,7 @@ def regex_findall_functions(content): def parse_parameters(parameters, variables_mapping=None, functions_mapping=None): - """ parse parameters and generate cartesian product. + """parse parameters and generate cartesian product. Args: parameters (list) parameters: parameter name and value in list @@ -188,13 +185,9 @@ def parse_parameters(parameters, variables_mapping=None, functions_mapping=None) parameter_content_list.append(parameter_content_dict) else: # (2) & (3) - parsed_variables_mapping = parse_variables_mapping( - variables_mapping - ) + parsed_variables_mapping = parse_variables_mapping(variables_mapping) parsed_parameter_content = eval_lazy_data( - parameter_content, - parsed_variables_mapping, - functions_mapping + parameter_content, parsed_variables_mapping, functions_mapping ) if not isinstance(parsed_parameter_content, list): raise exceptions.ParamsError("parameters syntax error!") @@ -210,7 +203,9 @@ def parse_parameters(parameters, variables_mapping=None, functions_mapping=None) # {"username": "user1", "password": "111111"}, # {"username": "user2", "password": "222222"} # ] - parameter_dict = {key: parameter_item[key] for key in parameter_name_list} + parameter_dict = { + key: parameter_item[key] for key in parameter_name_list + } elif isinstance(parameter_item, (list, tuple)): # {"username-password": "${get_account()}"} # get_account() => [("user1", "111111"), ("user2", "222222")] @@ -218,9 +213,7 @@ def parse_parameters(parameters, variables_mapping=None, functions_mapping=None) elif len(parameter_name_list) == 1: # {"user_agent": "${get_user_agent()}"} # get_user_agent() => ["iOS/10.1", "iOS/10.2"] - parameter_dict = { - parameter_name_list[0]: parameter_item - } + parameter_dict = {parameter_name_list[0]: parameter_item} parameter_content_list.append(parameter_dict) @@ -230,8 +223,7 @@ def parse_parameters(parameters, variables_mapping=None, functions_mapping=None) def get_uniform_comparator(comparator): - """ convert comparator alias to uniform name - """ + """convert comparator alias to uniform name""" if comparator in ["eq", "equals", "==", "is"]: return "equals" elif comparator in ["lt", "less_than"]: @@ -248,22 +240,35 @@ def get_uniform_comparator(comparator): return "string_equals" elif comparator in ["len_eq", "length_equals", "count_eq"]: return "length_equals" - elif comparator in ["len_gt", "count_gt", "length_greater_than", "count_greater_than"]: + elif comparator in [ + "len_gt", + "count_gt", + "length_greater_than", + "count_greater_than", + ]: return "length_greater_than" - elif comparator in ["len_ge", "count_ge", "length_greater_than_or_equals", - "count_greater_than_or_equals"]: + elif comparator in [ + "len_ge", + "count_ge", + "length_greater_than_or_equals", + "count_greater_than_or_equals", + ]: return "length_greater_than_or_equals" elif comparator in ["len_lt", "count_lt", "length_less_than", "count_less_than"]: return "length_less_than" - elif comparator in ["len_le", "count_le", "length_less_than_or_equals", - "count_less_than_or_equals"]: + elif comparator in [ + "len_le", + "count_le", + "length_less_than_or_equals", + "count_less_than_or_equals", + ]: return "length_less_than_or_equals" else: return comparator def uniform_validator(validator): - """ unify validator + """unify validator Args: validator (dict): validator maybe in two formats: @@ -310,15 +315,11 @@ def uniform_validator(validator): # uniform comparator, e.g. lt => less_than, eq => equals comparator = get_uniform_comparator(comparator) - return { - "check": check_item, - "expect": expect_value, - "comparator": comparator - } + return {"check": check_item, "expect": expect_value, "comparator": comparator} def _convert_validators_to_mapping(validators): - """ convert validators list to mapping. + """convert validators list to mapping. Args: validators (list): validators in list @@ -353,7 +354,7 @@ def _convert_validators_to_mapping(validators): def extend_validators(raw_validators, override_validators): - """ extend raw_validators with override_validators. + """extend raw_validators with override_validators. override_validators will merge and override raw_validators. Args: @@ -393,8 +394,9 @@ def extend_validators(raw_validators, override_validators): ## parse content with variables and functions mapping ############################################################################### + def get_mapping_variable(variable_name, variables_mapping): - """ get variable from variables_mapping. + """get variable from variables_mapping. Args: variable_name (str): variable name @@ -414,7 +416,7 @@ def get_mapping_variable(variable_name, variables_mapping): def get_mapping_function(function_name, functions_mapping): - """ get function from functions_mapping, + """get function from functions_mapping, if not found, then try to check if builtin function. Args: @@ -440,6 +442,7 @@ def get_mapping_function(function_name, functions_mapping): elif function_name in ["multipart_encoder", "multipart_content_type"]: # extension for upload test from httprunner.ext import uploader + return getattr(uploader, function_name) try: @@ -459,7 +462,7 @@ def get_mapping_function(function_name, functions_mapping): def parse_function_params(params): - """ parse function params to args and kwargs. + """parse function params to args and kwargs. Args: params (str): function param in string @@ -489,20 +492,17 @@ def parse_function_params(params): {'args': [1, 2], 'kwargs': {'a':3, 'b':4}} """ - function_meta = { - "args": [], - "kwargs": {} - } + function_meta = {"args": [], "kwargs": {}} params_str = params.strip() if params_str == "": return function_meta - args_list = params_str.split(',') + args_list = params_str.split(",") for arg in args_list: arg = arg.strip() - if '=' in arg: - key, value = arg.split('=') + if "=" in arg: + key, value = arg.split("=") function_meta["kwargs"][key.strip()] = parse_string_value(value.strip()) else: function_meta["args"].append(parse_string_value(arg)) @@ -511,11 +511,10 @@ def parse_function_params(params): class LazyFunction(object): - """ call function lazily. - """ + """call function lazily.""" def __init__(self, function_meta, functions_mapping=None, check_variables_set=None): - """ init LazyFunction object with function_meta + """init LazyFunction object with function_meta Args: function_meta (dict): function name, args and kwargs. @@ -532,25 +531,24 @@ class LazyFunction(object): self.__parse(function_meta) def __parse(self, function_meta): - """ init func as lazy functon instance + """init func as lazy functon instance Args: function_meta (dict): function meta including name, args and kwargs """ self._func = get_mapping_function( - function_meta["func_name"], - self.functions_mapping + function_meta["func_name"], self.functions_mapping ) self.func_name = self._func.__name__ self._args = prepare_lazy_data( function_meta.get("args", []), self.functions_mapping, - self.check_variables_set + self.check_variables_set, ) self._kwargs = prepare_lazy_data( function_meta.get("kwargs", {}), self.functions_mapping, - self.check_variables_set + self.check_variables_set, ) if self.func_name == "load_csv_file": @@ -578,8 +576,7 @@ class LazyFunction(object): if self._kwargs: args_string += ", " str_kwargs = [ - "{}={}".format(key, str(value)) - for key, value in self._kwargs.items() + "{}={}".format(key, str(value)) for key, value in self._kwargs.items() ] args_string += ", ".join(str_kwargs) @@ -589,8 +586,8 @@ class LazyFunction(object): return self.func_name, repr(args), repr(kwargs) def to_value(self, variables_mapping=None): - """ parse lazy data with evaluated variables mapping. - Notice: variables_mapping should not contain any variable or function. + """parse lazy data with evaluated variables mapping. + Notice: variables_mapping should not contain any variable or function. """ variables_mapping = variables_mapping or {} args = parse_lazy_data(self._args, variables_mapping) @@ -605,12 +602,13 @@ cached_functions_mapping = {} class LazyString(object): - """ evaluate string lazily. - """ + """evaluate string lazily.""" - def __init__(self, raw_string, functions_mapping=None, check_variables_set=None, cached=False): - """ make raw_string as lazy object with functions_mapping - check if any variable undefined in check_variables_set + def __init__( + self, raw_string, functions_mapping=None, check_variables_set=None, cached=False + ): + """make raw_string as lazy object with functions_mapping + check if any variable undefined in check_variables_set """ self.raw_string = raw_string self.functions_mapping = functions_mapping or {} @@ -619,7 +617,7 @@ class LazyString(object): self.__parse(raw_string) def __parse(self, raw_string): - """ parse raw string, replace function and variable with {} + """parse raw string, replace function and variable with {} Args: raw_string(str): string with functions or varialbes @@ -658,14 +656,10 @@ class LazyString(object): # search function like ${func($a, $b)} func_match = function_regex_compile.match(raw_string, match_start_position) if func_match: - function_meta = { - "func_name": func_match.group(1) - } + function_meta = {"func_name": func_match.group(1)} function_meta.update(parse_function_params(func_match.group(2))) lazy_func = LazyFunction( - function_meta, - self.functions_mapping, - self.check_variables_set + function_meta, self.functions_mapping, self.check_variables_set ) self._args.append(lazy_func) match_start_position = func_match.end() @@ -701,15 +695,19 @@ class LazyString(object): return "LazyString({})".format(self.raw_string) def to_value(self, variables_mapping=None): - """ parse lazy data with evaluated variables mapping. - Notice: variables_mapping should not contain any variable or function. + """parse lazy data with evaluated variables mapping. + Notice: variables_mapping should not contain any variable or function. """ variables_mapping = variables_mapping or {} args = [] for arg in self._args: if isinstance(arg, LazyFunction): - if self.cached and arg.cache_key and arg.cache_key in cached_functions_mapping: + if ( + self.cached + and arg.cache_key + and arg.cache_key in cached_functions_mapping + ): value = cached_functions_mapping[arg.cache_key] else: value = arg.to_value(variables_mapping) @@ -726,8 +724,10 @@ class LazyString(object): return self._string.format(*args) -def prepare_lazy_data(content, functions_mapping=None, check_variables_set=None, cached=False): - """ make string in content as lazy object with functions_mapping +def prepare_lazy_data( + content, functions_mapping=None, check_variables_set=None, cached=False +): + """make string in content as lazy object with functions_mapping Raises: exceptions.VariableNotFound: if any variable undefined in check_variables_set @@ -739,12 +739,7 @@ def prepare_lazy_data(content, functions_mapping=None, check_variables_set=None, elif isinstance(content, (list, set, tuple)): return [ - prepare_lazy_data( - item, - functions_mapping, - check_variables_set, - cached - ) + prepare_lazy_data(item, functions_mapping, check_variables_set, cached) for item in content ] @@ -752,16 +747,10 @@ def prepare_lazy_data(content, functions_mapping=None, check_variables_set=None, parsed_content = {} for key, value in content.items(): parsed_key = prepare_lazy_data( - key, - functions_mapping, - check_variables_set, - cached + key, functions_mapping, check_variables_set, cached ) parsed_value = prepare_lazy_data( - value, - functions_mapping, - check_variables_set, - cached + value, functions_mapping, check_variables_set, cached ) parsed_content[parsed_key] = parsed_value @@ -783,8 +772,8 @@ def prepare_lazy_data(content, functions_mapping=None, check_variables_set=None, def parse_lazy_data(content, variables_mapping=None): - """ parse lazy data with evaluated variables mapping. - Notice: variables_mapping should not contain any variable or function. + """parse lazy data with evaluated variables mapping. + Notice: variables_mapping should not contain any variable or function. """ # TODO: refactor type check if content is None or isinstance(content, (numeric_types, bool, type)): @@ -795,10 +784,7 @@ def parse_lazy_data(content, variables_mapping=None): return content.to_value(variables_mapping) elif isinstance(content, (list, set, tuple)): - return [ - parse_lazy_data(item, variables_mapping) - for item in content - ] + return [parse_lazy_data(item, variables_mapping) for item in content] elif isinstance(content, dict): parsed_content = {} @@ -813,24 +799,19 @@ def parse_lazy_data(content, variables_mapping=None): def eval_lazy_data(content, variables_mapping=None, functions_mapping=None): - """ evaluate data instantly. - Notice: variables_mapping should not contain any variable or function. + """evaluate data instantly. + Notice: variables_mapping should not contain any variable or function. """ variables_mapping = variables_mapping or {} check_variables_set = set(variables_mapping.keys()) return parse_lazy_data( - prepare_lazy_data( - content, - functions_mapping, - check_variables_set - ), - variables_mapping + prepare_lazy_data(content, functions_mapping, check_variables_set), + variables_mapping, ) def extract_variables(content): - """ extract all variables in content recursively. - """ + """extract all variables in content recursively.""" if isinstance(content, (list, set, tuple)): variables = set() for item in content: @@ -850,7 +831,7 @@ def extract_variables(content): def parse_variables_mapping(variables_mapping): - """ eval each prepared variable and function in variables_mapping. + """eval each prepared variable and function in variables_mapping. Args: variables_mapping (dict): @@ -911,7 +892,12 @@ def parse_variables_mapping(variables_mapping): # reference other variable, or function call with other variable # e.g. {"varA": "123$varB", "varB": "456$varC"} # e.g. {"varC": "${sum_two($a, $b)}"} - if any([_var_name not in parsed_variables_mapping for _var_name in variables]): + if any( + [ + _var_name not in parsed_variables_mapping + for _var_name in variables + ] + ): # reference variable not parsed continue @@ -922,7 +908,7 @@ def parse_variables_mapping(variables_mapping): def _extend_with_api(test_dict, api_def_dict): - """ extend test with api definition, test will merge and override api definition. + """extend test with api definition, test will merge and override api definition. Args: test_dict (dict): test block, this will override api_def_dict @@ -955,27 +941,21 @@ def _extend_with_api(test_dict, api_def_dict): # override variables def_variables = api_def_dict.pop("variables", []) test_dict["variables"] = utils.extend_variables( - def_variables, - test_dict.get("variables", {}) + def_variables, test_dict.get("variables", {}) ) # merge & override validators TODO: relocate def_raw_validators = api_def_dict.pop("validate", []) def_validators = [ - uniform_validator(_validator) - for _validator in def_raw_validators + uniform_validator(_validator) for _validator in def_raw_validators ] ref_validators = test_dict.pop("validate", []) - test_dict["validate"] = extend_validators( - def_validators, - ref_validators - ) + test_dict["validate"] = extend_validators(def_validators, ref_validators) # merge & override extractors def_extrators = api_def_dict.pop("extract", {}) test_dict["extract"] = utils.extend_variables( - def_extrators, - test_dict.get("extract", {}) + def_extrators, test_dict.get("extract", {}) ) # merge & override request @@ -1010,7 +990,7 @@ def _extend_with_api(test_dict, api_def_dict): def _extend_with_testcase(test_dict, testcase_def_dict): - """ extend test with testcase definition + """extend test with testcase definition test will merge and override testcase config definition. Args: @@ -1024,7 +1004,8 @@ def _extend_with_testcase(test_dict, testcase_def_dict): # override testcase config variables testcase_def_dict["config"].setdefault("variables", {}) testcase_def_variables = utils.ensure_mapping_format( - testcase_def_dict["config"].get("variables", {})) + testcase_def_dict["config"].get("variables", {}) + ) testcase_def_variables.update(test_dict.pop("variables", {})) testcase_def_dict["config"]["variables"] = testcase_def_variables @@ -1035,9 +1016,11 @@ def _extend_with_testcase(test_dict, testcase_def_dict): testcase_def_dict["config"]["base_url"] = test_base_url # override name - test_name = test_dict.pop("name", None) \ - or testcase_def_dict["config"].pop("name", None) \ - or "testcase name undefined" + test_name = ( + test_dict.pop("name", None) + or testcase_def_dict["config"].pop("name", None) + or "testcase name undefined" + ) # override testcase config name, output, etc. testcase_def_dict["config"].update(test_dict) @@ -1048,8 +1031,7 @@ def _extend_with_testcase(test_dict, testcase_def_dict): def __prepare_config(config, project_mapping, session_variables_set=None): - """ parse testcase/testsuite config. - """ + """parse testcase/testsuite config.""" # get config variables raw_config_variables = config.pop("variables", {}) @@ -1057,7 +1039,8 @@ def __prepare_config(config, project_mapping, session_variables_set=None): functions = project_mapping.get("functions", {}) if isinstance(raw_config_variables, basestring) and function_regex_compile.match( - raw_config_variables): + raw_config_variables + ): # config variables are generated by calling function # e.g. # "config": { @@ -1077,13 +1060,17 @@ def __prepare_config(config, project_mapping, session_variables_set=None): config["variables"] = raw_config_variables_mapping check_variables_set = set(raw_config_variables_mapping.keys()) - check_variables_set |= (session_variables_set or set()) - prepared_config = prepare_lazy_data(config, functions, check_variables_set, cached=True) + check_variables_set |= session_variables_set or set() + prepared_config = prepare_lazy_data( + config, functions, check_variables_set, cached=True + ) return prepared_config -def __prepare_testcase_tests(tests, config, project_mapping, session_variables_set=None): - """ override tests with testcase config variables, base_url and verify. +def __prepare_testcase_tests( + tests, config, project_mapping, session_variables_set=None +): + """override tests with testcase config variables, base_url and verify. test maybe nested testcase. variables priority: @@ -1107,7 +1094,9 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s functions = project_mapping.get("functions", {}) prepared_testcase_tests = [] - session_variables_set = set(config_variables.keys()) | (session_variables_set or set()) + session_variables_set = set(config_variables.keys()) | ( + session_variables_set or set() + ) for test_dict in tests: teststep_variables_set = {"request", "response"} @@ -1115,8 +1104,7 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s # 1, testcase config => testcase tests # override test_dict variables test_dict_variables = utils.extend_variables( - test_dict.pop("variables", {}), - config_variables + test_dict.pop("variables", {}), config_variables ) test_dict["variables"] = test_dict_variables @@ -1128,8 +1116,7 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s if "validate" in test_dict: ref_raw_validators = test_dict.pop("validate", []) test_dict["validate"] = [ - uniform_validator(_validator) - for _validator in ref_raw_validators + uniform_validator(_validator) for _validator in ref_raw_validators ] if "testcase_def" in test_dict: @@ -1152,7 +1139,9 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s test_dict["config"].setdefault("verify", config_verify) # 3, testcase_def config => testcase_def test_dict - test_dict = _parse_testcase(test_dict, project_mapping, session_variables_set) + test_dict = _parse_testcase( + test_dict, project_mapping, session_variables_set + ) if not test_dict: continue @@ -1169,6 +1158,7 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s if "upload" in test_dict["request"]: from httprunner.ext.uploader import prepare_upload_test + prepare_upload_test(test_dict) # current teststep variables @@ -1187,27 +1177,18 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s for _validator in validators: function_meta = { "func_name": _validator["comparator"], - "args": [ - _validator["check"], - _validator["expect"] - ], - "kwargs": {} + "args": [_validator["check"], _validator["expect"]], + "kwargs": {}, } prepared_validators.append( - LazyFunction( - function_meta, - functions, - teststep_variables_set - ) + LazyFunction(function_meta, functions, teststep_variables_set) ) test_dict["validate"] = prepared_validators # convert variables and functions to lazy object. # raises VariableNotFound if undefined variable exists in test_dict prepared_test_dict = prepare_lazy_data( - test_dict, - functions, - teststep_variables_set + test_dict, functions, teststep_variables_set ) prepared_testcase_tests.append(prepared_test_dict) @@ -1215,7 +1196,7 @@ def __prepare_testcase_tests(tests, config, project_mapping, session_variables_s def _parse_testcase(testcase, project_mapping, session_variables_set=None): - """ parse testcase + """parse testcase Args: testcase (dict): @@ -1229,25 +1210,22 @@ def _parse_testcase(testcase, project_mapping, session_variables_set=None): try: prepared_config = __prepare_config( - testcase["config"], - project_mapping, - session_variables_set + testcase["config"], project_mapping, session_variables_set ) prepared_testcase_tests = __prepare_testcase_tests( testcase["teststeps"], prepared_config, project_mapping, - session_variables_set + session_variables_set, ) - return { - "config": prepared_config, - "teststeps": prepared_testcase_tests - } + return {"config": prepared_config, "teststeps": prepared_testcase_tests} except (exceptions.MyBaseFailure, exceptions.MyBaseError) as ex: testcase_type = testcase["type"] testcase_path = testcase.get("path") - logger.log_error("failed to parse testcase: {}, error: {}".format(testcase_path, ex)) + logger.log_error( + "failed to parse testcase: {}, error: {}".format(testcase_path, ex) + ) global parse_failed_testfiles if testcase_type not in parse_failed_testfiles: @@ -1259,7 +1237,7 @@ def _parse_testcase(testcase, project_mapping, session_variables_set=None): def __get_parsed_testsuite_testcases(testcases, testsuite_config, project_mapping): - """ override testscases with testsuite config variables, base_url and verify. + """override testscases with testsuite config variables, base_url and verify. variables priority: parameters > testsuite config > testcase config > testcase_def config > testcase_def tests > api @@ -1323,45 +1301,46 @@ def __get_parsed_testsuite_testcases(testcases, testsuite_config, project_mappin # 1, testsuite config => testcase config # override test_dict variables testcase_config_variables = utils.extend_variables( - testcase.pop("variables", {}), - testsuite_config_variables + testcase.pop("variables", {}), testsuite_config_variables ) # 2, testcase config > testcase_def config # override testcase_def config variables overrided_testcase_config_variables = utils.extend_variables( - parsed_testcase["config"].pop("variables", {}), - testcase_config_variables + parsed_testcase["config"].pop("variables", {}), testcase_config_variables ) if overrided_testcase_config_variables: parsed_testcase["config"]["variables"] = overrided_testcase_config_variables # parse config variables - parsed_config_variables = parse_variables_mapping(overrided_testcase_config_variables) + parsed_config_variables = parse_variables_mapping( + overrided_testcase_config_variables + ) # parse parameters if "parameters" in testcase and testcase["parameters"]: cartesian_product_parameters = parse_parameters( - testcase["parameters"], - parsed_config_variables, - functions + testcase["parameters"], parsed_config_variables, functions ) for parameter_variables in cartesian_product_parameters: # deepcopy to avoid influence between parameters testcase_copied = utils.deepcopy_dict(parsed_testcase) - parsed_config_variables_copied = utils.deepcopy_dict(parsed_config_variables) - testcase_copied["config"]["variables"] = utils.extend_variables( - parsed_config_variables_copied, - parameter_variables + parsed_config_variables_copied = utils.deepcopy_dict( + parsed_config_variables + ) + testcase_copied["config"]["variables"] = utils.extend_variables( + parsed_config_variables_copied, parameter_variables + ) + parsed_testcase_copied = _parse_testcase( + testcase_copied, project_mapping ) - parsed_testcase_copied = _parse_testcase(testcase_copied, project_mapping) if not parsed_testcase_copied: continue parsed_testcase_copied["config"]["name"] = parse_lazy_data( parsed_testcase_copied["config"]["name"], - testcase_copied["config"]["variables"] + testcase_copied["config"]["variables"], ) parsed_testcase_list.append(parsed_testcase_copied) @@ -1378,15 +1357,13 @@ def _parse_testsuite(testsuite, project_mapping): testsuite.setdefault("config", {}) prepared_config = __prepare_config(testsuite["config"], project_mapping) parsed_testcase_list = __get_parsed_testsuite_testcases( - testsuite["testcases"], - prepared_config, - project_mapping + testsuite["testcases"], prepared_config, project_mapping ) return parsed_testcase_list def parse_tests(tests_mapping): - """ parse tests and load to parsed testcases + """parse tests and load to parsed testcases tests include api, testcases and testsuites. Args: @@ -1475,12 +1452,10 @@ def parse_tests(tests_mapping): # encapsulate api as a testcase for api_content in tests_mapping["apis"]: testcase = { - "config": { - "name": api_content.get("name") - }, + "config": {"name": api_content.get("name")}, "teststeps": [api_content], "path": api_content.pop("path", None), - "type": api_content.pop("type", "api") + "type": api_content.pop("type", "api"), } parsed_testcase = _parse_testcase(testcase, project_mapping) if not parsed_testcase: diff --git a/httprunner/report/__init__.py b/httprunner/report/__init__.py index eefd839f..9599cc3d 100644 --- a/httprunner/report/__init__.py +++ b/httprunner/report/__init__.py @@ -16,5 +16,5 @@ __all__ = [ "get_summary", "stringify_summary", "HtmlTestResult", - "gen_html_report" + "gen_html_report", ] diff --git a/httprunner/report/html/__init__.py b/httprunner/report/html/__init__.py index a1b4f12f..398adeea 100644 --- a/httprunner/report/html/__init__.py +++ b/httprunner/report/html/__init__.py @@ -9,7 +9,4 @@ HttpRunner html report from httprunner.report.html.result import HtmlTestResult from httprunner.report.html.gen_report import gen_html_report -__all__ = [ - "HtmlTestResult", - "gen_html_report" -] \ No newline at end of file +__all__ = ["HtmlTestResult", "gen_html_report"] diff --git a/httprunner/report/html/gen_report.py b/httprunner/report/html/gen_report.py index af7814c6..44e07682 100644 --- a/httprunner/report/html/gen_report.py +++ b/httprunner/report/html/gen_report.py @@ -9,7 +9,7 @@ from httprunner.exceptions import SummaryEmpty def gen_html_report(summary, report_template=None, report_dir=None, report_file=None): - """ render html report with specified report name and template + """render html report with specified report name and template Args: summary (dict): test result summary data @@ -24,8 +24,7 @@ def gen_html_report(summary, report_template=None, report_dir=None, report_file= if not report_template: report_template = os.path.join( - os.path.abspath(os.path.dirname(__file__)), - "template.html" + os.path.abspath(os.path.dirname(__file__)), "template.html" ) logger.log_debug("No html report template specified, use default.") else: @@ -43,22 +42,22 @@ def gen_html_report(summary, report_template=None, report_dir=None, report_file= else: report_dir = report_dir or os.path.join(os.getcwd(), "reports") # fix #826: Windows does not support file name include ":" - report_file_name = "{}.html".format(utc_time_iso_8601_str.replace(":", "").replace("-", "")) + report_file_name = "{}.html".format( + utc_time_iso_8601_str.replace(":", "").replace("-", "") + ) if not os.path.isdir(report_dir): os.makedirs(report_dir) report_path = os.path.join(report_dir, report_file_name) - with io.open(report_template, "r", encoding='utf-8') as fp_r: + with io.open(report_template, "r", encoding="utf-8") as fp_r: template_content = fp_r.read() - with io.open(report_path, 'w', encoding='utf-8') as fp_w: + with io.open(report_path, "w", encoding="utf-8") as fp_w: rendered_content = Template( - template_content, - extensions=["jinja2.ext.loopcontrols"] + template_content, extensions=["jinja2.ext.loopcontrols"] ).render(summary) fp_w.write(rendered_content) logger.log_info("Generated Html report: {}".format(report_path)) return report_path - diff --git a/httprunner/report/html/result.py b/httprunner/report/html/result.py index d4076c19..ce2a75ae 100644 --- a/httprunner/report/html/result.py +++ b/httprunner/report/html/result.py @@ -5,19 +5,20 @@ from httprunner import logger class HtmlTestResult(unittest.TextTestResult): - """ A html result class that can generate formatted html results. - Used by TextTestRunner. + """A html result class that can generate formatted html results. + Used by TextTestRunner. """ + def __init__(self, stream, descriptions, verbosity): super(HtmlTestResult, self).__init__(stream, descriptions, verbosity) self.records = [] - def _record_test(self, test, status, attachment=''): + def _record_test(self, test, status, attachment=""): data = { - 'name': test.shortDescription(), - 'status': status, - 'attachment': attachment, - "meta_datas": test.meta_datas + "name": test.shortDescription(), + "status": status, + "attachment": attachment, + "meta_datas": test.meta_datas, } self.records.append(data) @@ -25,38 +26,38 @@ class HtmlTestResult(unittest.TextTestResult): self.start_at = time.time() def startTest(self, test): - """ add start test time """ + """add start test time""" super(HtmlTestResult, self).startTest(test) logger.color_print(test.shortDescription(), "yellow") def addSuccess(self, test): super(HtmlTestResult, self).addSuccess(test) - self._record_test(test, 'success') + self._record_test(test, "success") print("") def addError(self, test, err): super(HtmlTestResult, self).addError(test, err) - self._record_test(test, 'error', self._exc_info_to_string(err, test)) + self._record_test(test, "error", self._exc_info_to_string(err, test)) print("") def addFailure(self, test, err): super(HtmlTestResult, self).addFailure(test, err) - self._record_test(test, 'failure', self._exc_info_to_string(err, test)) + self._record_test(test, "failure", self._exc_info_to_string(err, test)) print("") def addSkip(self, test, reason): super(HtmlTestResult, self).addSkip(test, reason) - self._record_test(test, 'skipped', reason) + self._record_test(test, "skipped", reason) print("") def addExpectedFailure(self, test, err): super(HtmlTestResult, self).addExpectedFailure(test, err) - self._record_test(test, 'ExpectedFailure', self._exc_info_to_string(err, test)) + self._record_test(test, "ExpectedFailure", self._exc_info_to_string(err, test)) print("") def addUnexpectedSuccess(self, test): super(HtmlTestResult, self).addUnexpectedSuccess(test) - self._record_test(test, 'UnexpectedSuccess') + self._record_test(test, "UnexpectedSuccess") print("") @property diff --git a/httprunner/report/report.py b/httprunner/report/report.py index 29824cc2..cc59bd9d 100644 --- a/httprunner/report/report.py +++ b/httprunner/report/report.py @@ -9,43 +9,37 @@ from httprunner import __version__ def prepare_event_kwargs(event_name, params): - """ prepare report event kwargs""" + """prepare report event kwargs""" kwargs = { - "headers": { - 'content-type': 'application/json' - }, + "headers": {"content-type": "application/json"}, "json": { - "user": { - "user_unique_id": str(uuid.getnode()) - }, + "user": {"user_unique_id": str(uuid.getnode())}, "header": { "app_id": 173519, "os_name": platform.system(), "os_version": platform.release(), - "app_version": __version__ # HttpRunner version + "app_version": __version__, # HttpRunner version }, "events": [ { "event": event_name, "params": json.dumps(params), - "time": int(time.time()) + "time": int(time.time()), } ], - "verbose": 1 - } + "verbose": 1, + }, } return kwargs def report_event(event_name, success=True): - params = { - "success": 1 if success else 0 - } + params = {"success": 1 if success else 0} kwargs = prepare_event_kwargs(event_name, params) resp = requests.post("http://mcs.snssdk.com/v1/json", **kwargs) print("resp---", resp.json()) -if __name__ == '__main__': +if __name__ == "__main__": report_event("loader") diff --git a/httprunner/report/stringify.py b/httprunner/report/stringify.py index bd9d9007..05b633f0 100644 --- a/httprunner/report/stringify.py +++ b/httprunner/report/stringify.py @@ -8,7 +8,7 @@ from httprunner.compat import basestring, bytes, json, numeric_types, JSONDecode def dumps_json(value): - """ dumps json value to indented string + """dumps json value to indented string Args: value (dict): raw json data @@ -28,7 +28,7 @@ def detect_encoding(value): def __stringify_request(request_data): - """ stringfy HTTP request data + """stringfy HTTP request data Args: request_data (dict): HTTP request data in dict. @@ -84,7 +84,7 @@ def __stringify_request(request_data): def __stringify_response(response_data): - """ stringfy HTTP response data + """stringfy HTTP response data Args: response_data (dict): @@ -124,8 +124,7 @@ def __stringify_response(response_data): if key == "body" and "image" in response_data["content_type"]: # display image value = "data:{};base64,{}".format( - response_data["content_type"], - b64encode(value).decode(encoding) + response_data["content_type"], b64encode(value).decode(encoding) ) else: value = escape(value.decode(encoding)) @@ -143,7 +142,7 @@ def __stringify_response(response_data): def __expand_meta_datas(meta_datas, meta_datas_expanded): - """ expand meta_datas to one level + """expand meta_datas to one level Args: meta_datas (dict/list): maybe in nested format @@ -173,8 +172,7 @@ def __expand_meta_datas(meta_datas, meta_datas_expanded): def __get_total_response_time(meta_datas_expanded): - """ caculate total response time of all meta_datas - """ + """caculate total response time of all meta_datas""" try: response_time = 0 for meta_data in meta_datas_expanded: @@ -200,15 +198,14 @@ def __stringify_meta_datas(meta_datas): def stringify_summary(summary): - """ stringify summary, in order to dump json file and generate html report. - """ + """stringify summary, in order to dump json file and generate html report.""" for index, suite_summary in enumerate(summary["details"]): if not suite_summary.get("name"): suite_summary["name"] = "testcase {}".format(index) for record in suite_summary.get("records"): - meta_datas = record['meta_datas'] + meta_datas = record["meta_datas"] __stringify_meta_datas(meta_datas) meta_datas_expanded = [] __expand_meta_datas(meta_datas, meta_datas_expanded) diff --git a/httprunner/report/summarize.py b/httprunner/report/summarize.py index 93c7145f..57d8514f 100644 --- a/httprunner/report/summarize.py +++ b/httprunner/report/summarize.py @@ -7,15 +7,14 @@ def get_platform(): return { "httprunner_version": __version__, "python_version": "{} {}".format( - platform.python_implementation(), - platform.python_version() + platform.python_implementation(), platform.python_version() ), - "platform": platform.platform() + "platform": platform.platform(), } def aggregate_stat(origin_stat, new_stat): - """ aggregate new_stat to origin_stat. + """aggregate new_stat to origin_stat. Args: origin_stat (dict): origin stat dict, will be updated with new_stat dict. @@ -30,8 +29,10 @@ def aggregate_stat(origin_stat, new_stat): origin_stat["start_at"] = min(origin_stat["start_at"], new_stat["start_at"]) elif key == "duration": # duration = max_end_time - min_start_time - max_end_time = max(origin_stat["start_at"] + origin_stat["duration"], - new_stat["start_at"] + new_stat["duration"]) + max_end_time = max( + origin_stat["start_at"] + origin_stat["duration"], + new_stat["start_at"] + new_stat["duration"], + ) min_start_time = min(origin_stat["start_at"], new_stat["start_at"]) origin_stat["duration"] = max_end_time - min_start_time else: @@ -39,7 +40,7 @@ def aggregate_stat(origin_stat, new_stat): def get_summary(result): - """ get summary from test result + """get summary from test result Args: result (instance): HtmlTestResult() instance @@ -58,25 +59,24 @@ def get_summary(result): summary = { "success": result.wasSuccessful(), "stat": { - 'total': result.testsRun, - 'failures': len(result.failures), - 'errors': len(result.errors), - 'skipped': len(result.skipped), - 'expectedFailures': len(result.expectedFailures), - 'unexpectedSuccesses': len(result.unexpectedSuccesses) - } + "total": result.testsRun, + "failures": len(result.failures), + "errors": len(result.errors), + "skipped": len(result.skipped), + "expectedFailures": len(result.expectedFailures), + "unexpectedSuccesses": len(result.unexpectedSuccesses), + }, } - summary["stat"]["successes"] = summary["stat"]["total"] \ - - summary["stat"]["failures"] \ - - summary["stat"]["errors"] \ - - summary["stat"]["skipped"] \ - - summary["stat"]["expectedFailures"] \ - - summary["stat"]["unexpectedSuccesses"] + summary["stat"]["successes"] = ( + summary["stat"]["total"] + - summary["stat"]["failures"] + - summary["stat"]["errors"] + - summary["stat"]["skipped"] + - summary["stat"]["expectedFailures"] + - summary["stat"]["unexpectedSuccesses"] + ) - summary["time"] = { - 'start_at': result.start_at, - 'duration': result.duration - } + summary["time"] = {"start_at": result.start_at, "duration": result.duration} summary["records"] = result.records return summary diff --git a/httprunner/response.py b/httprunner/response.py index 62aae114..b4ab4a56 100644 --- a/httprunner/response.py +++ b/httprunner/response.py @@ -10,9 +10,8 @@ text_extractor_regexp_compile = re.compile(r".*\(.*\).*") class ResponseObject(object): - def __init__(self, resp_obj): - """ initialize with a requests.Response object + """initialize with a requests.Response object Args: resp_obj (instance): requests.Response instance @@ -64,9 +63,9 @@ class ResponseObject(object): return result else: raise exceptions.ExtractFailure("\tjsonpath {} get nothing\n".format(field)) - + def _extract_field_with_regex(self, field): - """ extract field from response content with regex. + """extract field from response content with regex. requests.Response body could be json or html text. Args: @@ -87,15 +86,15 @@ class ResponseObject(object): """ matched = re.search(field, self.text) if not matched: - err_msg = u"Failed to extract data with regex! => {}\n".format(field) - err_msg += u"response body: {}\n".format(self.text) + err_msg = "Failed to extract data with regex! => {}\n".format(field) + err_msg += "response body: {}\n".format(self.text) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) return matched.group(1) def _extract_field_with_delimiter(self, field): - """ response content could be json or html text. + """response content could be json or html text. Args: field (str): string joined by delimiter. @@ -111,7 +110,7 @@ class ResponseObject(object): # string.split(sep=None, maxsplit=1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: - top_query, sub_query = field.split('.', 1) + top_query, sub_query = field.split(".", 1) except ValueError: top_query = field sub_query = None @@ -120,7 +119,7 @@ class ResponseObject(object): if top_query in ["status_code", "encoding", "ok", "reason", "url"]: if sub_query: # status_code.XX - err_msg = u"Failed to extract: {}\n".format(field) + err_msg = "Failed to extract: {}\n".format(field) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) @@ -136,16 +135,18 @@ class ResponseObject(object): try: return cookies[sub_query] except KeyError: - err_msg = u"Failed to extract cookie! => {}\n".format(field) - err_msg += u"response cookies: {}\n".format(cookies) + err_msg = "Failed to extract cookie! => {}\n".format(field) + err_msg += "response cookies: {}\n".format(cookies) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # elapsed elif top_query == "elapsed": - available_attributes = u"available attributes: days, seconds, microseconds, total_seconds" + available_attributes = ( + "available attributes: days, seconds, microseconds, total_seconds" + ) if not sub_query: - err_msg = u"elapsed is datetime.timedelta instance, attribute should also be specified!\n" + err_msg = "elapsed is datetime.timedelta instance, attribute should also be specified!\n" err_msg += available_attributes logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) @@ -154,7 +155,9 @@ class ResponseObject(object): elif sub_query == "total_seconds": return self.elapsed.total_seconds() else: - err_msg = "{} is not valid datetime.timedelta attribute.\n".format(sub_query) + err_msg = "{} is not valid datetime.timedelta attribute.\n".format( + sub_query + ) err_msg += available_attributes logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) @@ -169,8 +172,8 @@ class ResponseObject(object): try: return headers[sub_query] except KeyError: - err_msg = u"Failed to extract header! => {}\n".format(field) - err_msg += u"response headers: {}\n".format(headers) + err_msg = "Failed to extract header! => {}\n".format(field) + err_msg += "response headers: {}\n".format(headers) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) @@ -193,8 +196,12 @@ class ResponseObject(object): return utils.query_json(body, sub_query) else: # content = "abcdefg", content.xxx - err_msg = u"Failed to extract attribute from response body! => {}\n".format(field) - err_msg += u"response body: {}\n".format(body) + err_msg = ( + "Failed to extract attribute from response body! => {}\n".format( + field + ) + ) + err_msg += "response body: {}\n".format(body) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) @@ -214,26 +221,29 @@ class ResponseObject(object): return utils.query_json(attributes, sub_query) else: # content = "attributes.new_attribute_not_exist" - err_msg = u"Failed to extract cumstom set attribute from teardown hooks! => {}\n".format(field) - err_msg += u"response set attributes: {}\n".format(attributes) + err_msg = "Failed to extract cumstom set attribute from teardown hooks! => {}\n".format( + field + ) + err_msg += "response set attributes: {}\n".format(attributes) logger.log_error(err_msg) raise exceptions.TeardownHooksFailure(err_msg) # others else: - err_msg = u"Failed to extract attribute from response! => {}\n".format(field) - err_msg += u"available response attributes: status_code, cookies, elapsed, headers, content, " \ - u"text, json, encoding, ok, reason, url.\n\n" - err_msg += u"If you want to set attribute in teardown_hooks, take the following example as reference:\n" - err_msg += u"response.new_attribute = 'new_attribute_value'\n" + err_msg = "Failed to extract attribute from response! => {}\n".format(field) + err_msg += ( + "available response attributes: status_code, cookies, elapsed, headers, content, " + "text, json, encoding, ok, reason, url.\n\n" + ) + err_msg += "If you want to set attribute in teardown_hooks, take the following example as reference:\n" + err_msg += "response.new_attribute = 'new_attribute_value'\n" logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) def extract_field(self, field): - """ extract value from requests.Response. - """ + """extract value from requests.Response.""" if not isinstance(field, basestring): - err_msg = u"Invalid extractor! => {}\n".format(field) + err_msg = "Invalid extractor! => {}\n".format(field) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) @@ -255,7 +265,7 @@ class ResponseObject(object): return value def extract_response(self, extractors): - """ extract value from requests.Response and store in OrderedDict. + """extract value from requests.Response and store in OrderedDict. Args: extractors (list): diff --git a/httprunner/runner.py b/httprunner/runner.py index aa163f52..14b9c566 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -15,7 +15,7 @@ class HookTypeEnum(Enum): class Runner(object): - """ Running testcases. + """Running testcases. Examples: >>> tests_mapping = { @@ -52,7 +52,7 @@ class Runner(object): """ def __init__(self, config, http_client_session=None): - """ run testcase or testsuite. + """run testcase or testsuite. Args: config (dict): testcase/testsuite config dict @@ -87,15 +87,14 @@ class Runner(object): self.do_hook_actions(self.testcase_teardown_hooks, HookTypeEnum.TEARDOWN) def __clear_test_data(self): - """ clear request and response data - """ + """clear request and response data""" if not isinstance(self.http_client_session, HttpSession): return self.http_client_session.init_meta_data() def _handle_skip_feature(self, test_dict): - """ handle skip feature for test + """handle skip feature for test - skip: skip current test unconditionally - skipIf: skip current test if condition is true - skipUnless: skip current test unless condition is true @@ -127,7 +126,7 @@ class Runner(object): raise SkipTest(skip_reason) def do_hook_actions(self, actions, hook_type): - """ call hook actions. + """call hook actions. Args: actions (list): each action in actions list maybe in two format. @@ -153,9 +152,7 @@ class Runner(object): var_name, hook_content, hook_content_eval ) ) - self.session_context.update_test_variables( - var_name, hook_content_eval - ) + self.session_context.update_test_variables(var_name, hook_content_eval) else: # format 2 logger.log_debug("call hook function: {}".format(action)) @@ -163,7 +160,7 @@ class Runner(object): self.session_context.eval_content(action) def _run_test(self, test_dict): - """ run single teststep. + """run single teststep. Args: test_dict (dict): teststep info @@ -209,7 +206,7 @@ class Runner(object): test_name = self.session_context.eval_content(test_dict.get("name", "")) # parse test request - raw_request = test_dict.get('request', {}) + raw_request = test_dict.get("request", {}) parsed_test_request = self.session_context.eval_content(raw_request) self.session_context.update_test_variables("request", parsed_test_request) @@ -219,12 +216,12 @@ class Runner(object): self.do_hook_actions(setup_hooks, HookTypeEnum.SETUP) # prepend url with base_url unless it's already an absolute URL - url = parsed_test_request.pop('url') + url = parsed_test_request.pop("url") base_url = self.session_context.eval_content(test_dict.get("base_url", "")) parsed_url = utils.build_url(base_url, url) try: - method = parsed_test_request.pop('method') + method = parsed_test_request.pop("method") parsed_test_request.setdefault("verify", self.verify) group_name = parsed_test_request.pop("group", None) except KeyError: @@ -232,14 +229,12 @@ class Runner(object): logger.log_info("{method} {url}".format(method=method, url=parsed_url)) logger.log_debug( - "request kwargs(raw): {kwargs}".format(kwargs=parsed_test_request)) + "request kwargs(raw): {kwargs}".format(kwargs=parsed_test_request) + ) # request resp = self.http_client_session.request( - method, - parsed_url, - name=(group_name or test_name), - **parsed_test_request + method, parsed_url, name=(group_name or test_name), **parsed_test_request ) resp_obj = response.ResponseObject(resp) @@ -284,10 +279,7 @@ class Runner(object): validators = test_dict.get("validate") or test_dict.get("validators") or [] validate_script = test_dict.get("validate_script", []) if validate_script: - validators.append({ - "type": "python_script", - "script": validate_script - }) + validators.append({"type": "python_script", "script": validate_script}) validator = Validator(self.session_context, resp_obj) try: @@ -299,8 +291,7 @@ class Runner(object): self.validation_results = validator.validation_results def _run_testcase(self, testcase_dict): - """ run single testcase. - """ + """run single testcase.""" self.meta_datas = [] config = testcase_dict.get("config", {}) @@ -333,7 +324,7 @@ class Runner(object): ) def run_test(self, test_dict): - """ run single teststep of testcase. + """run single teststep of testcase. test_dict may be in 3 types. Args: @@ -370,7 +361,8 @@ class Runner(object): # nested testcase test_dict.setdefault("config", {}).setdefault("variables", {}) test_dict["config"]["variables"].update( - self.session_context.session_variables_mapping) + self.session_context.session_variables_mapping + ) self._run_testcase(test_dict) else: # api @@ -388,8 +380,7 @@ class Runner(object): self.meta_datas["validators"] = self.validation_results def export_variables(self, output_variables_list): - """ export current testcase variables - """ + """export current testcase variables""" variables_mapping = self.session_context.session_variables_mapping output = {} diff --git a/httprunner/utils.py b/httprunner/utils.py index 1273ba35..d1c4b20c 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -23,7 +23,7 @@ absolute_http_url_regexp = re.compile(r"^https?://", re.I) def init_sentry_sdk(): sentry_sdk.init( dsn="https://cc6dd86fbe9f4e7fbd95248cfcff114d@sentry.io/1862849", - release="httprunner@{}".format(__version__) + release="httprunner@{}".format(__version__), ) with sentry_sdk.configure_scope() as scope: @@ -32,46 +32,48 @@ def init_sentry_sdk(): class GAClient(object): - version = '1' # GA API Version - report_url = 'https://www.google-analytics.com/collect' - report_debug_url = 'https://www.google-analytics.com/debug/collect' # used for debug + version = "1" # GA API Version + report_url = "https://www.google-analytics.com/collect" + report_debug_url = ( + "https://www.google-analytics.com/debug/collect" # used for debug + ) def __init__(self, tracking_id): self.http_client = requests.Session() self.label = str(__version__) self.common_params = { - 'v': self.version, - 'tid': tracking_id, # Tracking ID / Property ID, XX-XXXXXXX-X - 'cid': uuid.getnode(), # Anonymous Client ID - 'ua': 'HttpRunner/{}'.format(__version__), + "v": self.version, + "tid": tracking_id, # Tracking ID / Property ID, XX-XXXXXXX-X + "cid": uuid.getnode(), # Anonymous Client ID + "ua": "HttpRunner/{}".format(__version__), } def track_event(self, category, action, value=0): data = { - 't': 'event', # Event hit type = event - 'ec': category, # Required. Event Category. - 'ea': action, # Required. Event Action. - 'el': self.label, # Optional. Event label, used as version. - 'ev': value, # Optional. Event value, must be non-negative integer + "t": "event", # Event hit type = event + "ec": category, # Required. Event Category. + "ea": action, # Required. Event Action. + "el": self.label, # Optional. Event label, used as version. + "ev": value, # Optional. Event value, must be non-negative integer } data.update(self.common_params) try: self.http_client.post(self.report_url, data=data, timeout=5) - except Exception: # ProxyError, SSLError, ConnectionError + except Exception: # ProxyError, SSLError, ConnectionError pass def track_user_timing(self, category, variable, duration): data = { - 't': 'timing', # Event hit type = timing - 'utc': category, # Required. user timing category. e.g. jsonLoader - 'utv': variable, # Required. timing variable. e.g. load - 'utt': duration, # Required. time took duration. - 'utl': self.label, # Optional. user timing label, used as version. + "t": "timing", # Event hit type = timing + "utc": category, # Required. user timing category. e.g. jsonLoader + "utv": variable, # Required. timing variable. e.g. load + "utt": duration, # Required. time took duration. + "utl": self.label, # Optional. user timing label, used as version. } data.update(self.common_params) try: self.http_client.post(self.report_url, data=data, timeout=5) - except Exception: # ProxyError, SSLError, ConnectionError + except Exception: # ProxyError, SSLError, ConnectionError pass @@ -79,23 +81,21 @@ ga_client = GAClient("UA-114587036-1") def set_os_environ(variables_mapping): - """ set variables mapping to os.environ - """ + """set variables mapping to os.environ""" for variable in variables_mapping: os.environ[variable] = variables_mapping[variable] logger.log_debug("Set OS environment variable: {}".format(variable)) def unset_os_environ(variables_mapping): - """ set variables mapping to os.environ - """ + """set variables mapping to os.environ""" for variable in variables_mapping: os.environ.pop(variable) logger.log_debug("Unset OS environment variable: {}".format(variable)) def get_os_environ(variable_name): - """ get value of environment variable. + """get value of environment variable. Args: variable_name(str): variable name @@ -114,7 +114,7 @@ def get_os_environ(variable_name): def build_url(base_url, path): - """ prepend url with base_url unless it's already an absolute URL """ + """prepend url with base_url unless it's already an absolute URL""" if absolute_http_url_regexp.match(path): return path elif base_url: @@ -123,8 +123,8 @@ def build_url(base_url, path): raise ParamsError("base url missed!") -def query_json(json_content, query, delimiter='.'): - """ Do an xpath-like query with json_content. +def query_json(json_content, query, delimiter="."): + """Do an xpath-like query with json_content. Args: json_content (dict/list/string): content to be queried. @@ -158,7 +158,7 @@ def query_json(json_content, query, delimiter='.'): """ raise_flag = False - response_body = u"response body: {}\n".format(json_content) + response_body = "response body: {}\n".format(json_content) try: for key in query.split(delimiter): if isinstance(json_content, (list, basestring)): @@ -167,13 +167,16 @@ def query_json(json_content, query, delimiter='.'): json_content = json_content[key] else: logger.log_error( - "invalid type value: {}({})".format(json_content, type(json_content))) + "invalid type value: {}({})".format( + json_content, type(json_content) + ) + ) raise_flag = True except (KeyError, ValueError, IndexError): raise_flag = True if raise_flag: - err_msg = u"Failed to extract! => {}\n".format(query) + err_msg = "Failed to extract! => {}\n".format(query) err_msg += response_body logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) @@ -182,7 +185,7 @@ def query_json(json_content, query, delimiter='.'): def lower_dict_keys(origin_dict): - """ convert keys in dict to lower case + """convert keys in dict to lower case Args: origin_dict (dict): mapping data structure @@ -213,16 +216,13 @@ def lower_dict_keys(origin_dict): if not origin_dict or not isinstance(origin_dict, dict): return origin_dict - return { - key.lower(): value - for key, value in origin_dict.items() - } + return {key.lower(): value for key, value in origin_dict.items()} def lower_test_dict_keys(test_dict): - """ convert keys in test_dict to lower case, convertion will occur in two places: - 1, all keys in test_dict; - 2, all keys in test_dict["request"] + """convert keys in test_dict to lower case, convertion will occur in two places: + 1, all keys in test_dict; + 2, all keys in test_dict["request"] """ # convert keys in test_dict test_dict = lower_dict_keys(test_dict) @@ -235,7 +235,7 @@ def lower_test_dict_keys(test_dict): def deepcopy_dict(data): - """ deepcopy dict data, ignore file object (_io.BufferedReader) + """deepcopy dict data, ignore file object (_io.BufferedReader) Args: data (dict): dict data structure @@ -271,7 +271,7 @@ def deepcopy_dict(data): def ensure_mapping_format(variables): - """ ensure variables are in mapping format. + """ensure variables are in mapping format. Args: variables (list/dict): original variables @@ -306,7 +306,7 @@ def ensure_mapping_format(variables): def extend_variables(raw_variables, override_variables): - """ extend raw_variables with override_variables. + """extend raw_variables with override_variables. override_variables will merge and override raw_variables. Args: @@ -343,7 +343,7 @@ def extend_variables(raw_variables, override_variables): def get_testcase_io(testcase): - """ get and print testcase input(variables) and output(export). + """get and print testcase input(variables) and output(export). Args: testcase (unittest.suite.TestSuite): corresponding to one YAML/JSON file, it has been set two attributes: @@ -355,18 +355,14 @@ def get_testcase_io(testcase): """ test_runner = testcase.runner variables = testcase.config.get("variables", {}) - output_list = testcase.config.get("export") \ - or testcase.config.get("output", []) + output_list = testcase.config.get("export") or testcase.config.get("output", []) export_mapping = test_runner.export_variables(output_list) - return { - "in": variables, - "out": export_mapping - } + return {"in": variables, "out": export_mapping} def print_info(info_mapping): - """ print info in mapping. + """print info in mapping. Args: info_mapping (dict): input(variables) or output mapping. @@ -417,10 +413,11 @@ def print_info(info_mapping): def create_scaffold(project_name): - """ create scaffold with specified project name. - """ + """create scaffold with specified project name.""" if os.path.isdir(project_name): - logger.log_warning(u"Folder {} exists, please specify a new folder name.".format(project_name)) + logger.log_warning( + "Folder {} exists, please specify a new folder name.".format(project_name) + ) return ga_client.track_event("Scaffold", "startproject") @@ -433,7 +430,7 @@ def create_scaffold(project_name): logger.color_print(msg, "BLUE") def create_file(path, file_content=""): - with open(path, 'w') as f: + with open(path, "w") as f: f.write(file_content) msg = "created file: {}".format(path) logger.color_print(msg, "BLUE") @@ -498,24 +495,16 @@ testcases: variables: device_sn: $device_sn """ - ignore_content = "\n".join([ - ".env", - "reports/*", - "__pycache__/*", - "*.pyc", - ".python-version", - "logs/*" - ]) + ignore_content = "\n".join( + [".env", "reports/*", "__pycache__/*", "*.pyc", ".python-version", "logs/*"] + ) demo_debugtalk_content = """ import time def sleep(n_secs): time.sleep(n_secs) """ - demo_env_content = "\n".join([ - "USERNAME=leolee", - "PASSWORD=123456" - ]) + demo_env_content = "\n".join(["USERNAME=leolee", "PASSWORD=123456"]) create_folder(project_name) create_folder(os.path.join(project_name, "api")) @@ -523,15 +512,21 @@ def sleep(n_secs): create_folder(os.path.join(project_name, "testsuites")) create_folder(os.path.join(project_name, "reports")) create_file(os.path.join(project_name, "api", "demo_api.yml"), demo_api_content) - create_file(os.path.join(project_name, "testcases", "demo_testcase.yml"), demo_testcase_content) - create_file(os.path.join(project_name, "testsuites", "demo_testsuite.yml"), demo_testsuite_content) + create_file( + os.path.join(project_name, "testcases", "demo_testcase.yml"), + demo_testcase_content, + ) + create_file( + os.path.join(project_name, "testsuites", "demo_testsuite.yml"), + demo_testsuite_content, + ) create_file(os.path.join(project_name, "debugtalk.py"), demo_debugtalk_content) create_file(os.path.join(project_name, ".env"), demo_env_content) create_file(os.path.join(project_name, ".gitignore"), ignore_content) def gen_cartesian_product(*args): - """ generate cartesian product for lists + """generate cartesian product for lists Args: args (list of list): lists to be generated with cartesian product @@ -572,11 +567,12 @@ def gen_cartesian_product(*args): def prettify_json_file(file_list): - """ prettify JSON testcase format - """ + """prettify JSON testcase format""" for json_file in set(file_list): if not json_file.endswith(".json"): - logger.log_warning("Only JSON file format can be prettified, skip: {}".format(json_file)) + logger.log_warning( + "Only JSON file format can be prettified, skip: {}".format(json_file) + ) continue logger.color_print("Start to prettify JSON file: {}".format(json_file), "GREEN") @@ -585,22 +581,21 @@ def prettify_json_file(file_list): file_name, file_suffix = os.path.splitext(os.path.basename(json_file)) outfile = os.path.join(dir_path, "{}.pretty.json".format(file_name)) - with io.open(json_file, 'r', encoding='utf-8') as stream: + with io.open(json_file, "r", encoding="utf-8") as stream: try: obj = json.load(stream) except ValueError as e: raise SystemExit(e) - with io.open(outfile, 'w', encoding='utf-8') as out: - json.dump(obj, out, indent=4, separators=(',', ': ')) - out.write('\n') + with io.open(outfile, "w", encoding="utf-8") as out: + json.dump(obj, out, indent=4, separators=(",", ": ")) + out.write("\n") print("success: {}".format(outfile)) def omit_long_data(body, omit_len=512): - """ omit too long str/bytes - """ + """omit too long str/bytes""" if not isinstance(body, basestring): return body @@ -618,8 +613,8 @@ def omit_long_data(body, omit_len=512): def dump_json_file(json_data, json_file_abs_path): - """ dump json data to file - """ + """dump json data to file""" + class PythonObjectEncoder(json.JSONEncoder): def default(self, obj): try: @@ -632,26 +627,28 @@ def dump_json_file(json_data, json_file_abs_path): os.makedirs(file_foder_path) try: - with io.open(json_file_abs_path, 'w', encoding='utf-8') as outfile: + with io.open(json_file_abs_path, "w", encoding="utf-8") as outfile: if is_py2: outfile.write( - unicode(json.dumps( - json_data, - indent=4, - separators=(',', ':'), - encoding="utf8", - ensure_ascii=False, - cls=PythonObjectEncoder - )) + unicode( + json.dumps( + json_data, + indent=4, + separators=(",", ":"), + encoding="utf8", + ensure_ascii=False, + cls=PythonObjectEncoder, + ) + ) ) else: json.dump( json_data, outfile, indent=4, - separators=(',', ':'), + separators=(",", ":"), ensure_ascii=False, - cls=PythonObjectEncoder + cls=PythonObjectEncoder, ) msg = "dump file: {}".format(json_file_abs_path) @@ -663,8 +660,7 @@ def dump_json_file(json_data, json_file_abs_path): def prepare_dump_json_file_abs_path(project_mapping, tag_name): - """ prepare dump json file absolute path. - """ + """prepare dump json file absolute path.""" pwd_dir_path = project_mapping.get("PWD") or os.getcwd() test_path = project_mapping.get("test_path") @@ -676,7 +672,7 @@ def prepare_dump_json_file_abs_path(project_mapping, tag_name): # both test_path and pwd_dir_path are absolute path logs_dir_path = os.path.join(pwd_dir_path, "logs") - test_path_relative_path = test_path[len(pwd_dir_path)+1:] + test_path_relative_path = test_path[len(pwd_dir_path) + 1 :] if os.path.isdir(test_path): file_foder_path = os.path.join(logs_dir_path, test_path_relative_path) @@ -692,7 +688,7 @@ def prepare_dump_json_file_abs_path(project_mapping, tag_name): def dump_logs(json_data, project_mapping, tag_name): - """ dump tests data to json file. + """dump tests data to json file. the dumped file is located in PWD/logs folder. Args: @@ -711,7 +707,11 @@ def get_python2_retire_msg(): left_days = (retire_day - today).days if left_days > 0: - retire_msg = "Python 2 will retire in {} days, why not move to Python 3?".format(left_days) + retire_msg = ( + "Python 2 will retire in {} days, why not move to Python 3?".format( + left_days + ) + ) else: retire_msg = "Python 2 has been retired, you should move to Python 3." diff --git a/httprunner/validator.py b/httprunner/validator.py index eb2d52c4..ea8dcade 100644 --- a/httprunner/validator.py +++ b/httprunner/validator.py @@ -16,7 +16,7 @@ class Validator(object): """ def __init__(self, session_context, resp_obj): - """ initialize a Validator for each teststep (API request) + """initialize a Validator for each teststep (API request) Args: session_context: HttpRunner session context @@ -27,7 +27,7 @@ class Validator(object): self.validation_results = {} def __eval_validator_check(self, check_item): - """ evaluate check item in validator. + """evaluate check item in validator. Args: check_item: check_item should only be the following 5 formats: @@ -38,8 +38,9 @@ class Validator(object): 5, regex string, e.g. "LB[\d]*(.*)RB[\d]*" """ - if isinstance(check_item, (dict, list)) \ - or isinstance(check_item, parser.LazyString): + if isinstance(check_item, (dict, list)) or isinstance( + check_item, parser.LazyString + ): # format 1/2/3 check_value = self.session_context.eval_content(check_item) else: @@ -49,7 +50,7 @@ class Validator(object): return check_value def __eval_validator_expect(self, expect_item): - """ evaluate expect item in validator. + """evaluate expect item in validator. Args: expect_item: expect_item should only be in 2 types: @@ -61,12 +62,11 @@ class Validator(object): return expect_value def validate_script(self, script): - """ make validation with python script - """ + """make validation with python script""" result = { "validate_script": "
".join(script), "check_result": "pass", - "output": "" + "output": "", } script = "\n ".join(script) @@ -75,12 +75,14 @@ class Validator(object): def run_validate_script(): {} -""".format(script) +""".format( + script + ) variables = { "status_code": self.resp_obj.status_code, "response_json": self.resp_obj.json, - "response": self.resp_obj + "response": self.resp_obj, } variables.update(self.session_context.test_variables_mapping) variables.update(globals()) @@ -90,11 +92,13 @@ def run_validate_script(): except SyntaxError as ex: logger.log_warning("SyntaxError in python validate script: {}".format(ex)) result["check_result"] = "fail" - result["output"] = "
".join([ - "ErrorMessage: {}".format(ex.msg), - "ErrorLine: {}".format(ex.lineno), - "ErrorText: {}".format(ex.text) - ]) + result["output"] = "
".join( + [ + "ErrorMessage: {}".format(ex.msg), + "ErrorLine: {}".format(ex.lineno), + "ErrorText: {}".format(ex.text), + ] + ) return result try: @@ -117,16 +121,17 @@ def run_validate_script(): else: line_no = "N/A" - result["output"] = "
".join([ - "ErrorType: {}".format(_type.__name__), - "ErrorLine: {}".format(line_no) - ]) + result["output"] = "
".join( + [ + "ErrorType: {}".format(_type.__name__), + "ErrorLine: {}".format(line_no), + ] + ) return result def validate(self, validators): - """ make validation with comparators - """ + """make validation with comparators""" self.validation_results = {} if not validators: return @@ -154,7 +159,8 @@ def run_validate_script(): # validator should be LazyFunction object if not isinstance(validator, parser.LazyFunction): raise exceptions.ValidationFailure( - "validator should be parsed first: {}".format(validators)) + "validator should be parsed first: {}".format(validators) + ) # evaluate validator args with context variable mapping. validator_args = validator.get_args() @@ -169,13 +175,10 @@ def run_validate_script(): "check": check_item, "check_value": check_value, "expect": expect_item, - "expect_value": expect_value + "expect_value": expect_value, } validate_msg = "\nvalidate: {} {} {}({})".format( - check_item, - comparator, - expect_value, - type(expect_value).__name__ + check_item, comparator, expect_value, type(expect_value).__name__ ) try: @@ -192,7 +195,7 @@ def run_validate_script(): type(check_value).__name__, comparator, expect_value, - type(expect_value).__name__ + type(expect_value).__name__, ) logger.log_error(validate_msg) failures.append(validate_msg) diff --git a/tests/api_server.py b/tests/api_server.py index 6919b274..462edf18 100644 --- a/tests/api_server.py +++ b/tests/api_server.py @@ -9,6 +9,7 @@ from httprunner.builtin.functions import gen_random_string try: from httpbin import app as httpbin_app + HTTPBIN_HOST = "127.0.0.1" HTTPBIN_PORT = 3458 HTTPBIN_SERVER = "http://{}:{}".format(HTTPBIN_HOST, HTTPBIN_PORT) @@ -49,37 +50,30 @@ token_dict = {} def get_sign(*args): - content = ''.join(args).encode('ascii') - sign_key = SECRET_KEY.encode('ascii') + content = "".join(args).encode("ascii") + sign_key = SECRET_KEY.encode("ascii") sign = hmac.new(sign_key, content, hashlib.sha1).hexdigest() return sign def gen_md5(*args): - return hashlib.md5("".join(args).encode('utf-8')).hexdigest() + return hashlib.md5("".join(args).encode("utf-8")).hexdigest() def validate_request(func): - @wraps(func) def wrapper(*args, **kwargs): - device_sn = request.headers.get('device_sn', "") - token = request.headers.get('token', "") + device_sn = request.headers.get("device_sn", "") + token = request.headers.get("token", "") if not device_sn or not token: - result = { - 'success': False, - 'msg': "device_sn or token is null." - } + result = {"success": False, "msg": "device_sn or token is null."} response = make_response(json.dumps(result), 401) response.headers["Content-Type"] = "application/json" return response if token_dict[device_sn] != token: - result = { - 'success': False, - 'msg': "Authorization failed!" - } + result = {"success": False, "msg": "Authorization failed!"} response = make_response(json.dumps(result), 403) response.headers["Content-Type"] = "application/json" return response @@ -89,82 +83,64 @@ def validate_request(func): return wrapper -@app.route('/') +@app.route("/") def index(): return "Hello World!" -@app.route('/api/get-token', methods=['POST']) +@app.route("/api/get-token", methods=["POST"]) def get_token(): - device_sn = request.headers.get('device_sn', "") - os_platform = request.headers.get('os_platform', "") - app_version = request.headers.get('app_version', "") + device_sn = request.headers.get("device_sn", "") + os_platform = request.headers.get("os_platform", "") + app_version = request.headers.get("app_version", "") data = request.get_json() - sign = data.get('sign', "") + sign = data.get("sign", "") expected_sign = get_sign(device_sn, os_platform, app_version) if expected_sign != sign: - result = { - 'success': False, - 'msg': "Authorization failed!" - } + result = {"success": False, "msg": "Authorization failed!"} response = make_response(json.dumps(result), 403) else: token = gen_random_string(16) token_dict[device_sn] = token - result = { - 'success': True, - 'token': token - } + result = {"success": True, "token": token} response = make_response(json.dumps(result)) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users') +@app.route("/api/users") @validate_request def get_users(): users_list = [user for uid, user in users_dict.items()] - users = { - 'success': True, - 'count': len(users_list), - 'items': users_list - } + users = {"success": True, "count": len(users_list), "items": users_list} response = make_response(json.dumps(users)) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/reset-all') +@app.route("/api/reset-all") @validate_request def clear_users(): users_dict.clear() - result = { - 'success': True - } + result = {"success": True} response = make_response(json.dumps(result)) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users/', methods=['POST']) +@app.route("/api/users/", methods=["POST"]) @validate_request def create_user(uid): user = request.get_json() if uid not in users_dict: - result = { - 'success': True, - 'msg': "user created successfully." - } + result = {"success": True, "msg": "user created successfully."} status_code = 201 users_dict[uid] = user else: - result = { - 'success': False, - 'msg': "user already existed." - } + result = {"success": False, "msg": "user already existed."} status_code = 500 response = make_response(json.dumps(result), status_code) @@ -172,21 +148,15 @@ def create_user(uid): return response -@app.route('/api/users/') +@app.route("/api/users/") @validate_request def get_user(uid): user = users_dict.get(uid, {}) if user: - result = { - 'success': True, - 'data': user - } + result = {"success": True, "data": user} status_code = 200 else: - result = { - 'success': False, - 'data': user - } + result = {"success": False, "data": user} status_code = 404 response = make_response(json.dumps(result), status_code) @@ -194,7 +164,7 @@ def get_user(uid): return response -@app.route('/api/users/', methods=['PUT']) +@app.route("/api/users/", methods=["PUT"]) @validate_request def update_user(uid): user = users_dict.get(uid, {}) @@ -207,16 +177,13 @@ def update_user(uid): success = False status_code = 404 - result = { - 'success': success, - 'data': user - } + result = {"success": success, "data": user} response = make_response(json.dumps(result), status_code) response.headers["Content-Type"] = "application/json" return response -@app.route('/api/users/', methods=['DELETE']) +@app.route("/api/users/", methods=["DELETE"]) @validate_request def delete_user(uid): user = users_dict.pop(uid, {}) @@ -227,10 +194,7 @@ def delete_user(uid): success = False status_code = 404 - result = { - 'success': success, - 'data': user - } + result = {"success": success, "data": user} response = make_response(json.dumps(result), status_code) response.headers["Content-Type"] = "application/json" return response diff --git a/tests/base.py b/tests/base.py index 86da90fb..07bf7aca 100644 --- a/tests/base.py +++ b/tests/base.py @@ -19,18 +19,13 @@ def run_httpbin(): class ApiServerUnittest(unittest.TestCase): - """ Test case class that sets up an HTTP server which can be used within the tests - """ + """Test case class that sets up an HTTP server which can be used within the tests""" @classmethod def setUpClass(cls): cls.host = "http://127.0.0.1:5000" - cls.flask_process = multiprocessing.Process( - target=run_flask - ) - cls.httpbin_process = multiprocessing.Process( - target=run_httpbin - ) + cls.flask_process = multiprocessing.Process(target=run_flask) + cls.httpbin_process = multiprocessing.Process(target=run_httpbin) cls.flask_process.start() cls.httpbin_process.start() time.sleep(1) @@ -44,15 +39,13 @@ class ApiServerUnittest(unittest.TestCase): def get_token(self, user_agent, device_sn, os_platform, app_version): url = "%s/api/get-token" % self.host headers = { - 'Content-Type': 'application/json', - 'User-Agent': user_agent, - 'device_sn': device_sn, - 'os_platform': os_platform, - 'app_version': app_version - } - data = { - 'sign': get_sign(device_sn, os_platform, app_version) + "Content-Type": "application/json", + "User-Agent": user_agent, + "device_sn": device_sn, + "os_platform": os_platform, + "app_version": app_version, } + data = {"sign": get_sign(device_sn, os_platform, app_version)} resp = self.api_client.post(url, json=data, headers=headers) resp_json = resp.json() @@ -62,14 +55,11 @@ class ApiServerUnittest(unittest.TestCase): return resp_json["token"] def get_authenticated_headers(self): - user_agent = 'iOS/10.3' + user_agent = "iOS/10.3" device_sn = gen_random_string(15) - os_platform = 'ios' - app_version = '2.8.6' + os_platform = "ios" + app_version = "2.8.6" token = self.get_token(user_agent, device_sn, os_platform, app_version) - headers = { - 'device_sn': device_sn, - 'token': token - } + headers = {"device_sn": device_sn, "token": token} return headers diff --git a/tests/debugtalk.py b/tests/debugtalk.py index 101d6308..27910f8b 100644 --- a/tests/debugtalk.py +++ b/tests/debugtalk.py @@ -17,12 +17,7 @@ def get_base_url(): def get_default_request(): - return { - "base_url": BASE_URL, - "headers": { - "content-type": "application/json" - } - } + return {"base_url": BASE_URL, "headers": {"content-type": "application/json"}} def sum_two(m, n): @@ -30,8 +25,8 @@ def sum_two(m, n): def sum_status_code(status_code, expect_sum): - """ sum status code digits - e.g. 400 => 4, 201 => 3 + """sum status code digits + e.g. 400 => 4, 201 => 3 """ sum_value = 0 for digit in str(status_code): @@ -48,8 +43,7 @@ os.environ["TEST_ENV"] = "PRODUCTION" def skip_test_in_production_env(): - """ skip this test in production environment - """ + """skip this test in production environment""" return os.environ["TEST_ENV"] == "PRODUCTION" @@ -58,16 +52,13 @@ def get_user_agent(): def gen_app_version(): - return [ - {"app_version": "2.8.5"}, - {"app_version": "2.8.6"} - ] + return [{"app_version": "2.8.5"}, {"app_version": "2.8.6"}] def get_account(): return [ {"username": "user1", "password": "111111"}, - {"username": "user2", "password": "222222"} + {"username": "user2", "password": "222222"}, ] @@ -81,7 +72,7 @@ def gen_random_string(str_len): random_char = random.choice(string.ascii_letters + string.digits) random_char_list.append(random_char) - random_string = ''.join(random_char_list) + random_string = "".join(random_char_list) return random_string @@ -94,8 +85,7 @@ def setup_hook_remove_kwargs(request): def teardown_hook_sleep_N_secs(response, n_secs): - """ sleep n seconds after request - """ + """sleep n seconds after request""" if response.status_code == 200: time.sleep(0.1) else: @@ -113,9 +103,11 @@ def modify_request_json(request, os_platform): def setup_hook_httpntlmauth(request): if "httpntlmauth" in request: from requests_ntlm import HttpNtlmAuth + auth_account = request.pop("httpntlmauth") request["auth"] = HttpNtlmAuth( - auth_account["username"], auth_account["password"]) + auth_account["username"], auth_account["password"] + ) def alter_response(response): @@ -123,18 +115,15 @@ def alter_response(response): response.headers["Content-Type"] = "html/text" response.json["headers"]["Host"] = "127.0.0.1:8888" response.new_attribute = "new_attribute_value" - response.new_attribute_dict = { - "key": 123 - } + response.new_attribute_dict = {"key": 123} + def alter_response_302(response): response.status_code = 500 response.headers["Content-Type"] = "html/text" response.text = "abcdef" response.new_attribute = "new_attribute_value" - response.new_attribute_dict = { - "key": 123 - } + response.new_attribute_dict = {"key": 123} def alter_response_error(response): @@ -143,7 +132,4 @@ def alter_response_error(response): def gen_variables(): - return { - "var_a": 1, - "var_b": 2 - } + return {"var_a": 1, "var_b": 2} diff --git a/tests/test_api.py b/tests/test_api.py index 4055aefc..67825ce6 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -11,64 +11,69 @@ from tests.base import ApiServerUnittest class TestHttpRunner(ApiServerUnittest): - def setUp(self): self.testcase_cli_path = "tests/data/demo_testcase_cli.yml" self.testcase_file_path_list = [ - os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.yml'), - os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.json') + os.path.join(os.getcwd(), "tests/data/demo_testcase_hardcode.yml"), + os.path.join(os.getcwd(), "tests/data/demo_testcase_hardcode.json"), ] - testcases = [{ - 'config': { - 'name': 'testcase description', - 'request': { - 'base_url': '', - 'headers': {'User-Agent': 'python-requests/2.18.4'} - }, - 'variables': [] - }, - "teststeps": [ - { - 'name': '/api/get-token', - 'request': { - 'url': 'http://127.0.0.1:5000/api/get-token', - 'method': 'POST', - 'headers': {'Content-Type': 'application/json', 'app_version': '2.8.6', - 'device_sn': 'FwgRiO7CNA50DSU', 'os_platform': 'ios', 'user_agent': 'iOS/10.3'}, - 'json': {'sign': '9c0c7e51c91ae963c833a4ccbab8d683c4a90c98'} + testcases = [ + { + "config": { + "name": "testcase description", + "request": { + "base_url": "", + "headers": {"User-Agent": "python-requests/2.18.4"}, }, - 'extract': [ - {'token': 'content.token'} - ], - 'validate': [ - {'eq': ['status_code', 200]}, - {'eq': ['headers.Content-Type', 'application/json']}, - {'eq': ['content.success', True]} - ] + "variables": [], }, - { - 'name': '/api/users/1000', - 'request': { - 'url': 'http://127.0.0.1:5000/api/users/1000', - 'method': 'POST', - 'headers': {'Content-Type': 'application/json', - 'device_sn': 'FwgRiO7CNA50DSU','token': '$token'}, - 'json': {'name': 'user1', 'password': '123456'} + "teststeps": [ + { + "name": "/api/get-token", + "request": { + "url": "http://127.0.0.1:5000/api/get-token", + "method": "POST", + "headers": { + "Content-Type": "application/json", + "app_version": "2.8.6", + "device_sn": "FwgRiO7CNA50DSU", + "os_platform": "ios", + "user_agent": "iOS/10.3", + }, + "json": { + "sign": "9c0c7e51c91ae963c833a4ccbab8d683c4a90c98" + }, + }, + "extract": [{"token": "content.token"}], + "validate": [ + {"eq": ["status_code", 200]}, + {"eq": ["headers.Content-Type", "application/json"]}, + {"eq": ["content.success", True]}, + ], }, - 'validate': [ - {'eq': ['status_code', 201]}, - {'eq': ['headers.Content-Type', 'application/json']}, - {'eq': ['content.success', True]}, - {'eq': ['content.msg', 'user created successfully.']} - ] - } - ] - }] - self.tests_mapping = { - "testcases": testcases - } + { + "name": "/api/users/1000", + "request": { + "url": "http://127.0.0.1:5000/api/users/1000", + "method": "POST", + "headers": { + "Content-Type": "application/json", + "device_sn": "FwgRiO7CNA50DSU", + "token": "$token", + }, + "json": {"name": "user1", "password": "123456"}, + }, + "validate": [ + {"eq": ["status_code", 201]}, + {"eq": ["headers.Content-Type", "application/json"]}, + {"eq": ["content.success", True]}, + {"eq": ["content.msg", "user created successfully."]}, + ], + }, + ], + } + ] + self.tests_mapping = {"testcases": testcases} self.runner = HttpRunner(failfast=True) self.reset_all() @@ -85,10 +90,7 @@ class TestHttpRunner(ApiServerUnittest): def test_text_run_times_invalid(self): testcases = [ { - "config": { - 'name': "post data", - 'variables': [] - }, + "config": {"name": "post data", "variables": []}, "teststeps": [ { "name": "post data", @@ -98,20 +100,16 @@ class TestHttpRunner(ApiServerUnittest): "method": "POST", "headers": { "User-Agent": "python-requests/2.18.4", - "Content-Type": "application/json" + "Content-Type": "application/json", }, - "data": "abc" + "data": "abc", }, - "validate": [ - {"eq": ["status_code", 200]} - ] + "validate": [{"eq": ["status_code", 200]}], } - ] + ], } ] - tests_mapping = { - "testcases": testcases - } + tests_mapping = {"testcases": testcases} with self.assertRaises(exceptions.ParamsError): self.runner.run_tests(tests_mapping) @@ -123,12 +121,9 @@ class TestHttpRunner(ApiServerUnittest): testcases = [ { "config": { - 'name': "post data", - 'variables': { - "var1": "abc", - "var2": "def" - }, - "export": ["status_code", "req_data"] + "name": "post data", + "variables": {"var1": "abc", "var2": "def"}, + "export": ["status_code", "req_data"], }, "teststeps": [ { @@ -138,24 +133,20 @@ class TestHttpRunner(ApiServerUnittest): "method": "POST", "headers": { "User-Agent": "python-requests/2.18.4", - "Content-Type": "application/json" + "Content-Type": "application/json", }, - "data": "$var1" + "data": "$var1", }, "extract": { "status_code": "status_code", - "req_data": "content.data" + "req_data": "content.data", }, - "validate": [ - {"eq": ["status_code", 200]} - ] + "validate": [{"eq": ["status_code", 200]}], } - ] + ], } ] - tests_mapping = { - "testcases": testcases - } + tests_mapping = {"testcases": testcases} self.runner.run_tests(tests_mapping) vars_out = self.runner.get_vars_out() self.assertIsInstance(vars_out, list) @@ -166,7 +157,8 @@ class TestHttpRunner(ApiServerUnittest): def test_save_variables_output_with_parameters(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/testsuites/create_users_with_parameters.yml') + os.getcwd(), "tests/testsuites/create_users_with_parameters.yml" + ) self.runner.run(testcase_file_path) vars_out = self.runner.get_vars_out() self.assertIsInstance(vars_out, list) @@ -188,7 +180,7 @@ class TestHttpRunner(ApiServerUnittest): self.assertEqual(summary["stat"]["teststeps"]["total"], 10) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) - report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") + report_save_dir = os.path.join(os.getcwd(), "reports", "demo") report.gen_html_report(summary, report_dir=report_save_dir) self.assertGreater(len(os.listdir(report_save_dir)), 0) shutil.rmtree(report_save_dir) @@ -200,7 +192,7 @@ class TestHttpRunner(ApiServerUnittest): self.assertEqual(summary["stat"]["teststeps"]["total"], 10) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) - report_file = os.path.join(os.getcwd(), 'reports', "demo", "test.html") + report_file = os.path.join(os.getcwd(), "reports", "demo", "test.html") report.gen_html_report(summary, report_file=report_file) report_save_dir = os.path.dirname(report_file) self.assertEqual(len(os.listdir(report_save_dir)), 1) @@ -208,7 +200,7 @@ class TestHttpRunner(ApiServerUnittest): shutil.rmtree(report_save_dir) def test_log_file(self): - log_file_path = os.path.join(os.getcwd(), 'reports', "test_log_file.log") + log_file_path = os.path.join(os.getcwd(), "reports", "test_log_file.log") runner = HttpRunner(failfast=True, log_file=log_file_path) runner.run(self.testcase_cli_path) self.assertTrue(os.path.isfile(log_file_path)) @@ -223,10 +215,7 @@ class TestHttpRunner(ApiServerUnittest): self.assertIn("records", summary["details"][0]) def test_run_yaml_upload(self): - upload_cases_list = [ - "tests/httpbin/upload.yml", - "tests/httpbin/upload.v2.yml" - ] + upload_cases_list = ["tests/httpbin/upload.yml", "tests/httpbin/upload.v2.yml"] for upload_case in upload_cases_list: summary = self.runner.run(upload_case) self.assertTrue(summary["success"]) @@ -238,10 +227,7 @@ class TestHttpRunner(ApiServerUnittest): def test_run_post_data(self): testcases = [ { - "config": { - 'name': "post data", - 'variables': [] - }, + "config": {"name": "post data", "variables": []}, "teststeps": [ { "name": "post data", @@ -250,35 +236,32 @@ class TestHttpRunner(ApiServerUnittest): "method": "POST", "headers": { "User-Agent": "python-requests/2.18.4", - "Content-Type": "application/json" + "Content-Type": "application/json", }, - "data": "abc" + "data": "abc", }, - "validate": [ - {"eq": ["status_code", 200]} - ] + "validate": [{"eq": ["status_code", 200]}], } - ] + ], } ] - tests_mapping = { - "testcases": testcases - } + tests_mapping = {"testcases": testcases} summary = self.runner.run_tests(tests_mapping) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 1) - resp_json = json.loads(summary["details"][0]["records"][0]["meta_datas"]["data"][0]["response"]["body"]) - self.assertEqual( - resp_json["data"], - "abc" + resp_json = json.loads( + summary["details"][0]["records"][0]["meta_datas"]["data"][0]["response"][ + "body" + ] ) + self.assertEqual(resp_json["data"], "abc") def test_html_report_repsonse_image(self): runner = HttpRunner(failfast=True) summary = runner.run("tests/httpbin/load_image.yml") - report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") + report_save_dir = os.path.join(os.getcwd(), "reports", "demo") report_path = report.gen_html_report(summary, report_dir=report_save_dir) self.assertTrue(os.path.isfile(report_path)) shutil.rmtree(report_save_dir) @@ -286,7 +269,9 @@ class TestHttpRunner(ApiServerUnittest): def test_testcase_layer_with_api(self): summary = self.runner.run("tests/testcases/setup.yml") self.assertTrue(summary["success"]) - self.assertEqual(summary["details"][0]["records"][0]["name"], "get token (setup)") + self.assertEqual( + summary["details"][0]["records"][0]["name"], "get token (setup)" + ) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 2) @@ -301,8 +286,7 @@ class TestHttpRunner(ApiServerUnittest): self.assertFalse(summary["success"]) def test_run_httprunner_with_hooks(self): - testcase_file_path = os.path.join( - os.getcwd(), 'tests/httpbin/hooks.yml') + testcase_file_path = os.path.join(os.getcwd(), "tests/httpbin/hooks.yml") start_time = time.time() summary = self.runner.run(testcase_file_path) end_time = time.time() @@ -319,11 +303,9 @@ class TestHttpRunner(ApiServerUnittest): "request": { "url": "{}/headers".format(HTTPBIN_SERVER), "method": "GET", - "data": "abc" + "data": "abc", }, - "teardown_hooks": [ - "${alter_response($response)}" - ], + "teardown_hooks": ["${alter_response($response)}"], "validate": [ {"eq": ["status_code", 500]}, {"eq": ["headers.content-type", "html/text"]}, @@ -332,16 +314,16 @@ class TestHttpRunner(ApiServerUnittest): {"eq": ["text.headers.Host", "127.0.0.1:8888"]}, {"eq": ["new_attribute", "new_attribute_value"]}, {"eq": ["new_attribute_dict", {"key": 123}]}, - {"eq": ["new_attribute_dict.key", 123]} - ] + {"eq": ["new_attribute_dict.key", 123]}, + ], } - ] + ], } ] tests_mapping = { "project_mapping": loader.load_project_data("tests"), - "testcases": testcases + "testcases": testcases, } summary = self.runner.run_tests(tests_mapping) self.assertTrue(summary["success"]) @@ -349,30 +331,24 @@ class TestHttpRunner(ApiServerUnittest): def test_run_httprunner_with_teardown_hooks_not_exist_attribute(self): testcases = [ { - "config": { - "name": "test teardown hooks" - }, + "config": {"name": "test teardown hooks"}, "teststeps": [ { "name": "test teardown hooks", "request": { "url": "{}/headers".format(HTTPBIN_SERVER), "method": "GET", - "data": "abc" + "data": "abc", }, - "teardown_hooks": [ - "${alter_response($response)}" - ], - "validate": [ - {"eq": ["attribute_not_exist", "new_attribute"]} - ] + "teardown_hooks": ["${alter_response($response)}"], + "validate": [{"eq": ["attribute_not_exist", "new_attribute"]}], } - ] + ], } ] tests_mapping = { "project_mapping": loader.load_project_data("tests"), - "testcases": testcases + "testcases": testcases, } summary = self.runner.run_tests(tests_mapping) self.assertFalse(summary["success"]) @@ -381,27 +357,23 @@ class TestHttpRunner(ApiServerUnittest): def test_run_httprunner_with_teardown_hooks_error(self): testcases = [ { - "config": { - "name": "test teardown hooks" - }, + "config": {"name": "test teardown hooks"}, "teststeps": [ { "name": "test teardown hooks", "request": { "url": "{}/headers".format(HTTPBIN_SERVER), "method": "GET", - "data": "abc" + "data": "abc", }, - "teardown_hooks": [ - "${alter_response_error($response)}" - ] + "teardown_hooks": ["${alter_response_error($response)}"], } - ] + ], } ] tests_mapping = { "project_mapping": loader.load_project_data("tests"), - "testcases": testcases + "testcases": testcases, } summary = self.runner.run_tests(tests_mapping) self.assertFalse(summary["success"]) @@ -478,29 +450,32 @@ class TestHttpRunner(ApiServerUnittest): self.assertEqual(summary["stat"]["teststeps"]["total"], 3) self.assertEqual(summary["stat"]["teststeps"]["successes"], 3) - def test_run_testcase_template_variables(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_variables.yml') + os.getcwd(), "tests/data/demo_testcase_variables.yml" + ) summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) def test_run_testcase_template_import_functions(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_functions.yml') + os.getcwd(), "tests/data/demo_testcase_functions.yml" + ) summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) def test_run_testcase_layered(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_layer.yml') + os.getcwd(), "tests/data/demo_testcase_layer.yml" + ) summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertEqual(len(summary["details"]), 1) def test_run_testcase_output(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_layer.yml') + os.getcwd(), "tests/data/demo_testcase_layer.yml" + ) summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertIn("token", summary["details"][0]["in_out"]["out"]) @@ -509,10 +484,9 @@ class TestHttpRunner(ApiServerUnittest): def test_run_testcase_with_variables_mapping(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_layer.yml') - variables_mapping = { - "app_version": '2.9.7' - } + os.getcwd(), "tests/data/demo_testcase_layer.yml" + ) + variables_mapping = {"app_version": "2.9.7"} summary = self.runner.run(testcase_file_path, mapping=variables_mapping) self.assertTrue(summary["success"]) self.assertIn("token", summary["details"][0]["in_out"]["out"]) @@ -521,7 +495,8 @@ class TestHttpRunner(ApiServerUnittest): def test_run_testcase_with_parameters(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/testsuites/create_users_with_parameters.yml') + os.getcwd(), "tests/testsuites/create_users_with_parameters.yml" + ) summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertEqual(len(summary["details"]), 3 * 2) @@ -530,16 +505,13 @@ class TestHttpRunner(ApiServerUnittest): self.assertEqual(summary["stat"]["teststeps"]["total"], 3 * 2 * 2) self.assertEqual( summary["details"][0]["name"], - "create user 101 and check result for TESTSUITE_X1." + "create user 101 and check result for TESTSUITE_X1.", ) self.assertEqual( summary["details"][5]["name"], - "create user 103 and check result for TESTSUITE_X2." - ) - self.assertEqual( - summary["details"][0]["stat"]["total"], - 2 + "create user 103 and check result for TESTSUITE_X2.", ) + self.assertEqual(summary["details"][0]["stat"]["total"], 2) records_name_list = [ summary["details"][i]["records"][1]["meta_datas"][1]["name"] for i in range(6) @@ -552,59 +524,51 @@ class TestHttpRunner(ApiServerUnittest): "create user 102 for TESTSUITE_X1", "create user 102 for TESTSUITE_X2", "create user 103 for TESTSUITE_X1", - "create user 103 for TESTSUITE_X2" - } + "create user 103 for TESTSUITE_X2", + }, ) def test_validate_response_content(self): - testcase_file_path = os.path.join( - os.getcwd(), 'tests/httpbin/basic.yml') + testcase_file_path = os.path.join(os.getcwd(), "tests/httpbin/basic.yml") summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) def test_html_report_xss(self): testcases = [ { - "config": { - 'name': "post data" - }, + "config": {"name": "post data"}, "teststeps": [ { "name": "post data", "request": { "url": "{}/anything".format(HTTPBIN_SERVER), "method": "POST", - "headers": { - "Content-Type": "application/json" - }, + "headers": {"Content-Type": "application/json"}, "json": { - 'success': False, - "person": "" - } + "success": False, + "person": "", + }, }, - "validate": [ - {"eq": ["status_code", 200]} - ] + "validate": [{"eq": ["status_code", 200]}], } - ] + ], } ] - tests_mapping = { - "testcases": testcases - } + tests_mapping = {"testcases": testcases} summary = self.runner.run(tests_mapping) report_path = report.gen_html_report(summary) with open(report_path) as f: content = f.read() m = re.findall( - re.escape(""person": "<img src=x onerror=alert(1)>""), - content + re.escape( + ""person": "<img src=x onerror=alert(1)>"" + ), + content, ) self.assertEqual(len(m), 2) class TestApi(ApiServerUnittest): - def test_testcase_loader(self): testcase_path = "tests/testcases/setup.yml" tests_mapping = loader.load_cases(testcase_path) @@ -628,7 +592,9 @@ class TestApi(ApiServerUnittest): self.assertEqual(testcase_tests[0]["name"], "get token (setup)") self.assertIsInstance(testcase_tests[0]["variables"], dict) self.assertIn("api_def", testcase_tests[0]) - self.assertEqual(testcase_tests[0]["api_def"]["request"]["url"], "/api/get-token") + self.assertEqual( + testcase_tests[0]["api_def"]["request"]["url"], "/api/get-token" + ) def test_testcase_parser(self): testcase_path = "tests/testcases/setup.yml" @@ -696,7 +662,7 @@ class TestApi(ApiServerUnittest): "tests/testcases/create_user.yml", "tests/testcases/create_user.v2.yml", "tests/testcases/create_user.json", - "tests/testcases/create_user.v2.json" + "tests/testcases/create_user.v2.json", ]: tests_mapping = loader.load_cases(testcase_path) testcases = parser.parse_tests(tests_mapping) @@ -708,11 +674,10 @@ class TestApi(ApiServerUnittest): results = tests_results[0][1] self.assertEqual( results.records[0]["name"], - "setup and reset all (override) for TESTCASE_CREATE_XXX." + "setup and reset all (override) for TESTCASE_CREATE_XXX.", ) self.assertEqual( - results.records[1]["name"], - "create user and check result." + results.records[1]["name"], "create user and check result." ) def test_testsuite_loader(self): @@ -740,11 +705,14 @@ class TestApi(ApiServerUnittest): self.assertIn("testcase_def", testcase_tests) self.assertEqual(testcase_tests["name"], "create user 1000 and check result.") self.assertIsInstance(testcase_tests["testcase_def"], dict) - self.assertEqual(testcase_tests["testcase_def"]["config"]["name"], "create user and check result.") + self.assertEqual( + testcase_tests["testcase_def"]["config"]["name"], + "create user and check result.", + ) self.assertEqual(len(testcase_tests["testcase_def"]["teststeps"]), 2) self.assertEqual( testcase_tests["testcase_def"]["teststeps"][0]["name"], - "setup and reset all (override) for $device_sn." + "setup and reset all (override) for $device_sn.", ) def test_testsuite_parser(self): @@ -756,14 +724,13 @@ class TestApi(ApiServerUnittest): self.assertEqual(len(parsed_testcases[0]["teststeps"]), 2) testcase1 = parsed_testcases[0]["teststeps"][0] - self.assertIn("setup and reset all (override)", testcase1["config"]["name"].raw_string) + self.assertIn( + "setup and reset all (override)", testcase1["config"]["name"].raw_string + ) teststeps = testcase1["teststeps"] self.assertNotIn("testcase_def", testcase1) self.assertEqual(len(teststeps), 2) - self.assertEqual( - teststeps[0]["request"]["url"], - "/api/get-token" - ) + self.assertEqual(teststeps[0]["request"]["url"], "/api/get-token") def test_testsuite_add_tests(self): testcase_path = "tests/testsuites/create_users.yml" @@ -775,7 +742,9 @@ class TestApi(ApiServerUnittest): self.assertEqual(len(test_suite._tests), 2) tests = test_suite._tests[0].teststeps - self.assertIn("setup and reset all (override)", tests[0]["config"]["name"].raw_string) + self.assertIn( + "setup and reset all (override)", tests[0]["config"]["name"].raw_string + ) def test_testsuite_run_suite(self): testcase_path = "tests/testsuites/create_users.yml" @@ -790,11 +759,5 @@ class TestApi(ApiServerUnittest): self.assertEqual(len(tests_results[0][1].records), 2) results = tests_results[0][1] - self.assertIn( - "setup and reset all (override)", - results.records[0]["name"] - ) - self.assertEqual( - results.records[1]["name"], - "create user and check result." - ) + self.assertIn("setup and reset all (override)", results.records[0]["name"]) + self.assertEqual(results.records[1]["name"], "create user and check result.") diff --git a/tests/test_apiserver.py b/tests/test_apiserver.py index 5d144349..ac5c45b6 100644 --- a/tests/test_apiserver.py +++ b/tests/test_apiserver.py @@ -2,7 +2,6 @@ from tests.base import ApiServerUnittest class TestApiServer(ApiServerUnittest): - def setUp(self): super(TestApiServer, self).setUp() self.headers = self.get_authenticated_headers() @@ -25,10 +24,7 @@ class TestApiServer(ApiServerUnittest): def create_user(self, uid, name, password): url = "%s/api/users/%d" % (self.host, uid) - data = { - 'name': name, - 'password': password - } + data = {"name": name, "password": password} return self.api_client.post(url, headers=self.headers, json=data) def get_user(self, uid): @@ -37,10 +33,7 @@ class TestApiServer(ApiServerUnittest): def update_user(self, uid, name, password): url = "%s/api/users/%d" % (self.host, uid) - data = { - 'name': name, - 'password': password - } + data = {"name": name, "password": password} return self.api_client.put(url, headers=self.headers, json=data) def delete_user(self, uid): @@ -50,63 +43,63 @@ class TestApiServer(ApiServerUnittest): def test_reset_all(self): resp = self.reset_all() self.assertEqual(200, resp.status_code) - self.assertEqual(True, resp.json()['success']) + self.assertEqual(True, resp.json()["success"]) def test_create_user_not_existed(self): - resp = self.create_user(1000, 'user1', '123456') + resp = self.create_user(1000, "user1", "123456") self.assertEqual(201, resp.status_code) - self.assertEqual(True, resp.json()['success']) + self.assertEqual(True, resp.json()["success"]) def test_create_user_existed(self): - resp = self.create_user(1000, 'user1', '123456') - resp = self.create_user(1000, 'user1', '123456') + resp = self.create_user(1000, "user1", "123456") + resp = self.create_user(1000, "user1", "123456") self.assertEqual(500, resp.status_code) def test_get_users_empty(self): resp = self.get_users() self.assertEqual(200, resp.status_code) - self.assertEqual(resp.json()['count'], 0) + self.assertEqual(resp.json()["count"], 0) def test_get_users_not_empty(self): - resp = self.create_user(1000, 'user1', '123456') + resp = self.create_user(1000, "user1", "123456") resp = self.get_users() self.assertEqual(200, resp.status_code) - self.assertEqual(resp.json()['count'], 1) + self.assertEqual(resp.json()["count"], 1) - resp = self.create_user(1001, 'user2', '123456') + resp = self.create_user(1001, "user2", "123456") resp = self.get_users() self.assertEqual(200, resp.status_code) - self.assertEqual(resp.json()['count'], 2) + self.assertEqual(resp.json()["count"], 2) def test_get_user_not_existed(self): resp = self.get_user(1000) self.assertEqual(404, resp.status_code) - self.assertEqual(resp.json()['success'], False) + self.assertEqual(resp.json()["success"], False) def test_get_user_existed(self): - self.create_user(1000, 'user1', '123456') + self.create_user(1000, "user1", "123456") resp = self.get_user(1000) self.assertEqual(200, resp.status_code) - self.assertEqual(resp.json()['success'], True) + self.assertEqual(resp.json()["success"], True) def test_update_user_not_existed(self): - resp = self.update_user(1000, 'user1', '123456') + resp = self.update_user(1000, "user1", "123456") self.assertEqual(404, resp.status_code) - self.assertEqual(resp.json()['success'], False) + self.assertEqual(resp.json()["success"], False) def test_update_user_existed(self): - self.create_user(1000, 'user1', '123456') - resp = self.update_user(1000, 'user2', '123456') + self.create_user(1000, "user1", "123456") + resp = self.update_user(1000, "user2", "123456") self.assertEqual(200, resp.status_code) - self.assertEqual(resp.json()['data']['name'], 'user2') + self.assertEqual(resp.json()["data"]["name"], "user2") def test_delete_user_not_existed(self): resp = self.delete_user(1000) self.assertEqual(404, resp.status_code) - self.assertEqual(resp.json()['success'], False) + self.assertEqual(resp.json()["success"], False) def test_delete_user_existed(self): - self.create_user(1000, 'leo', '123456') + self.create_user(1000, "leo", "123456") resp = self.delete_user(1000) self.assertEqual(200, resp.status_code) - self.assertEqual(resp.json()['success'], True) + self.assertEqual(resp.json()["success"], True) diff --git a/tests/test_cli.py b/tests/test_cli.py index abf2a714..8b1a4f98 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,7 +6,6 @@ from httprunner.compat import io class TestCli(unittest.TestCase): - def setUp(self): self.captured_output = io.StringIO() sys.stdout = self.captured_output @@ -23,6 +22,7 @@ class TestCli(unittest.TestCase): self.assertEqual(cm.exception.code, 0) from httprunner import __version__ + self.assertIn(__version__, self.captured_output.getvalue().strip()) def test_show_help(self): @@ -34,4 +34,5 @@ class TestCli(unittest.TestCase): self.assertEqual(cm.exception.code, 0) from httprunner import __description__ + self.assertIn(__description__, self.captured_output.getvalue().strip()) diff --git a/tests/test_client.py b/tests/test_client.py index 8dc3dd3a..075dd746 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -20,30 +20,21 @@ class TestHttpClient(ApiServerUnittest): def test_request_with_full_url(self): url = "%s/api/users/1000" % self.host - data = { - 'name': 'user1', - 'password': '123456' - } + data = {"name": "user1", "password": "123456"} resp = self.api_client.post(url, json=data, headers=self.headers) self.assertEqual(201, resp.status_code) - self.assertEqual(True, resp.json()['success']) + self.assertEqual(True, resp.json()["success"]) def test_request_without_base_url(self): url = "{}/api/users/1000".format(self.host) - data = { - 'name': 'user1', - 'password': '123456' - } + data = {"name": "user1", "password": "123456"} resp = self.api_client.post(url, json=data, headers=self.headers) self.assertEqual(201, resp.status_code) - self.assertEqual(True, resp.json()['success']) + self.assertEqual(True, resp.json()["success"]) def test_request_post_data(self): url = "{}/api/users/1000".format(self.host) - data = { - 'name': 'user1', - 'password': '123456' - } + data = {"name": "user1", "password": "123456"} resp = self.api_client.post(url, json=data, headers=self.headers) # b'{"name": "user1", "password": "123456"}' self.assertIn(b'"name": "user1"', resp.request.body) @@ -56,14 +47,8 @@ class TestHttpClient(ApiServerUnittest): def test_request_with_cookies(self): url = "{}/api/users/1000".format(self.host) - data = { - 'name': 'user1', - 'password': '123456' - } - cookies = { - "a": "1", - "b": "2" - } + data = {"name": "user1", "password": "123456"} + cookies = {"a": "1", "b": "2"} resp = self.api_client.get(url, cookies=cookies, headers=self.headers) self.assertEqual(resp.request._cookies["a"], "1") self.assertEqual(resp.request._cookies["b"], "2") diff --git a/tests/test_context.py b/tests/test_context.py index 46bbf343..392fc24d 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -6,17 +6,13 @@ from tests.base import ApiServerUnittest, gen_random_string class TestContext(ApiServerUnittest): - def setUp(self): loader.load_project_data(os.path.join(os.getcwd(), "tests")) - self.context = context.SessionContext( - variables={"SECRET_KEY": "DebugTalk"} - ) + self.context = context.SessionContext(variables={"SECRET_KEY": "DebugTalk"}) def test_init_test_variables_initialize(self): self.assertEqual( - self.context.test_variables_mapping, - {'SECRET_KEY': 'DebugTalk'} + self.context.test_variables_mapping, {"SECRET_KEY": "DebugTalk"} ) def test_init_test_variables(self): @@ -28,36 +24,25 @@ class TestContext(ApiServerUnittest): # "data": '{"name": "$username", "password": "123456"}', "TOKEN": "debugtalk", "username": "user1", - "num": 6 - } - functions = { - "gen_random_string": gen_random_string, - "gen_md5": gen_md5 + "num": 6, } + functions = {"gen_random_string": gen_random_string, "gen_md5": gen_md5} variables = parser.prepare_lazy_data(variables, functions, variables.keys()) variables = parser.parse_variables_mapping(variables) self.context.init_test_variables(variables) variables_mapping = self.context.test_variables_mapping self.assertEqual(len(variables_mapping["random"]), 6) self.assertEqual(len(variables_mapping["authorization"]), 32) - self.assertEqual(variables_mapping["data"], 'user1') + self.assertEqual(variables_mapping["data"], "user1") def test_update_seesion_variables(self): self.context.update_session_variables({"TOKEN": "debugtalk"}) - self.assertEqual( - self.context.session_variables_mapping["TOKEN"], - "debugtalk" - ) + self.assertEqual(self.context.session_variables_mapping["TOKEN"], "debugtalk") def test_eval_content_variables(self): - variables = { - "SECRET_KEY": "DebugTalk" - } + variables = {"SECRET_KEY": "DebugTalk"} content = parser.prepare_lazy_data("abc$SECRET_KEY", {}, variables.keys()) - self.assertEqual( - self.context.eval_content(content), - "abcDebugTalk" - ) + self.assertEqual(self.context.eval_content(content), "abcDebugTalk") # TODO: fix variable extraction # content = "abc$SECRET_KEYdef" @@ -71,12 +56,9 @@ class TestContext(ApiServerUnittest): "random": "${gen_random_string(5)}", "data": '{"name": "user", "password": "123456"}', "authorization": "${gen_md5($TOKEN, $data, $random)}", - "TOKEN": "debugtalk" - } - functions = { - "gen_random_string": gen_random_string, - "gen_md5": gen_md5 + "TOKEN": "debugtalk", } + functions = {"gen_random_string": gen_random_string, "gen_md5": gen_md5} variables = parser.prepare_lazy_data(variables, functions, variables.keys()) variables = parser.parse_variables_mapping(variables) self.context.init_test_variables(variables) @@ -88,14 +70,12 @@ class TestContext(ApiServerUnittest): "Content-Type": "application/json", "authorization": "$authorization", "random": "$random", - "secret_key": "$SECRET_KEY" + "secret_key": "$SECRET_KEY", }, - "data": "$data" + "data": "$data", } prepared_request = parser.prepare_lazy_data( - request, - functions, - {"authorization", "random", "SECRET_KEY", "data"} + request, functions, {"authorization", "random", "SECRET_KEY", "data"} ) parsed_request = self.context.eval_content(prepared_request) self.assertIn("authorization", parsed_request["headers"]) @@ -104,17 +84,14 @@ class TestContext(ApiServerUnittest): self.assertEqual(len(parsed_request["headers"]["random"]), 5) self.assertIn("data", parsed_request) self.assertEqual( - parsed_request["data"], - '{"name": "user", "password": "123456"}' + parsed_request["data"], '{"name": "user", "password": "123456"}' ) self.assertEqual(parsed_request["headers"]["secret_key"], "DebugTalk") def test_validate(self): testcases = [ { - "config": { - 'name': "test validation" - }, + "config": {"name": "test validation"}, "teststeps": [ { "name": "test validation", @@ -124,26 +101,32 @@ class TestContext(ApiServerUnittest): }, "variables": { "resp_status_code": 200, - "resp_body_success": True + "resp_body_success": True, }, "validate": [ {"eq": ["$resp_status_code", 200]}, - {"check": "$resp_status_code", "comparator": "eq", "expect": 200}, + { + "check": "$resp_status_code", + "comparator": "eq", + "expect": 200, + }, {"check": "$resp_body_success", "expect": True}, - {"check": "${is_status_code_200($resp_status_code)}", "expect": True} - ] + { + "check": "${is_status_code_200($resp_status_code)}", + "expect": True, + }, + ], } - ] + ], } ] from tests.debugtalk import is_status_code_200 + tests_mapping = { "project_mapping": { - "functions": { - "is_status_code_200": is_status_code_200 - } + "functions": {"is_status_code_200": is_status_code_200} }, - "testcases": testcases + "testcases": testcases, } testcases = parser.parse_tests(tests_mapping) parsed_testcase = testcases[0] @@ -154,9 +137,7 @@ class TestContext(ApiServerUnittest): def test_validate_exception(self): testcases = [ { - "config": { - 'name': "test validation" - }, + "config": {"name": "test validation"}, "teststeps": [ { "name": "test validation", @@ -166,20 +147,22 @@ class TestContext(ApiServerUnittest): }, "variables": { "resp_status_code": 200, - "resp_body_success": True + "resp_body_success": True, }, "validate": [ {"eq": ["$resp_status_code", 201]}, {"check": "$resp_status_code", "expect": 201}, - {"check": "$resp_body_success", "comparator": "eq", "expect": True} - ] + { + "check": "$resp_body_success", + "comparator": "eq", + "expect": True, + }, + ], } - ] + ], } ] - tests_mapping = { - "testcases": testcases - } + tests_mapping = {"testcases": testcases} testcases = parser.parse_tests(tests_mapping) parsed_testcase = testcases[0] test_runner = runner.Runner(parsed_testcase["config"]) diff --git a/tests/test_extension/test_locusts.py b/tests/test_extension/test_locusts.py index 59d957ff..b513dc56 100644 --- a/tests/test_extension/test_locusts.py +++ b/tests/test_extension/test_locusts.py @@ -5,15 +5,13 @@ from httprunner.ext.locusts.utils import prepare_locust_tests class TestLocust(unittest.TestCase): - def test_prepare_locust_tests(self): - path = os.path.join( - os.getcwd(), 'tests/locust_tests/demo_locusts.yml') + path = os.path.join(os.getcwd(), "tests/locust_tests/demo_locusts.yml") locust_tests = prepare_locust_tests(path) self.assertEqual(len(locust_tests), 2 + 3) name_list = [ "create user 1000 and check result.", - "create user 1001 and check result." + "create user 1001 and check result.", ] self.assertIn(locust_tests[0]["config"]["name"], name_list) self.assertIn(locust_tests[4]["config"]["name"], name_list) diff --git a/tests/test_loader/test_cases.py b/tests/test_loader/test_cases.py index 5a4dcea1..09c9449b 100644 --- a/tests/test_loader/test_cases.py +++ b/tests/test_loader/test_cases.py @@ -1,4 +1,3 @@ - import os import unittest @@ -7,14 +6,15 @@ from httprunner.loader import buildup class TestModuleLoader(unittest.TestCase): - def test_filter_module_functions(self): module_functions = buildup.load_module_functions(buildup) self.assertIn("load_module_functions", module_functions) self.assertNotIn("is_py3", module_functions) def test_load_debugtalk_module(self): - project_mapping = buildup.load_project_data(os.path.join(os.getcwd(), "httprunner")) + project_mapping = buildup.load_project_data( + os.path.join(os.getcwd(), "httprunner") + ) self.assertNotIn("alter_response", project_mapping["functions"]) project_mapping = buildup.load_project_data(os.path.join(os.getcwd(), "tests")) @@ -28,51 +28,38 @@ class TestModuleLoader(unittest.TestCase): project_mapping = buildup.load_project_data("tests/data/demo_testcase.yml") project_working_directory = project_mapping["PWD"] debugtalk_functions = project_mapping["functions"] - self.assertEqual( - project_working_directory, - os.path.join(os.getcwd(), "tests") - ) + self.assertEqual(project_working_directory, os.path.join(os.getcwd(), "tests")) self.assertIn("gen_md5", debugtalk_functions) project_mapping = buildup.load_project_data("tests/base.py") project_working_directory = project_mapping["PWD"] debugtalk_functions = project_mapping["functions"] - self.assertEqual( - project_working_directory, - os.path.join(os.getcwd(), "tests") - ) + self.assertEqual(project_working_directory, os.path.join(os.getcwd(), "tests")) self.assertIn("gen_md5", debugtalk_functions) project_mapping = buildup.load_project_data("httprunner/__init__.py") project_working_directory = project_mapping["PWD"] debugtalk_functions = project_mapping["functions"] - self.assertEqual( - project_working_directory, - os.getcwd() - ) + self.assertEqual(project_working_directory, os.getcwd()) self.assertEqual(debugtalk_functions, {}) class TestSuiteLoader(unittest.TestCase): - @classmethod def setUpClass(cls): - cls.project_mapping = buildup.load_project_data(os.path.join(os.getcwd(), "tests")) + cls.project_mapping = buildup.load_project_data( + os.path.join(os.getcwd(), "tests") + ) cls.tests_def_mapping = buildup.tests_def_mapping def test_load_teststep_api(self): raw_test = { "name": "create user (override).", "api": "api/create_user.yml", - "variables": [ - {"uid": "999"} - ] + "variables": [{"uid": "999"}], } teststep = buildup.load_teststep(raw_test) - self.assertEqual( - "create user (override).", - teststep["name"] - ) + self.assertEqual("create user (override).", teststep["name"]) self.assertIn("api_def", teststep) api_def = teststep["api_def"] self.assertEqual(api_def["name"], "create user") @@ -82,15 +69,10 @@ class TestSuiteLoader(unittest.TestCase): raw_test = { "name": "setup and reset all (override).", "testcase": "testcases/setup.yml", - "variables": [ - {"device_sn": "$device_sn"} - ] + "variables": [{"device_sn": "$device_sn"}], } testcase = buildup.load_teststep(raw_test) - self.assertEqual( - "setup and reset all (override).", - testcase["name"] - ) + self.assertEqual("setup and reset all (override).", testcase["name"]) tests = testcase["testcase_def"]["teststeps"] self.assertEqual(len(tests), 2) self.assertEqual(tests[0]["name"], "get token (setup)") @@ -106,7 +88,7 @@ class TestSuiteLoader(unittest.TestCase): def test_load_test_file_testcase(self): for loaded_content in [ buildup.load_test_file("tests/testcases/setup.yml"), - buildup.load_test_file("tests/testcases/setup.json") + buildup.load_test_file("tests/testcases/setup.json"), ]: self.assertEqual(loaded_content["type"], "testcase") self.assertIn("path", loaded_content) @@ -118,7 +100,7 @@ class TestSuiteLoader(unittest.TestCase): def test_load_test_file_testcase_v2(self): for loaded_content in [ buildup.load_test_file("tests/testcases/setup.v2.yml"), - buildup.load_test_file("tests/testcases/setup.v2.json") + buildup.load_test_file("tests/testcases/setup.v2.json"), ]: self.assertEqual(loaded_content["type"], "testcase") self.assertIn("path", loaded_content) @@ -130,38 +112,45 @@ class TestSuiteLoader(unittest.TestCase): def test_load_test_file_testsuite(self): for loaded_content in [ buildup.load_test_file("tests/testsuites/create_users.yml"), - buildup.load_test_file("tests/testsuites/create_users.json") + buildup.load_test_file("tests/testsuites/create_users.json"), ]: self.assertEqual(loaded_content["type"], "testsuite") testcases = loaded_content["testcases"] self.assertEqual(len(testcases), 2) - self.assertIn('create user 1000 and check result.', testcases) - self.assertIn('testcase_def', testcases["create user 1000 and check result."]) + self.assertIn("create user 1000 and check result.", testcases) + self.assertIn( + "testcase_def", testcases["create user 1000 and check result."] + ) self.assertEqual( - testcases["create user 1000 and check result."]["testcase_def"]["config"]["name"], - "create user and check result." + testcases["create user 1000 and check result."]["testcase_def"][ + "config" + ]["name"], + "create user and check result.", ) def test_load_test_file_testsuite_v2(self): for loaded_content in [ buildup.load_test_file("tests/testsuites/create_users.v2.yml"), - buildup.load_test_file("tests/testsuites/create_users.v2.json") + buildup.load_test_file("tests/testsuites/create_users.v2.json"), ]: self.assertEqual(loaded_content["type"], "testsuite") testcases = loaded_content["testcases"] self.assertEqual(len(testcases), 2) - self.assertIn('create user 1000 and check result.', testcases) - self.assertIn('testcase_def', testcases["create user 1000 and check result."]) + self.assertIn("create user 1000 and check result.", testcases) + self.assertIn( + "testcase_def", testcases["create user 1000 and check result."] + ) self.assertEqual( - testcases["create user 1000 and check result."]["testcase_def"]["config"]["name"], - "create user and check result." + testcases["create user 1000 and check result."]["testcase_def"][ + "config" + ]["name"], + "create user and check result.", ) def test_load_tests_api_file(self): - path = os.path.join( - os.getcwd(), 'tests/api/create_user.yml') + path = os.path.join(os.getcwd(), "tests/api/create_user.yml") tests_mapping = loader.load_cases(path) project_mapping = tests_mapping["project_mapping"] api_list = tests_mapping["apis"] @@ -170,8 +159,7 @@ class TestSuiteLoader(unittest.TestCase): def test_load_tests_testcase_file(self): # absolute file path - path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.json') + path = os.path.join(os.getcwd(), "tests/data/demo_testcase_hardcode.json") tests_mapping = loader.load_cases(path) project_mapping = tests_mapping["project_mapping"] testcases_list = tests_mapping["testcases"] @@ -180,7 +168,7 @@ class TestSuiteLoader(unittest.TestCase): self.assertIn("get_sign", project_mapping["functions"]) # relative file path - path = 'tests/data/demo_testcase_hardcode.yml' + path = "tests/data/demo_testcase_hardcode.yml" tests_mapping = loader.load_cases(path) project_mapping = tests_mapping["project_mapping"] testcases_list = tests_mapping["testcases"] @@ -189,91 +177,75 @@ class TestSuiteLoader(unittest.TestCase): self.assertIn("get_sign", project_mapping["functions"]) def test_load_tests_testcase_file_2(self): - testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase.yml') + testcase_file_path = os.path.join(os.getcwd(), "tests/data/demo_testcase.yml") tests_mapping = loader.load_cases(testcase_file_path) testcases = tests_mapping["testcases"] self.assertIsInstance(testcases, list) - self.assertEqual(testcases[0]["config"]["name"], '123t$var_a') - self.assertIn( - "sum_two", - tests_mapping["project_mapping"]["functions"] + self.assertEqual(testcases[0]["config"]["name"], "123t$var_a") + self.assertIn("sum_two", tests_mapping["project_mapping"]["functions"]) + self.assertEqual( + testcases[0]["config"]["variables"]["var_c"], "${sum_two($var_a, $var_b)}" ) self.assertEqual( - testcases[0]["config"]["variables"]["var_c"], - "${sum_two($var_a, $var_b)}" - ) - self.assertEqual( - testcases[0]["config"]["variables"]["PROJECT_KEY"], - "${ENV(PROJECT_KEY)}" + testcases[0]["config"]["variables"]["PROJECT_KEY"], "${ENV(PROJECT_KEY)}" ) def test_load_tests_testcase_file_with_api_ref(self): - path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_layer.yml') + path = os.path.join(os.getcwd(), "tests/data/demo_testcase_layer.yml") tests_mapping = loader.load_cases(path) project_mapping = tests_mapping["project_mapping"] testcases_list = tests_mapping["testcases"] - self.assertIn('device_sn', testcases_list[0]["config"]["variables"]) + self.assertIn("device_sn", testcases_list[0]["config"]["variables"]) self.assertIn("gen_md5", project_mapping["functions"]) self.assertIn("base_url", testcases_list[0]["config"]) test_dict0 = testcases_list[0]["teststeps"][0] - self.assertEqual( - "get token with $user_agent, $app_version", - test_dict0["name"] - ) + self.assertEqual("get token with $user_agent, $app_version", test_dict0["name"]) self.assertIn("/api/get-token", test_dict0["api_def"]["request"]["url"]) - self.assertIn( - {'eq': ['status_code', 200]}, - test_dict0["validate"] - ) + self.assertIn({"eq": ["status_code", 200]}, test_dict0["validate"]) def test_load_tests_testsuite_file_with_testcase_ref(self): - path = os.path.join( - os.getcwd(), 'tests/testsuites/create_users.yml') + path = os.path.join(os.getcwd(), "tests/testsuites/create_users.yml") tests_mapping = loader.load_cases(path) project_mapping = tests_mapping["project_mapping"] testsuites_list = tests_mapping["testsuites"] + self.assertEqual("create users with uid", testsuites_list[0]["config"]["name"]) self.assertEqual( - "create users with uid", - testsuites_list[0]["config"]["name"] - ) - self.assertEqual( - '${gen_random_string(15)}', - testsuites_list[0]["config"]["variables"]['device_sn'] + "${gen_random_string(15)}", + testsuites_list[0]["config"]["variables"]["device_sn"], ) self.assertIn( - "create user 1000 and check result.", - testsuites_list[0]["testcases"] + "create user 1000 and check result.", testsuites_list[0]["testcases"] ) self.assertEqual( - testsuites_list[0]["testcases"]["create user 1000 and check result."]["testcase_def"]["config"]["name"], - "create user and check result." + testsuites_list[0]["testcases"]["create user 1000 and check result."][ + "testcase_def" + ]["config"]["name"], + "create user and check result.", ) def test_load_tests_folder_path(self): # absolute folder path - path = os.path.join(os.getcwd(), 'tests/data') + path = os.path.join(os.getcwd(), "tests/data") tests_mapping = loader.load_cases(path) testcase_list_1 = tests_mapping["testcases"] self.assertGreater(len(testcase_list_1), 4) # relative folder path - path = 'tests/data/' + path = "tests/data/" tests_mapping = loader.load_cases(path) testcase_list_2 = tests_mapping["testcases"] self.assertEqual(len(testcase_list_1), len(testcase_list_2)) def test_load_tests_path_not_exist(self): # absolute folder path - path = os.path.join(os.getcwd(), 'tests/data_not_exist') + path = os.path.join(os.getcwd(), "tests/data_not_exist") with self.assertRaises(exceptions.FileNotFound): loader.load_cases(path) # relative folder path - path = 'tests/data_not_exist' + path = "tests/data_not_exist" with self.assertRaises(exceptions.FileNotFound): loader.load_cases(path) @@ -281,5 +253,11 @@ class TestSuiteLoader(unittest.TestCase): buildup.load_project_data(os.path.join(os.getcwd(), "tests")) self.assertIn("gen_md5", self.project_mapping["functions"]) self.assertEqual(self.project_mapping["env"]["PROJECT_KEY"], "ABCDEFGH") - self.assertEqual(self.project_mapping["PWD"], os.path.abspath(os.path.dirname(os.path.dirname(__file__)))) - self.assertEqual(self.project_mapping["test_path"], os.path.abspath(os.path.dirname(os.path.dirname(__file__)))) + self.assertEqual( + self.project_mapping["PWD"], + os.path.abspath(os.path.dirname(os.path.dirname(__file__))), + ) + self.assertEqual( + self.project_mapping["test_path"], + os.path.abspath(os.path.dirname(os.path.dirname(__file__))), + ) diff --git a/tests/test_loader/test_check.py b/tests/test_loader/test_check.py index 62de19b1..46ac9afe 100644 --- a/tests/test_loader/test_check.py +++ b/tests/test_loader/test_check.py @@ -4,7 +4,6 @@ from httprunner.loader import check class TestLoaderCheck(unittest.TestCase): - def test_is_testcases(self): data_structure = "path/to/file" self.assertFalse(check.is_test_content(data_structure)) @@ -12,11 +11,7 @@ class TestLoaderCheck(unittest.TestCase): self.assertFalse(check.is_test_content(data_structure)) data_structure = { - "project_mapping": { - "PWD": "XXXXX", - "functions": {}, - "env": {} - }, + "project_mapping": {"PWD": "XXXXX", "functions": {}, "env": {}}, "testcases": [ { # testcase data structure "config": { @@ -27,19 +22,19 @@ class TestLoaderCheck(unittest.TestCase): "teststeps": [ # test data structure { - 'name': 'test step desc1', - 'variables': [], # optional - 'extract': {}, # optional - 'validate': [], - 'request': { + "name": "test step desc1", + "variables": [], # optional + "extract": {}, # optional + "validate": [], + "request": { "method": "GET", - "url": "https://docs.httprunner.org" - } + "url": "https://docs.httprunner.org", + }, }, # test_dict2 # another test dict - ] + ], }, # testcase_dict_2 # another testcase dict - ] + ], } self.assertTrue(check.is_test_content(data_structure)) diff --git a/tests/test_loader/test_load.py b/tests/test_loader/test_load.py index 4a2e0f91..132951ac 100644 --- a/tests/test_loader/test_load.py +++ b/tests/test_loader/test_load.py @@ -7,11 +7,10 @@ from httprunner.loader.buildup import load_test_file class TestFileLoader(unittest.TestCase): - def test_load_yaml_file_file_format_error(self): yaml_tmp_file = "tests/data/tmp.yml" # create empty yaml file - with open(yaml_tmp_file, 'w') as f: + with open(yaml_tmp_file, "w") as f: f.write("") with self.assertRaises(exceptions.FileFormatError): @@ -20,7 +19,7 @@ class TestFileLoader(unittest.TestCase): os.remove(yaml_tmp_file) # create invalid format yaml file - with open(yaml_tmp_file, 'w') as f: + with open(yaml_tmp_file, "w") as f: f.write("abc") with self.assertRaises(exceptions.FileFormatError): @@ -31,7 +30,7 @@ class TestFileLoader(unittest.TestCase): def test_load_json_file_file_format_error(self): json_tmp_file = "tests/data/tmp.json" # create empty file - with open(json_tmp_file, 'w') as f: + with open(json_tmp_file, "w") as f: f.write("") with self.assertRaises(exceptions.FileFormatError): @@ -40,7 +39,7 @@ class TestFileLoader(unittest.TestCase): os.remove(json_tmp_file) # create empty json file - with open(json_tmp_file, 'w') as f: + with open(json_tmp_file, "w") as f: f.write("{}") with self.assertRaises(exceptions.FileFormatError): @@ -49,7 +48,7 @@ class TestFileLoader(unittest.TestCase): os.remove(json_tmp_file) # create invalid format json file - with open(json_tmp_file, 'w') as f: + with open(json_tmp_file, "w") as f: f.write("abc") with self.assertRaises(exceptions.FileFormatError): @@ -58,62 +57,62 @@ class TestFileLoader(unittest.TestCase): os.remove(json_tmp_file) def test_load_testcases_bad_filepath(self): - testcase_file_path = os.path.join(os.getcwd(), 'tests/data/demo') + testcase_file_path = os.path.join(os.getcwd(), "tests/data/demo") with self.assertRaises(exceptions.FileNotFound): load.load_file(testcase_file_path) def test_load_json_testcases(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.json') + os.getcwd(), "tests/data/demo_testcase_hardcode.json" + ) testcases = load.load_file(testcase_file_path) self.assertEqual(len(testcases), 3) test = testcases[0]["test"] - self.assertIn('name', test) - self.assertIn('request', test) - self.assertIn('url', test['request']) - self.assertIn('method', test['request']) + self.assertIn("name", test) + self.assertIn("request", test) + self.assertIn("url", test["request"]) + self.assertIn("method", test["request"]) def test_load_yaml_testcases(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.yml') + os.getcwd(), "tests/data/demo_testcase_hardcode.yml" + ) testcases = load.load_file(testcase_file_path) self.assertEqual(len(testcases), 3) test = testcases[0]["test"] - self.assertIn('name', test) - self.assertIn('request', test) - self.assertIn('url', test['request']) - self.assertIn('method', test['request']) + self.assertIn("name", test) + self.assertIn("request", test) + self.assertIn("url", test["request"]) + self.assertIn("method", test["request"]) def test_load_csv_file_one_parameter(self): - csv_file_path = os.path.join( - os.getcwd(), 'tests/data/user_agent.csv') + csv_file_path = os.path.join(os.getcwd(), "tests/data/user_agent.csv") csv_content = load.load_file(csv_file_path) self.assertEqual( csv_content, [ - {'user_agent': 'iOS/10.1'}, - {'user_agent': 'iOS/10.2'}, - {'user_agent': 'iOS/10.3'} - ] + {"user_agent": "iOS/10.1"}, + {"user_agent": "iOS/10.2"}, + {"user_agent": "iOS/10.3"}, + ], ) def test_load_csv_file_multiple_parameters(self): - csv_file_path = os.path.join( - os.getcwd(), 'tests/data/account.csv') + csv_file_path = os.path.join(os.getcwd(), "tests/data/account.csv") csv_content = load.load_file(csv_file_path) self.assertEqual( csv_content, [ - {'username': 'test1', 'password': '111111'}, - {'username': 'test2', 'password': '222222'}, - {'username': 'test3', 'password': '333333'} - ] + {"username": "test1", "password": "111111"}, + {"username": "test2", "password": "222222"}, + {"username": "test3", "password": "333333"}, + ], ) def test_load_folder_files(self): - folder = os.path.join(os.getcwd(), 'tests') - file1 = os.path.join(os.getcwd(), 'tests', 'test_utils.py') - file2 = os.path.join(os.getcwd(), 'tests', 'api', 'reset_all.yml') + folder = os.path.join(os.getcwd(), "tests") + file1 = os.path.join(os.getcwd(), "tests", "test_utils.py") + file2 = os.path.join(os.getcwd(), "tests", "api", "reset_all.yml") files = load.load_folder_files(folder, recursive=False) self.assertEqual(files, []) @@ -129,25 +128,25 @@ class TestFileLoader(unittest.TestCase): self.assertEqual([], files) def test_load_dot_env_file(self): - dot_env_path = os.path.join( - os.getcwd(), "tests", ".env" - ) + dot_env_path = os.path.join(os.getcwd(), "tests", ".env") env_variables_mapping = load.load_dot_env_file(dot_env_path) self.assertIn("PROJECT_KEY", env_variables_mapping) self.assertEqual(env_variables_mapping["UserName"], "debugtalk") def test_load_custom_dot_env_file(self): - dot_env_path = os.path.join( - os.getcwd(), "tests", "data", "test.env" - ) + dot_env_path = os.path.join(os.getcwd(), "tests", "data", "test.env") env_variables_mapping = load.load_dot_env_file(dot_env_path) self.assertIn("PROJECT_KEY", env_variables_mapping) self.assertEqual(env_variables_mapping["UserName"], "test") - self.assertEqual(env_variables_mapping["content_type"], "application/json; charset=UTF-8") + self.assertEqual( + env_variables_mapping["content_type"], "application/json; charset=UTF-8" + ) def test_load_env_path_not_exist(self): dot_env_path = os.path.join( - os.getcwd(), "tests", "data", + os.getcwd(), + "tests", + "data", ) env_variables_mapping = load.load_dot_env_file(dot_env_path) self.assertEqual(env_variables_mapping, {}) diff --git a/tests/test_loader/test_locate.py b/tests/test_loader/test_locate.py index 54a2d15c..df26aad7 100644 --- a/tests/test_loader/test_locate.py +++ b/tests/test_loader/test_locate.py @@ -1,4 +1,3 @@ - import os import unittest @@ -7,7 +6,6 @@ from httprunner.loader import locate class TestLoaderLocate(unittest.TestCase): - def test_locate_file(self): with self.assertRaises(exceptions.FileNotFound): locate.locate_file(os.getcwd(), "debugtalk.py") @@ -18,23 +16,21 @@ class TestLoaderLocate(unittest.TestCase): start_path = os.path.join(os.getcwd(), "tests") self.assertEqual( locate.locate_file(start_path, "debugtalk.py"), - os.path.join( - os.getcwd(), "tests/debugtalk.py" - ) + os.path.join(os.getcwd(), "tests/debugtalk.py"), ) self.assertEqual( locate.locate_file("tests/", "debugtalk.py"), - os.path.join(os.getcwd(), "tests", "debugtalk.py") + os.path.join(os.getcwd(), "tests", "debugtalk.py"), ) self.assertEqual( locate.locate_file("tests", "debugtalk.py"), - os.path.join(os.getcwd(), "tests", "debugtalk.py") + os.path.join(os.getcwd(), "tests", "debugtalk.py"), ) self.assertEqual( locate.locate_file("tests/base.py", "debugtalk.py"), - os.path.join(os.getcwd(), "tests", "debugtalk.py") + os.path.join(os.getcwd(), "tests", "debugtalk.py"), ) self.assertEqual( locate.locate_file("tests/data/demo_testcase.yml", "debugtalk.py"), - os.path.join(os.getcwd(), "tests", "debugtalk.py") + os.path.join(os.getcwd(), "tests", "debugtalk.py"), ) diff --git a/tests/test_parser.py b/tests/test_parser.py index 67356d6f..c7c8ee93 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -8,7 +8,6 @@ from tests.debugtalk import gen_random_string, sum_two class TestParserBasic(unittest.TestCase): - def test_parse_string_value(self): self.assertEqual(parser.parse_string_value("123"), 123) self.assertEqual(parser.parse_string_value("12.3"), 12.3) @@ -17,198 +16,124 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(parser.parse_string_value("${func}"), "${func}") def test_regex_findall_variables(self): - self.assertEqual( - parser.regex_findall_variables("$var"), - ["var"] - ) - self.assertEqual( - parser.regex_findall_variables("$var123"), - ["var123"] - ) - self.assertEqual( - parser.regex_findall_variables("$var_name"), - ["var_name"] - ) - self.assertEqual( - parser.regex_findall_variables("var"), - [] - ) - self.assertEqual( - parser.regex_findall_variables("a$var"), - ["var"] - ) + self.assertEqual(parser.regex_findall_variables("$var"), ["var"]) + self.assertEqual(parser.regex_findall_variables("$var123"), ["var123"]) + self.assertEqual(parser.regex_findall_variables("$var_name"), ["var_name"]) + self.assertEqual(parser.regex_findall_variables("var"), []) + self.assertEqual(parser.regex_findall_variables("a$var"), ["var"]) self.assertEqual( parser.regex_findall_variables("a$var${var2}$var3${var4}"), - ["var", "var2", "var3", "var4"] - ) - self.assertEqual( - parser.regex_findall_variables("$v ar"), - ["v"] - ) - self.assertEqual( - parser.regex_findall_variables(" "), - [] - ) - self.assertEqual( - parser.regex_findall_variables("$abc*"), - ["abc"] - ) - self.assertEqual( - parser.regex_findall_variables("${func()}"), - [] - ) - self.assertEqual( - parser.regex_findall_variables("${func(1,2)}"), - [] + ["var", "var2", "var3", "var4"], ) + self.assertEqual(parser.regex_findall_variables("$v ar"), ["v"]) + self.assertEqual(parser.regex_findall_variables(" "), []) + self.assertEqual(parser.regex_findall_variables("$abc*"), ["abc"]) + self.assertEqual(parser.regex_findall_variables("${func()}"), []) + self.assertEqual(parser.regex_findall_variables("${func(1,2)}"), []) self.assertEqual( parser.regex_findall_variables("${gen_md5($TOKEN, $data, $random)}"), - ["TOKEN", "data", "random"] + ["TOKEN", "data", "random"], ) def test_parse_function_params(self): + self.assertEqual(parser.parse_function_params(""), {"args": [], "kwargs": {}}) + self.assertEqual(parser.parse_function_params("5"), {"args": [5], "kwargs": {}}) self.assertEqual( - parser.parse_function_params(""), - {'args': [], 'kwargs': {}} - ) - self.assertEqual( - parser.parse_function_params("5"), - {'args': [5], 'kwargs': {}} - ) - self.assertEqual( - parser.parse_function_params("1, 2"), - {'args': [1, 2], 'kwargs': {}} + parser.parse_function_params("1, 2"), {"args": [1, 2], "kwargs": {}} ) self.assertEqual( parser.parse_function_params("a=1, b=2"), - {'args': [], 'kwargs': {'a': 1, 'b': 2}} + {"args": [], "kwargs": {"a": 1, "b": 2}}, ) self.assertEqual( parser.parse_function_params("a= 1, b =2"), - {'args': [], 'kwargs': {'a': 1, 'b': 2}} + {"args": [], "kwargs": {"a": 1, "b": 2}}, ) self.assertEqual( parser.parse_function_params("1, 2, a=3, b=4"), - {'args': [1, 2], 'kwargs': {'a': 3, 'b': 4}} + {"args": [1, 2], "kwargs": {"a": 3, "b": 4}}, ) self.assertEqual( parser.parse_function_params("$request, 123"), - {'args': ["$request", 123], 'kwargs': {}} - ) - self.assertEqual( - parser.parse_function_params(" "), - {'args': [], 'kwargs': {}} + {"args": ["$request", 123], "kwargs": {}}, ) + self.assertEqual(parser.parse_function_params(" "), {"args": [], "kwargs": {}}) self.assertEqual( parser.parse_function_params("hello world, a=3, b=4"), - {'args': ["hello world"], 'kwargs': {'a': 3, 'b': 4}} + {"args": ["hello world"], "kwargs": {"a": 3, "b": 4}}, ) self.assertEqual( parser.parse_function_params("$request, 12 3"), - {'args': ["$request", '12 3'], 'kwargs': {}} + {"args": ["$request", "12 3"], "kwargs": {}}, ) def test_extract_variables(self): prepared_content = parser.prepare_lazy_data("123$a", {}, {"a"}) - self.assertEqual( - parser.extract_variables(prepared_content), - {"a"} - ) + self.assertEqual(parser.extract_variables(prepared_content), {"a"}) prepared_content = parser.prepare_lazy_data("$a$b", {}, {"a", "b"}) - self.assertEqual( - parser.extract_variables(prepared_content), - {"a", "b"} - ) - prepared_content = parser.prepare_lazy_data(["$a$b", "$c", "d"], {}, {"a", "b", "c", "d"}) - self.assertEqual( - parser.extract_variables(prepared_content), - {"a", "b", "c"} - ) + self.assertEqual(parser.extract_variables(prepared_content), {"a", "b"}) prepared_content = parser.prepare_lazy_data( - {"a": 1, "b": {"c": "$d", "e": 3}}, - {}, - {"d"} - ) - self.assertEqual( - parser.extract_variables(prepared_content), - {"d"} + ["$a$b", "$c", "d"], {}, {"a", "b", "c", "d"} ) + self.assertEqual(parser.extract_variables(prepared_content), {"a", "b", "c"}) prepared_content = parser.prepare_lazy_data( - {"a": ["$b"], "b": {"c": "$d", "e": 3}}, - {}, - {"b", "d"} - ) - self.assertEqual( - parser.extract_variables(prepared_content), - {"b", "d"} + {"a": 1, "b": {"c": "$d", "e": 3}}, {}, {"d"} ) + self.assertEqual(parser.extract_variables(prepared_content), {"d"}) prepared_content = parser.prepare_lazy_data( - ["$a$b", "$c", {"c": "$d"}], - {}, - {"a", "b", "c", "d"} + {"a": ["$b"], "b": {"c": "$d", "e": 3}}, {}, {"b", "d"} + ) + self.assertEqual(parser.extract_variables(prepared_content), {"b", "d"}) + prepared_content = parser.prepare_lazy_data( + ["$a$b", "$c", {"c": "$d"}], {}, {"a", "b", "c", "d"} ) self.assertEqual( - parser.extract_variables(prepared_content), - {"a", "b", "c", "d"} + parser.extract_variables(prepared_content), {"a", "b", "c", "d"} ) def test_extract_functions(self): + self.assertEqual(parser.regex_findall_functions("${func()}"), [("func", "")]) + self.assertEqual(parser.regex_findall_functions("${func(5)}"), [("func", "5")]) self.assertEqual( - parser.regex_findall_functions("${func()}"), - [('func', '')] - ) - self.assertEqual( - parser.regex_findall_functions("${func(5)}"), - [('func', '5')] - ) - self.assertEqual( - parser.regex_findall_functions("${func(a=1, b=2)}"), - [('func', 'a=1, b=2')] + parser.regex_findall_functions("${func(a=1, b=2)}"), [("func", "a=1, b=2")] ) self.assertEqual( parser.regex_findall_functions("${func(1, $b, c=$x, d=4)}"), - [('func', '1, $b, c=$x, d=4')] + [("func", "1, $b, c=$x, d=4")], ) self.assertEqual( parser.regex_findall_functions("/api/1000?_t=${get_timestamp()}"), - [('get_timestamp', '')] + [("get_timestamp", "")], ) self.assertEqual( - parser.regex_findall_functions("/api/${add(1, 2)}"), - [('add', '1, 2')] + parser.regex_findall_functions("/api/${add(1, 2)}"), [("add", "1, 2")] ) self.assertEqual( parser.regex_findall_functions("/api/${add(1, 2)}?_t=${get_timestamp()}"), - [('add', '1, 2'), ('get_timestamp', '')] + [("add", "1, 2"), ("get_timestamp", "")], ) self.assertEqual( parser.regex_findall_functions("abc${func(1, 2, a=3, b=4)}def"), - [('func', '1, 2, a=3, b=4')] + [("func", "1, 2, a=3, b=4")], ) def test_parse_data(self): content = { - 'request': { - 'url': '/api/users/$uid', - 'method': "$method", - 'headers': {'token': '$token'}, - 'data': { + "request": { + "url": "/api/users/$uid", + "method": "$method", + "headers": {"token": "$token"}, + "data": { "null": None, "true": True, "false": False, "empty_str": "", - "value": "abc${add_one(3)}def" - } + "value": "abc${add_one(3)}def", + }, } } - variables_mapping = { - "uid": 1000, - "method": "POST", - "token": "abc123" - } - functions_mapping = { - "add_one": lambda x: x + 1 - } + variables_mapping = {"uid": 1000, "method": "POST", "token": "abc123"} + functions_mapping = {"add_one": lambda x: x + 1} result = parser.eval_lazy_data(content, variables_mapping, functions_mapping) self.assertEqual("/api/users/1000", result["request"]["url"]) self.assertEqual("abc123", result["request"]["headers"]["token"]) @@ -226,63 +151,68 @@ class TestParserBasic(unittest.TestCase): "var_3": 123, "var_4": {"a": 1}, "var_5": True, - "var_6": None + "var_6": None, } self.assertEqual( - parser.eval_lazy_data("$var_1", variables_mapping=variables_mapping), - "abc" + parser.eval_lazy_data("$var_1", variables_mapping=variables_mapping), "abc" ) self.assertEqual( - parser.eval_lazy_data("var_1", variables_mapping=variables_mapping), - "var_1" + parser.eval_lazy_data("var_1", variables_mapping=variables_mapping), "var_1" ) self.assertEqual( parser.eval_lazy_data("$var_1#XYZ", variables_mapping=variables_mapping), - "abc#XYZ" + "abc#XYZ", ) self.assertEqual( - parser.eval_lazy_data("/$var_1/$var_2/var3", variables_mapping=variables_mapping), - "/abc/def/var3" + parser.eval_lazy_data( + "/$var_1/$var_2/var3", variables_mapping=variables_mapping + ), + "/abc/def/var3", ) self.assertEqual( - parser.eval_lazy_data("/$var_1/$var_2/$var_1", variables_mapping=variables_mapping), - "/abc/def/abc" + parser.eval_lazy_data( + "/$var_1/$var_2/$var_1", variables_mapping=variables_mapping + ), + "/abc/def/abc", ) self.assertEqual( - parser.eval_lazy_data("$var_3", variables_mapping=variables_mapping), - 123 + parser.eval_lazy_data("$var_3", variables_mapping=variables_mapping), 123 ) self.assertEqual( parser.eval_lazy_data("$var_4", variables_mapping=variables_mapping), - {"a": 1} + {"a": 1}, ) self.assertEqual( - parser.eval_lazy_data("$var_5", variables_mapping=variables_mapping), - True + parser.eval_lazy_data("$var_5", variables_mapping=variables_mapping), True ) self.assertEqual( parser.eval_lazy_data("abc$var_5", variables_mapping=variables_mapping), - "abcTrue" + "abcTrue", ) self.assertEqual( parser.eval_lazy_data("abc$var_4", variables_mapping=variables_mapping), - "abc{'a': 1}" + "abc{'a': 1}", ) self.assertEqual( - parser.eval_lazy_data("$var_6", variables_mapping=variables_mapping), - None + parser.eval_lazy_data("$var_6", variables_mapping=variables_mapping), None ) with self.assertRaises(exceptions.VariableNotFound): - parser.eval_lazy_data("/api/$SECRET_KEY", variables_mapping=variables_mapping) + parser.eval_lazy_data( + "/api/$SECRET_KEY", variables_mapping=variables_mapping + ) self.assertEqual( - parser.eval_lazy_data(["$var_1", "$var_2"], variables_mapping=variables_mapping), - ["abc", "def"] + parser.eval_lazy_data( + ["$var_1", "$var_2"], variables_mapping=variables_mapping + ), + ["abc", "def"], ) self.assertEqual( - parser.eval_lazy_data({"$var_1": "$var_2"}, variables_mapping=variables_mapping), - {"abc": "def"} + parser.eval_lazy_data( + {"$var_1": "$var_2"}, variables_mapping=variables_mapping + ), + {"abc": "def"}, ) def test_parse_func_var_abnormal(self): @@ -292,12 +222,10 @@ class TestParserBasic(unittest.TestCase): "var_3": 123, "var_4": {"a": 1}, "var_5": True, - "var_6": None + "var_6": None, } check_variables_set = variables_mapping.keys() - functions_mapping = { - "func1": lambda x,y: str(x) + str(y) - } + functions_mapping = {"func1": lambda x, y: str(x) + str(y)} # { var = parser.LazyString("ABC$var_1{", functions_mapping, check_variables_set) @@ -305,12 +233,16 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc{") - var = parser.LazyString("{ABC$var_1{}a}", functions_mapping, check_variables_set) + var = parser.LazyString( + "{ABC$var_1{}a}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "{{ABC{}{{}}a}}") self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "{ABCabc{}a}") - var = parser.LazyString("AB{C$var_1{}a}", functions_mapping, check_variables_set) + var = parser.LazyString( + "AB{C$var_1{}a}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "AB{{C{}{{}}a}}") self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "AB{Cabc{}a}") @@ -375,28 +307,28 @@ class TestParserBasic(unittest.TestCase): "var_3": 123, "var_4": {"a": 1}, "var_5": True, - "var_6": None + "var_6": None, } check_variables_set = variables_mapping.keys() - functions_mapping = { - "func1": lambda x,y: str(x) + str(y) - } + functions_mapping = {"func1": lambda x, y: str(x) + str(y)} var = parser.LazyString( "ABC${func1($var_1, $var_3)}--${func1($var_1, $var_3)}", functions_mapping, - check_variables_set + check_variables_set, ) self.assertEqual(var._string, "ABC{}--{}") self.assertEqual(var.to_value(variables_mapping), "ABCabc123--abc123") - var = parser.LazyString("ABC${func1($var_1, $var_3)}$var_1", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${func1($var_1, $var_3)}$var_1", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}{}") self.assertEqual(var.to_value(variables_mapping), "ABCabc123abc") var = parser.LazyString( "ABC${func1($var_1, $var_3)}$var_1--${func1($var_1, $var_3)}$var_1", functions_mapping, - check_variables_set + check_variables_set, ) self.assertEqual(var._string, "ABC{}{}--{}{}") self.assertEqual(var.to_value(variables_mapping), "ABCabc123abc--abc123abc") @@ -408,50 +340,61 @@ class TestParserBasic(unittest.TestCase): "var_3": 123, "var_4": {"a": 1}, "var_5": True, - "var_6": None + "var_6": None, } check_variables_set = variables_mapping.keys() - functions_mapping = { - "func1": lambda x,y: str(x) + str(y) - } + functions_mapping = {"func1": lambda x, y: str(x) + str(y)} - var = parser.LazyString("${func1($var_1, $var_3)}", functions_mapping, check_variables_set) + var = parser.LazyString( + "${func1($var_1, $var_3)}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "{}") self.assertIsInstance(var._args[0], parser.LazyFunction) self.assertEqual(var.to_value(variables_mapping), "abc123") - var = parser.LazyString("ABC${func1($var_1, $var_3)}DE", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${func1($var_1, $var_3)}DE", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}DE") self.assertIsInstance(var._args[0], parser.LazyFunction) self.assertEqual(var.to_value(variables_mapping), "ABCabc123DE") - var = parser.LazyString("ABC${func1($var_1, $var_3)}$var_5", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${func1($var_1, $var_3)}$var_5", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}{}") self.assertEqual(var.to_value(variables_mapping), "ABCabc123True") - var = parser.LazyString("ABC${func1($var_1, $var_3)}DE$var_4", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${func1($var_1, $var_3)}DE$var_4", + functions_mapping, + check_variables_set, + ) self.assertEqual(var._string, "ABC{}DE{}") self.assertEqual(var.to_value(variables_mapping), "ABCabc123DE{'a': 1}") - var = parser.LazyString("ABC$var_5${func1($var_1, $var_3)}", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC$var_5${func1($var_1, $var_3)}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}{}") self.assertEqual(var.to_value(variables_mapping), "ABCTrueabc123") # Python builtin functions - var = parser.LazyString("ABC${ord(a)}DEF${len(abcd)}", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${ord(a)}DEF${len(abcd)}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}DEF{}") self.assertEqual(var.to_value(variables_mapping), "ABC97DEF4") def test_parse_variable(self): - """ variable format ${var} and $var - """ + """variable format ${var} and $var""" variables_mapping = { "var_1": "abc", "var_2": "def", "var_3": 123, "var_4": {"a": 1}, "var_5": True, - "var_6": None + "var_6": None, } check_variables_set = variables_mapping.keys() functions_mapping = {} @@ -462,12 +405,16 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc") - var = parser.LazyString("ABC$var_1$var_3", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC$var_1$var_3", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}{}") self.assertEqual(var._args, ["var_1", "var_3"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc123") - var = parser.LazyString("ABC$var_1/$var_3", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC$var_1/$var_3", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}/{}") self.assertEqual(var._args, ["var_1", "var_3"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/123") @@ -482,17 +429,23 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc$") - var = parser.LazyString("ABC$var_1/123$var_1/456", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC$var_1/123$var_1/456", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}/123{}/456") self.assertEqual(var._args, ["var_1", "var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/123abc/456") - var = parser.LazyString("ABC$var_1/$var_2/$var_1", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC$var_1/$var_2/$var_1", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}/{}/{}") self.assertEqual(var._args, ["var_1", "var_2", "var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/def/abc") - var = parser.LazyString("func1($var_1, $var_3)", functions_mapping, check_variables_set) + var = parser.LazyString( + "func1($var_1, $var_3)", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "func1({}, {})") self.assertEqual(var._args, ["var_1", "var_3"]) self.assertEqual(var.to_value(variables_mapping), "func1(abc, 123)") @@ -503,12 +456,16 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc") - var = parser.LazyString("ABC${var_1}${var_3}", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${var_1}${var_3}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}{}") self.assertEqual(var._args, ["var_1", "var_3"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc123") - var = parser.LazyString("ABC${var_1}/${var_3}", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${var_1}/${var_3}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}/{}") self.assertEqual(var._args, ["var_1", "var_3"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/123") @@ -518,83 +475,92 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/") - var = parser.LazyString("ABC${var_1}123", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${var_1}123", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}123") self.assertEqual(var._args, ["var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc123") - var = parser.LazyString("ABC${var_1}/123${var_1}/456", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${var_1}/123${var_1}/456", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}/123{}/456") self.assertEqual(var._args, ["var_1", "var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/123abc/456") - var = parser.LazyString("ABC${var_1}/${var_2}/${var_1}", functions_mapping, check_variables_set) + var = parser.LazyString( + "ABC${var_1}/${var_2}/${var_1}", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "ABC{}/{}/{}") self.assertEqual(var._args, ["var_1", "var_2", "var_1"]) self.assertEqual(var.to_value(variables_mapping), "ABCabc/def/abc") - var = parser.LazyString("func1(${var_1}, ${var_3})", functions_mapping, check_variables_set) + var = parser.LazyString( + "func1(${var_1}, ${var_3})", functions_mapping, check_variables_set + ) self.assertEqual(var._string, "func1({}, {})") self.assertEqual(var._args, ["var_1", "var_3"]) self.assertEqual(var.to_value(variables_mapping), "func1(abc, 123)") def test_parse_data_multiple_identical_variables(self): - variables_mapping = { - "userid": 100, - "data": 1498 - } + variables_mapping = {"userid": 100, "data": 1498} content = "/users/$userid/training/$data?userId=$userid&data=$data" self.assertEqual( parser.eval_lazy_data(content, variables_mapping=variables_mapping), - "/users/100/training/1498?userId=100&data=1498" + "/users/100/training/1498?userId=100&data=1498", ) - variables_mapping = { - "user": 100, - "userid": 1000, - "data": 1498 - } + variables_mapping = {"user": 100, "userid": 1000, "data": 1498} content = "/users/$user/$userid/$data?userId=$userid&data=$data" self.assertEqual( parser.eval_lazy_data(content, variables_mapping=variables_mapping), - "/users/100/1000/1498?userId=1000&data=1498" + "/users/100/1000/1498?userId=1000&data=1498", ) def test_parse_data_functions(self): - functions_mapping = { - "gen_random_string": gen_random_string - } - result = parser.eval_lazy_data("${gen_random_string(5)}", functions_mapping=functions_mapping) + functions_mapping = {"gen_random_string": gen_random_string} + result = parser.eval_lazy_data( + "${gen_random_string(5)}", functions_mapping=functions_mapping + ) self.assertEqual(len(result), 5) add_two_nums = lambda a, b=1: a + b functions_mapping["add_two_nums"] = add_two_nums self.assertEqual( - parser.eval_lazy_data("${add_two_nums(1)}", functions_mapping=functions_mapping), - 2 + parser.eval_lazy_data( + "${add_two_nums(1)}", functions_mapping=functions_mapping + ), + 2, ) self.assertEqual( - parser.eval_lazy_data("${add_two_nums(1, 2)}", functions_mapping=functions_mapping), - 3 + parser.eval_lazy_data( + "${add_two_nums(1, 2)}", functions_mapping=functions_mapping + ), + 3, ) self.assertEqual( - parser.eval_lazy_data("/api/${add_two_nums(1, 2)}", functions_mapping=functions_mapping), - "/api/3" + parser.eval_lazy_data( + "/api/${add_two_nums(1, 2)}", functions_mapping=functions_mapping + ), + "/api/3", ) with self.assertRaises(exceptions.FunctionNotFound): - parser.eval_lazy_data("/api/${gen_md5(abc)}", functions_mapping=functions_mapping) + parser.eval_lazy_data( + "/api/${gen_md5(abc)}", functions_mapping=functions_mapping + ) def test_parse_data_testcase(self): variables = { "uid": "1000", "random": "A2dEx", "authorization": "a83de0ff8d2e896dbd8efb81ba14e17d", - "data": {"name": "user", "password": "123456"} + "data": {"name": "user", "password": "123456"}, } functions = { "add_two_nums": lambda a, b=1: a + b, - "get_timestamp": lambda: int(time.time() * 1000) + "get_timestamp": lambda: int(time.time() * 1000), } testcase_template = { "url": "http://127.0.0.1:5000/api/users/$uid/${add_two_nums(1,2)}", @@ -603,35 +569,22 @@ class TestParserBasic(unittest.TestCase): "Content-Type": "application/json", "authorization": "$authorization", "random": "$random", - "sum": "${add_two_nums(1, 2)}" + "sum": "${add_two_nums(1, 2)}", }, - "body": "$data" + "body": "$data", } parsed_testcase = parser.eval_lazy_data( - testcase_template, - variables_mapping=variables, - functions_mapping=functions + testcase_template, variables_mapping=variables, functions_mapping=functions ) self.assertEqual( - parsed_testcase["url"], - "http://127.0.0.1:5000/api/users/1000/3" + parsed_testcase["url"], "http://127.0.0.1:5000/api/users/1000/3" ) self.assertEqual( - parsed_testcase["headers"]["authorization"], - variables["authorization"] - ) - self.assertEqual( - parsed_testcase["headers"]["random"], - variables["random"] - ) - self.assertEqual( - parsed_testcase["body"], - variables["data"] - ) - self.assertEqual( - parsed_testcase["headers"]["sum"], - 3 + parsed_testcase["headers"]["authorization"], variables["authorization"] ) + self.assertEqual(parsed_testcase["headers"]["random"], variables["random"]) + self.assertEqual(parsed_testcase["body"], variables["data"]) + self.assertEqual(parsed_testcase["headers"]["sum"], 3) def test_parse_variables_mapping(self): variables = { @@ -639,12 +592,12 @@ class TestParserBasic(unittest.TestCase): "varB": "456$varC", "varC": "${sum_two($a, $b)}", "a": 1, - "b": 2 + "b": 2, } - functions = { - "sum_two": sum_two - } - prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys()) + functions = {"sum_two": sum_two} + prepared_variables = parser.prepare_lazy_data( + variables, functions, variables.keys() + ) parsed_variables = parser.parse_variables_mapping(prepared_variables) self.assertEqual(parsed_variables["varA"], "1234563") self.assertEqual(parsed_variables["varB"], "4563") @@ -652,24 +605,20 @@ class TestParserBasic(unittest.TestCase): def test_parse_variables_mapping_fix_duplicate_function_call(self): # fix duplicate function calling - variables = { - "varA": "$varB", - "varB": "${gen_random_string(5)}" - } - functions = { - "gen_random_string": gen_random_string - } - prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys()) + variables = {"varA": "$varB", "varB": "${gen_random_string(5)}"} + functions = {"gen_random_string": gen_random_string} + prepared_variables = parser.prepare_lazy_data( + variables, functions, variables.keys() + ) parsed_variables = parser.parse_variables_mapping(prepared_variables) self.assertEqual(parsed_variables["varA"], parsed_variables["varB"]) def test_parse_variables_mapping_dead_circle(self): - variables = { - "varA": "$varB", - "varB": "123$varC" - } + variables = {"varA": "$varB", "varB": "123$varC"} check_variables_set = {"varA", "varB", "varC"} - prepared_variables = parser.prepare_lazy_data(variables, {}, check_variables_set) + prepared_variables = parser.prepare_lazy_data( + variables, {}, check_variables_set + ) with self.assertRaises(exceptions.VariableNotFound): parser.parse_variables_mapping(prepared_variables) @@ -678,25 +627,18 @@ class TestParserBasic(unittest.TestCase): "varA": "123$varB", "varB": "456$varC", "varC": "${sum_two($a, $b)}", - "b": 2 - } - functions = { - "sum_two": sum_two + "b": 2, } + functions = {"sum_two": sum_two} with self.assertRaises(exceptions.VariableNotFound): parser.prepare_lazy_data(variables, functions, variables.keys()) def test_parse_variables_mapping_ref_self(self): - variables = { - "varC": "${sum_two($a, $b)}", - "a": 1, - "b": 2, - "token": "$token" - } - functions = { - "sum_two": sum_two - } - prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys()) + variables = {"varC": "${sum_two($a, $b)}", "a": 1, "b": 2, "token": "$token"} + functions = {"sum_two": sum_two} + prepared_variables = parser.prepare_lazy_data( + variables, functions, variables.keys() + ) with self.assertRaises(exceptions.VariableNotFound): parser.parse_variables_mapping(prepared_variables) @@ -705,12 +647,12 @@ class TestParserBasic(unittest.TestCase): "host2": "https://httprunner.org", "num3": "${sum_two($num2, 4)}", "num2": "${sum_two($num1, 3)}", - "num1": "${sum_two(1, 2)}" + "num1": "${sum_two(1, 2)}", } - functions = { - "sum_two": sum_two - } - prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys()) + functions = {"sum_two": sum_two} + prepared_variables = parser.prepare_lazy_data( + variables, functions, variables.keys() + ) parsed_testcase = parser.parse_variables_mapping(prepared_variables) self.assertEqual(parsed_testcase["num3"], 10) self.assertEqual(parsed_testcase["num2"], 6) @@ -736,12 +678,12 @@ class TestParserBasic(unittest.TestCase): "varC": "${sum_two($a, $b)}", "a": 1, "b": 2, - "c": "abc" + "c": "abc", } - functions = { - "sum_two": sum_two - } - prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys()) + functions = {"sum_two": sum_two} + prepared_variables = parser.prepare_lazy_data( + variables, functions, variables.keys() + ) parsed_testcase = parser.parse_variables_mapping(prepared_variables) self.assertEqual(parsed_testcase["varA"], "123456$0") self.assertEqual(parsed_testcase["varB"], "456$0") @@ -754,16 +696,10 @@ class TestParserBasic(unittest.TestCase): "num3": "${sum_two($num2, 4)}", "num2": "${sum_two($num1, 3)}", "num1": "${sum_two(1, 2)}", - "num0": 0 + "num0": 0, } - functions = { - "sum_two": sum_two - } - parser.prepare_lazy_data( - variables, - functions, - variables.keys() - ) + functions = {"sum_two": sum_two} + parser.prepare_lazy_data(variables, functions, variables.keys()) def test_prepare_lazy_data_not_found(self): variables = { @@ -771,17 +707,11 @@ class TestParserBasic(unittest.TestCase): "num4": "${sum_two($num0, 5)}", "num3": "${sum_two($num2, 4)}", "num2": "${sum_two($num1, 3)}", - "num1": "${sum_two(1, 2)}" - } - functions = { - "sum_two": sum_two + "num1": "${sum_two(1, 2)}", } + functions = {"sum_two": sum_two} with self.assertRaises(exceptions.VariableNotFound): - parser.prepare_lazy_data( - variables, - functions, - variables.keys() - ) + parser.prepare_lazy_data(variables, functions, variables.keys()) def test_prepare_lazy_data_dual_dollar(self): variables = { @@ -790,13 +720,9 @@ class TestParserBasic(unittest.TestCase): "var2": "abc$$$num0", "var3": "abc$$$$num0", } - functions = { - "sum_two": sum_two - } + functions = {"sum_two": sum_two} prepared_variables = parser.prepare_lazy_data( - variables, - functions, - variables.keys() + variables, functions, variables.keys() ) self.assertEqual(prepared_variables["var1"], "abc$num0") self.assertIsInstance(prepared_variables["var2"], parser.LazyString) @@ -821,105 +747,113 @@ class TestParserBasic(unittest.TestCase): self.assertEqual(parser.get_uniform_comparator("count_eq"), "length_equals") self.assertEqual(parser.get_uniform_comparator("len_gt"), "length_greater_than") - self.assertEqual(parser.get_uniform_comparator("count_gt"), "length_greater_than") - self.assertEqual(parser.get_uniform_comparator("count_greater_than"), "length_greater_than") + self.assertEqual( + parser.get_uniform_comparator("count_gt"), "length_greater_than" + ) + self.assertEqual( + parser.get_uniform_comparator("count_greater_than"), "length_greater_than" + ) - self.assertEqual(parser.get_uniform_comparator("len_ge"), "length_greater_than_or_equals") - self.assertEqual(parser.get_uniform_comparator("count_ge"), "length_greater_than_or_equals") - self.assertEqual(parser.get_uniform_comparator("count_greater_than_or_equals"), "length_greater_than_or_equals") + self.assertEqual( + parser.get_uniform_comparator("len_ge"), "length_greater_than_or_equals" + ) + self.assertEqual( + parser.get_uniform_comparator("count_ge"), "length_greater_than_or_equals" + ) + self.assertEqual( + parser.get_uniform_comparator("count_greater_than_or_equals"), + "length_greater_than_or_equals", + ) self.assertEqual(parser.get_uniform_comparator("len_lt"), "length_less_than") self.assertEqual(parser.get_uniform_comparator("count_lt"), "length_less_than") - self.assertEqual(parser.get_uniform_comparator("count_less_than"), "length_less_than") + self.assertEqual( + parser.get_uniform_comparator("count_less_than"), "length_less_than" + ) - self.assertEqual(parser.get_uniform_comparator("len_le"), "length_less_than_or_equals") - self.assertEqual(parser.get_uniform_comparator("count_le"), "length_less_than_or_equals") - self.assertEqual(parser.get_uniform_comparator("count_less_than_or_equals"), "length_less_than_or_equals") + self.assertEqual( + parser.get_uniform_comparator("len_le"), "length_less_than_or_equals" + ) + self.assertEqual( + parser.get_uniform_comparator("count_le"), "length_less_than_or_equals" + ) + self.assertEqual( + parser.get_uniform_comparator("count_less_than_or_equals"), + "length_less_than_or_equals", + ) def test_parse_validator(self): _validator = {"check": "status_code", "comparator": "eq", "expect": 201} self.assertEqual( parser.uniform_validator(_validator), - {"check": "status_code", "comparator": "equals", "expect": 201} + {"check": "status_code", "comparator": "equals", "expect": 201}, ) - _validator = {'eq': ['status_code', 201]} + _validator = {"eq": ["status_code", 201]} self.assertEqual( parser.uniform_validator(_validator), - {"check": "status_code", "comparator": "equals", "expect": 201} + {"check": "status_code", "comparator": "equals", "expect": 201}, ) def test_extend_validators(self): def_validators = [ - {'eq': ['v1', 200]}, - {"check": "s2", "expect": 16, "comparator": "len_eq"} - ] - current_validators = [ - {"check": "v1", "expect": 201}, - {'len_eq': ['s3', 12]} + {"eq": ["v1", 200]}, + {"check": "s2", "expect": 16, "comparator": "len_eq"}, ] + current_validators = [{"check": "v1", "expect": 201}, {"len_eq": ["s3", 12]}] def_validators = [ - parser.uniform_validator(_validator) - for _validator in def_validators + parser.uniform_validator(_validator) for _validator in def_validators ] ref_validators = [ - parser.uniform_validator(_validator) - for _validator in current_validators + parser.uniform_validator(_validator) for _validator in current_validators ] extended_validators = parser.extend_validators(def_validators, ref_validators) self.assertIn( - {"check": "v1", "expect": 201, "comparator": "equals"}, - extended_validators + {"check": "v1", "expect": 201, "comparator": "equals"}, extended_validators ) self.assertIn( {"check": "s2", "expect": 16, "comparator": "length_equals"}, - extended_validators + extended_validators, ) self.assertIn( {"check": "s3", "expect": 12, "comparator": "length_equals"}, - extended_validators + extended_validators, ) def test_extend_validators_with_dict(self): + def_validators = [{"eq": ["a", {"v": 1}]}, {"eq": [{"b": 1}, 200]}] + current_validators = [{"len_eq": ["s3", 12]}, {"eq": [{"b": 1}, 201]}] def_validators = [ - {'eq': ["a", {"v": 1}]}, - {'eq': [{"b": 1}, 200]} - ] - current_validators = [ - {'len_eq': ['s3', 12]}, - {'eq': [{"b": 1}, 201]} - ] - def_validators = [ - parser.uniform_validator(_validator) - for _validator in def_validators + parser.uniform_validator(_validator) for _validator in def_validators ] ref_validators = [ - parser.uniform_validator(_validator) - for _validator in current_validators + parser.uniform_validator(_validator) for _validator in current_validators ] extended_validators = parser.extend_validators(def_validators, ref_validators) self.assertEqual(len(extended_validators), 3) - self.assertIn({'check': {'b': 1}, 'expect': 201, 'comparator': 'equals'}, extended_validators) - self.assertNotIn({'check': {'b': 1}, 'expect': 200, 'comparator': 'equals'}, extended_validators) + self.assertIn( + {"check": {"b": 1}, "expect": 201, "comparator": "equals"}, + extended_validators, + ) + self.assertNotIn( + {"check": {"b": 1}, "expect": 200, "comparator": "equals"}, + extended_validators, + ) class TestParser(unittest.TestCase): - def test_parse_parameters_raw_list(self): parameters = [ {"user_agent": ["iOS/10.1", "iOS/10.2", "iOS/10.3"]}, - {"username-password": [("user1", "111111"), ["test2", "222222"]]} + {"username-password": [("user1", "111111"), ["test2", "222222"]]}, ] cartesian_product_parameters = parser.parse_parameters(parameters) - self.assertEqual( - len(cartesian_product_parameters), - 3 * 2 - ) + self.assertEqual(len(cartesian_product_parameters), 3 * 2) self.assertEqual( cartesian_product_parameters[0], - {'user_agent': 'iOS/10.1', 'username': 'user1', 'password': '111111'} + {"user_agent": "iOS/10.1", "username": "user1", "password": "111111"}, ) def test_parse_parameters_custom_function(self): @@ -927,44 +861,36 @@ class TestParser(unittest.TestCase): {"user_agent": "${get_user_agent()}"}, {"app_version": "${gen_app_version()}"}, {"username-password": "${get_account()}"}, - {"username2-password2": "${get_account_in_tuple()}"} + {"username2-password2": "${get_account_in_tuple()}"}, ] - dot_env_path = os.path.join( - os.getcwd(), "tests", ".env" - ) + dot_env_path = os.path.join(os.getcwd(), "tests", ".env") load.load_dot_env_file(dot_env_path) from tests import debugtalk + cartesian_product_parameters = parser.parse_parameters( - parameters, - functions_mapping=load.load_module_functions(debugtalk) + parameters, functions_mapping=load.load_module_functions(debugtalk) ) self.assertIn( { - 'user_agent': 'iOS/10.1', - 'app_version': '2.8.5', - 'username': 'user1', - 'password': '111111', - 'username2': 'user1', - 'password2': '111111' + "user_agent": "iOS/10.1", + "app_version": "2.8.5", + "username": "user1", + "password": "111111", + "username2": "user1", + "password2": "111111", }, - cartesian_product_parameters - ) - self.assertEqual( - len(cartesian_product_parameters), - 2 * 2 * 2 * 2 + cartesian_product_parameters, ) + self.assertEqual(len(cartesian_product_parameters), 2 * 2 * 2 * 2) def test_parse_parameters_parameterize(self): loader.load_project_data(os.path.join(os.getcwd(), "tests")) parameters = [ {"app_version": "${parameterize(data/app_version.csv)}"}, - {"username-password": "${parameterize(data/account.csv)}"} + {"username-password": "${parameterize(data/account.csv)}"}, ] cartesian_product_parameters = parser.parse_parameters(parameters) - self.assertEqual( - len(cartesian_product_parameters), - 2 * 3 - ) + self.assertEqual(len(cartesian_product_parameters), 2 * 3) def test_parse_parameters_mix(self): project_mapping = loader.load_project_data(os.path.join(os.getcwd(), "tests")) @@ -972,56 +898,55 @@ class TestParser(unittest.TestCase): parameters = [ {"user_agent": ["iOS/10.1", "iOS/10.2", "iOS/10.3"]}, {"app_version": "${gen_app_version()}"}, - {"username-password": "${parameterize(data/account.csv)}"} + {"username-password": "${parameterize(data/account.csv)}"}, ] cartesian_product_parameters = parser.parse_parameters( - parameters, functions_mapping=project_mapping["functions"]) - self.assertEqual( - len(cartesian_product_parameters), - 3 * 2 * 3 + parameters, functions_mapping=project_mapping["functions"] ) + self.assertEqual(len(cartesian_product_parameters), 3 * 2 * 3) def test_parse_tests_testcase(self): - testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/demo_testcase.yml') + testcase_file_path = os.path.join(os.getcwd(), "tests/data/demo_testcase.yml") tests_mapping = loader.load_cases(testcase_file_path) testcases = tests_mapping["testcases"] self.assertEqual( - testcases[0]["config"]["variables"]["var_c"], - "${sum_two($var_a, $var_b)}" + testcases[0]["config"]["variables"]["var_c"], "${sum_two($var_a, $var_b)}" ) self.assertEqual( - testcases[0]["config"]["variables"]["PROJECT_KEY"], - "${ENV(PROJECT_KEY)}" + testcases[0]["config"]["variables"]["PROJECT_KEY"], "${ENV(PROJECT_KEY)}" ) parsed_testcases = parser.parse_tests(tests_mapping) self.assertIsInstance(parsed_testcases, list) test_dict1 = parsed_testcases[0]["teststeps"][0] - self.assertEqual(test_dict1["variables"]["var_c"].raw_string, "${sum_two($var_a, $var_b)}") - self.assertEqual(test_dict1["variables"]["PROJECT_KEY"].raw_string, "${ENV(PROJECT_KEY)}") + self.assertEqual( + test_dict1["variables"]["var_c"].raw_string, "${sum_two($var_a, $var_b)}" + ) + self.assertEqual( + test_dict1["variables"]["PROJECT_KEY"].raw_string, "${ENV(PROJECT_KEY)}" + ) self.assertIsInstance(parsed_testcases[0]["config"]["name"], parser.LazyString) def test_parse_tests_override_variables(self): tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': '', - 'variables': [ + "name": "", + "variables": [ {"password": "123456"}, - {"creator": "user_test_001"} - ] + {"creator": "user_test_001"}, + ], }, "teststeps": [ { - 'name': 'testcase1', + "name": "testcase1", "variables": [ {"creator": "user_test_002"}, - {"username": "$creator"} + {"username": "$creator"}, ], - 'request': {'url': '/api1', 'method': 'GET'} + "request": {"url": "/api1", "method": "GET"}, } - ] + ], } ] } @@ -1031,26 +956,27 @@ class TestParser(unittest.TestCase): self.assertEqual(test_dict1_variables["username"].raw_string, "$creator") def test_parse_tests_base_url_priority(self): - """ base_url & verify: priority test_dict > config - """ + """base_url & verify: priority test_dict > config""" tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': '', + "name": "", "base_url": "$host", - 'variables': { - "host": "https://github.com" - }, - "verify": False + "variables": {"host": "https://github.com"}, + "verify": False, }, "teststeps": [ { - 'name': 'testcase1', + "name": "testcase1", "base_url": "https://httprunner.org", - 'request': {'url': '/api1', 'method': 'GET', "verify": True} + "request": { + "url": "/api1", + "method": "GET", + "verify": True, + }, } - ] + ], } ] } @@ -1061,24 +987,20 @@ class TestParser(unittest.TestCase): def test_parse_tests_base_url_path_with_variable(self): tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': '', + "name": "", "base_url": "$host1", - 'variables': { - "host1": "https://github.com" - } + "variables": {"host1": "https://github.com"}, }, "teststeps": [ { - 'name': 'testcase1', - "variables": { - "host2": "https://httprunner.org" - }, - 'request': {'url': '$host2/api1', 'method': 'GET'} + "name": "testcase1", + "variables": {"host2": "https://httprunner.org"}, + "request": {"url": "$host2/api1", "method": "GET"}, } - ] + ], } ] } @@ -1086,29 +1008,27 @@ class TestParser(unittest.TestCase): test_dict = parsed_testcases[0]["teststeps"][0] self.assertEqual(test_dict["variables"]["host2"], "https://httprunner.org") parsed_test_dict = parser.parse_lazy_data(test_dict, test_dict["variables"]) - self.assertEqual(parsed_test_dict["request"]["url"], "https://httprunner.org/api1") + self.assertEqual( + parsed_test_dict["request"]["url"], "https://httprunner.org/api1" + ) def test_parse_tests_base_url_test_dict(self): tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': '', + "name": "", "base_url": "$host1", - 'variables': { - "host1": "https://github.com" - } + "variables": {"host1": "https://github.com"}, }, "teststeps": [ { - 'name': 'testcase1', + "name": "testcase1", "base_url": "$host2", - "variables": { - "host2": "https://httprunner.org" - }, - 'request': {'url': '/api1', 'method': 'GET'} + "variables": {"host2": "https://httprunner.org"}, + "request": {"url": "/api1", "method": "GET"}, } - ] + ], } ] } @@ -1122,23 +1042,23 @@ class TestParser(unittest.TestCase): "project_mapping": { "functions": { "sum_two": sum_two, - "gen_random_string": gen_random_string + "gen_random_string": gen_random_string, } }, - 'testcases': [ + "testcases": [ { "config": { - 'name': '', + "name": "", "base_url": "$host1", - 'variables': { + "variables": { "host1": "https://github.com", "var_a": "${gen_random_string(5)}", - "var_b": "$var_a" - } + "var_b": "$var_a", + }, }, "teststeps": [ { - 'name': 'testcase1', + "name": "testcase1", "base_url": "$host2", "variables": { "host2": "https://httprunner.org", @@ -1146,16 +1066,16 @@ class TestParser(unittest.TestCase): "num2": "${sum_two($num1, 3)}", "num1": "${sum_two(1, 2)}", "str1": "${gen_random_string(5)}", - "str2": "$str1" + "str2": "$str1", + }, + "request": { + "url": "/api1/?num1=$num1&num2=$num2&num3=$num3", + "method": "GET", }, - 'request': { - 'url': '/api1/?num1=$num1&num2=$num2&num3=$num3', - 'method': 'GET' - } } - ] + ], } - ] + ], } parsed_testcases = parser.parse_tests(tests_mapping) test_dict = parsed_testcases[0]["teststeps"][0] @@ -1165,97 +1085,90 @@ class TestParser(unittest.TestCase): parsed_test_dict = parser.parse_lazy_data(test_dict, variables) self.assertEqual(parsed_test_dict["base_url"], "https://httprunner.org") self.assertEqual( - parsed_test_dict["request"]["url"], - "/api1/?num1=3&num2=6&num3=10" + parsed_test_dict["request"]["url"], "/api1/?num1=3&num2=6&num3=10" ) self.assertEqual(variables["str1"], variables["str2"]) def test_parse_tests_variable_not_found(self): tests_mapping = { - "project_mapping": { - "functions": { - "sum_two": sum_two - } - }, - 'testcases': [ + "project_mapping": {"functions": {"sum_two": sum_two}}, + "testcases": [ { "config": { - 'name': '', + "name": "", "base_url": "$host1", - 'variables': { - "host1": "https://github.com" - } + "variables": {"host1": "https://github.com"}, }, "teststeps": [ { - 'name': 'testcase1', + "name": "testcase1", "base_url": "$host2", "variables": { "host2": "https://httprunner.org", "num4": "${sum_two($num0, 5)}", "num3": "${sum_two($num2, 4)}", "num2": "${sum_two($num1, 3)}", - "num1": "${sum_two(1, 2)}" + "num1": "${sum_two(1, 2)}", + }, + "request": { + "url": "/api1/?num1=$num1&num2=$num2&num3=$num3&num4=$num4", + "method": "GET", }, - 'request': { - 'url': '/api1/?num1=$num1&num2=$num2&num3=$num3&num4=$num4', - 'method': 'GET' - } } - ] + ], } - ] + ], } parser.parse_tests(tests_mapping) parse_failed_testfiles = parser.get_parse_failed_testfiles() self.assertIn("testcase", parse_failed_testfiles) def test_parse_tests_base_url_teststep_empty(self): - """ base_url & verify: priority test_dict > config - """ + """base_url & verify: priority test_dict > config""" tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': '', + "name": "", "base_url": "$host", - 'variables': { - "host": "https://github.com" - }, - "verify": False + "variables": {"host": "https://github.com"}, + "verify": False, }, "teststeps": [ { - 'name': 'testcase1', + "name": "testcase1", "base_url": "", - 'request': {'url': '/api1', 'method': 'GET', "verify": True} + "request": { + "url": "/api1", + "method": "GET", + "verify": True, + }, } - ] + ], } ] } parsed_testcases = parser.parse_tests(tests_mapping) test_dict = parsed_testcases[0]["teststeps"][0] - self.assertEqual(str(test_dict["base_url"]), 'LazyString($host)') + self.assertEqual(str(test_dict["base_url"]), "LazyString($host)") self.assertEqual(test_dict["request"]["verify"], True) def test_parse_tests_verify_config_set(self): - """ verify priority: test_dict > config - """ + """verify priority: test_dict > config""" tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': 'bugfix verify', + "name": "bugfix verify", "base_url": "https://httpbin.org/", - "verify": False + "verify": False, }, "teststeps": [ { - 'name': 'testcase1', - 'request': {'url': '/headers', 'method': 'GET'} + "name": "testcase1", + "request": {"url": "/headers", "method": "GET"}, } - ] + ], } ] } @@ -1264,21 +1177,20 @@ class TestParser(unittest.TestCase): self.assertEqual(test_dict["request"]["verify"], False) def test_parse_tests_verify_config_unset(self): - """ verify priority: test_dict > config - """ + """verify priority: test_dict > config""" tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': 'bugfix verify', + "name": "bugfix verify", "base_url": "https://httpbin.org/", }, "teststeps": [ { - 'name': 'testcase1', - 'request': {'url': '/headers', 'method': 'GET'} + "name": "testcase1", + "request": {"url": "/headers", "method": "GET"}, } - ] + ], } ] } @@ -1287,22 +1199,25 @@ class TestParser(unittest.TestCase): self.assertEqual(test_dict["request"]["verify"], True) def test_parse_tests_verify_step_set_false(self): - """ verify priority: test_dict > config - """ + """verify priority: test_dict > config""" tests_mapping = { - 'testcases': [ + "testcases": [ { "config": { - 'name': 'bugfix verify', + "name": "bugfix verify", "base_url": "https://httpbin.org/", - "verify": True + "verify": True, }, "teststeps": [ { - 'name': 'testcase1', - 'request': {'url': '/headers', 'method': 'GET', "verify": False} + "name": "testcase1", + "request": { + "url": "/headers", + "method": "GET", + "verify": False, + }, } - ] + ], } ] } @@ -1312,32 +1227,27 @@ class TestParser(unittest.TestCase): def test_parse_tests_verify_nested_testcase_unset(self): tests_mapping = { - 'testcases': [ + "testcases": [ { - 'config': { - 'name': 'inquiry price', - 'verify': False - }, - 'teststeps': [ + "config": {"name": "inquiry price", "verify": False}, + "teststeps": [ { - 'name': 'login system', - 'testcase': 'testcases/deps/login.yml', - 'testcase_def': { - 'config': { - 'name': 'login system' - }, - 'teststeps': [ + "name": "login system", + "testcase": "testcases/deps/login.yml", + "testcase_def": { + "config": {"name": "login system"}, + "teststeps": [ { - 'name': '/', - 'request': { - 'method': 'GET', - 'url': 'https://httpbin.org/' - } + "name": "/", + "request": { + "method": "GET", + "url": "https://httpbin.org/", + }, } - ] - } + ], + }, } - ] + ], } ] } @@ -1347,26 +1257,14 @@ class TestParser(unittest.TestCase): def test_parse_environ(self): os.environ["PROJECT_KEY"] = "ABCDEFGH" - content = { - "variables": [ - {"PROJECT_KEY": "${ENV(PROJECT_KEY)}"} - ] - } + content = {"variables": [{"PROJECT_KEY": "${ENV(PROJECT_KEY)}"}]} result = parser.eval_lazy_data(content) - content = { - "variables": [ - {"PROJECT_KEY": "${ENV(PROJECT_KEY, abc)}"} - ] - } + content = {"variables": [{"PROJECT_KEY": "${ENV(PROJECT_KEY, abc)}"}]} with self.assertRaises(exceptions.ParamsError): parser.eval_lazy_data(content) - content = { - "variables": [ - {"PROJECT_KEY": "${ENV(abc=123)}"} - ] - } + content = {"variables": [{"PROJECT_KEY": "${ENV(abc=123)}"}]} with self.assertRaises(exceptions.ParamsError): parser.eval_lazy_data(content) @@ -1381,26 +1279,35 @@ class TestParser(unittest.TestCase): test_block = { "name": "override block", "times": 3, - "variables": [ - {"var": 123} - ], + "variables": [{"var": 123}], "base_url": "https://httprunner.org", - 'request': { - 'url': '/api/get-token', - 'method': 'POST', - 'headers': {'user_agent': '$user_agent', 'device_sn': '$device_sn', 'os_platform': '$os_platform', 'app_version': '$app_version'}, - 'json': {'sign': '${get_sign($device_sn, $os_platform, $app_version)}'} + "request": { + "url": "/api/get-token", + "method": "POST", + "headers": { + "user_agent": "$user_agent", + "device_sn": "$device_sn", + "os_platform": "$os_platform", + "app_version": "$app_version", + }, + "json": {"sign": "${get_sign($device_sn, $os_platform, $app_version)}"}, }, - 'validate': [ + "validate": [ {"check": "status_code", "comparator": "equals", "expect": 201}, - {"check": "content.token", "comparator": "length_equals", "expect": 32} - ] + {"check": "content.token", "comparator": "length_equals", "expect": 32}, + ], } parser._extend_with_api(test_block, api_def_dict) self.assertEqual(test_block["base_url"], "https://github.com") self.assertEqual(test_block["name"], "override block") - self.assertEqual({'var': 123}, test_block["variables"]) - self.assertIn({'check': 'status_code', 'expect': 201, 'comparator': 'equals'}, test_block["validate"]) - self.assertIn({'check': 'content.token', 'comparator': 'length_equals', 'expect': 32}, test_block["validate"]) + self.assertEqual({"var": 123}, test_block["variables"]) + self.assertIn( + {"check": "status_code", "expect": 201, "comparator": "equals"}, + test_block["validate"], + ) + self.assertIn( + {"check": "content.token", "comparator": "length_equals", "expect": 32}, + test_block["validate"], + ) self.assertEqual(test_block["times"], 3) diff --git a/tests/test_response.py b/tests/test_response.py index ddd90d54..49cd53ee 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -7,17 +7,16 @@ from tests.base import ApiServerUnittest class TestResponse(ApiServerUnittest): - def test_parse_response_object_json(self): url = "http://127.0.0.1:5000/api/users" resp = requests.get(url) resp_obj = response.ResponseObject(resp) - self.assertTrue(hasattr(resp_obj, 'status_code')) - self.assertTrue(hasattr(resp_obj, 'headers')) - self.assertTrue(hasattr(resp_obj, 'content')) - self.assertIn('Content-Type', resp_obj.headers) - self.assertIn('Content-Length', resp_obj.headers) - self.assertIn('success', resp_obj.json) + self.assertTrue(hasattr(resp_obj, "status_code")) + self.assertTrue(hasattr(resp_obj, "headers")) + self.assertTrue(hasattr(resp_obj, "content")) + self.assertIn("Content-Type", resp_obj.headers) + self.assertIn("Content-Length", resp_obj.headers) + self.assertIn("success", resp_obj.json) def test_parse_response_object_content(self): url = "http://127.0.0.1:5000/" @@ -29,19 +28,12 @@ class TestResponse(ApiServerUnittest): resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER)) resp_obj = response.ResponseObject(resp) - extract_binds_list = [ - {"resp_status_code": "status_code"} - ] + extract_binds_list = [{"resp_status_code": "status_code"}] extract_binds_dict = resp_obj.extract_response(extract_binds_list) - self.assertEqual( - extract_binds_dict["resp_status_code"], - 200 - ) + self.assertEqual(extract_binds_dict["resp_status_code"], 200) - extract_binds_list = [ - {"resp_status_code": "status_code.xx"} - ] + extract_binds_list = [{"resp_status_code": "status_code.xx"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) @@ -53,14 +45,16 @@ class TestResponse(ApiServerUnittest): {"resp_encoding": "encoding"}, {"resp_ok": "ok"}, {"resp_reason": "reason"}, - {"resp_url": "url"} + {"resp_url": "url"}, ] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_encoding"], "utf-8") self.assertEqual(extract_binds_dict["resp_ok"], True) self.assertEqual(extract_binds_dict["resp_reason"], "OK") - self.assertEqual(extract_binds_dict["resp_url"], "{}/status/200".format(HTTPBIN_SERVER)) + self.assertEqual( + extract_binds_dict["resp_url"], "{}/status/200".format(HTTPBIN_SERVER) + ) extract_binds_list = [{"resp_encoding": "encoding.xx"}] with self.assertRaises(exceptions.ParamsError): @@ -81,24 +75,15 @@ class TestResponse(ApiServerUnittest): def test_extract_response_cookies(self): resp = requests.get( url="{}/cookies".format(HTTPBIN_SERVER), - headers={ - "accept": "application/json" - } + headers={"accept": "application/json"}, ) resp_obj = response.ResponseObject(resp) - extract_binds_list = [ - {"resp_cookies": "cookies"} - ] + extract_binds_list = [{"resp_cookies": "cookies"}] extract_binds_dict = resp_obj.extract_response(extract_binds_list) - self.assertEqual( - extract_binds_dict["resp_cookies"], - {} - ) + self.assertEqual(extract_binds_dict["resp_cookies"], {}) - extract_binds_list = [ - {"resp_cookies": "cookies.xx"} - ] + extract_binds_list = [{"resp_cookies": "cookies.xx"}] with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list) @@ -106,22 +91,20 @@ class TestResponse(ApiServerUnittest): resp = requests.post( url="{}/anything".format(HTTPBIN_SERVER), json={ - 'success': False, + "success": False, "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, - "cities": ["Guangzhou", "Shenzhen"] - } - } + "cities": ["Guangzhou", "Shenzhen"], + }, + }, ) resp_obj = response.ResponseObject(resp) - extract_binds_list = [ - {"resp_elapsed": "elapsed"} - ] + extract_binds_list = [{"resp_elapsed": "elapsed"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) @@ -129,7 +112,7 @@ class TestResponse(ApiServerUnittest): {"resp_elapsed_microseconds": "elapsed.microseconds"}, {"resp_elapsed_seconds": "elapsed.seconds"}, {"resp_elapsed_days": "elapsed.days"}, - {"resp_elapsed_total_seconds": "elapsed.total_seconds"} + {"resp_elapsed_total_seconds": "elapsed.total_seconds"}, ] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertGreater(extract_binds_dict["resp_elapsed_microseconds"], 1000) @@ -137,9 +120,7 @@ class TestResponse(ApiServerUnittest): self.assertEqual(extract_binds_dict["resp_elapsed_days"], 0) self.assertGreater(extract_binds_dict["resp_elapsed_total_seconds"], 0) - extract_binds_list = [ - {"resp_elapsed": "elapsed.years"} - ] + extract_binds_list = [{"resp_elapsed": "elapsed.years"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) @@ -150,16 +131,16 @@ class TestResponse(ApiServerUnittest): extract_binds_list = [ {"resp_headers": "headers"}, {"resp_headers_content_type": "headers.Content-Type"}, - {"resp_headers_content_type_lowercase": "headers.content-type"} + {"resp_headers_content_type_lowercase": "headers.content-type"}, ] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertIn("Content-Type", extract_binds_dict["resp_headers"]) self.assertIn("text/html", extract_binds_dict["resp_headers_content_type"]) - self.assertIn("text/html", extract_binds_dict["resp_headers_content_type_lowercase"]) + self.assertIn( + "text/html", extract_binds_dict["resp_headers_content_type_lowercase"] + ) - extract_binds_list = [ - {"resp_headers_xxx": "headers.xxx"} - ] + extract_binds_list = [{"resp_headers_xxx": "headers.xxx"}] with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list) @@ -167,16 +148,16 @@ class TestResponse(ApiServerUnittest): resp = requests.post( url="{}/anything".format(HTTPBIN_SERVER), json={ - 'success': False, + "success": False, "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, - "cities": ["Guangzhou", "Shenzhen"] - } - } + "cities": ["Guangzhou", "Shenzhen"], + }, + }, ) # resp.json() # { @@ -218,51 +199,31 @@ class TestResponse(ApiServerUnittest): {"resp_content_content_success": "content.json.success"}, {"resp_content_text_success": "text.json.success"}, {"resp_content_person_first_name": "content.json.person.name.first_name"}, - {"resp_content_cities_1": "content.json.person.cities.1"} + {"resp_content_cities_1": "content.json.person.cities.1"}, ] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual( - extract_binds_dict["resp_headers_content_type"], - "application/json" - ) - self.assertEqual( - extract_binds_dict["resp_content_body_success"], - False - ) - self.assertEqual( - extract_binds_dict["resp_content_content_success"], - False - ) - self.assertEqual( - extract_binds_dict["resp_content_text_success"], - False - ) - self.assertEqual( - extract_binds_dict["resp_content_person_first_name"], - "Leo" - ) - self.assertEqual( - extract_binds_dict["resp_content_cities_1"], - "Shenzhen" + extract_binds_dict["resp_headers_content_type"], "application/json" ) + self.assertEqual(extract_binds_dict["resp_content_body_success"], False) + self.assertEqual(extract_binds_dict["resp_content_content_success"], False) + self.assertEqual(extract_binds_dict["resp_content_text_success"], False) + self.assertEqual(extract_binds_dict["resp_content_person_first_name"], "Leo") + self.assertEqual(extract_binds_dict["resp_content_cities_1"], "Shenzhen") def test_extract_response_body_html(self): resp = requests.get(url=HTTPBIN_SERVER) resp_obj = response.ResponseObject(resp) - extract_binds_list = [ - {"resp_content": "content"} - ] + extract_binds_list = [{"resp_content": "content"}] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertIsInstance(extract_binds_dict["resp_content"], basestring) self.assertIn("httpbin.org", extract_binds_dict["resp_content"]) - extract_binds_list = [ - {"resp_content": "content.xxx"} - ] + extract_binds_list = [{"resp_content": "content.xxx"}] with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list) @@ -272,7 +233,7 @@ class TestResponse(ApiServerUnittest): extract_binds_list = [ {"resp_others_encoding": "encoding"}, - {"resp_others_history": "history"} + {"resp_others_history": "history"}, ] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) @@ -281,21 +242,19 @@ class TestResponse(ApiServerUnittest): resp = requests.post( url="{}/anything".format(HTTPBIN_SERVER), json={ - 'success': False, + "success": False, "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, - "cities": ["Guangzhou", "Shenzhen"] - } - } + "cities": ["Guangzhou", "Shenzhen"], + }, + }, ) - extract_binds_list = [ - {"resp_content_dict_key_error": "content.not_exist"} - ] + extract_binds_list = [{"resp_content_dict_key_error": "content.not_exist"}] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ExtractFailure): @@ -310,80 +269,49 @@ class TestResponse(ApiServerUnittest): resp_obj.extract_response(extract_binds_list) def test_extract_response_json_string(self): - resp = requests.post( - url="{}/anything".format(HTTPBIN_SERVER), - data="abc" - ) + resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), data="abc") - extract_binds_list = [ - {"resp_content_body": "content.data"} - ] + extract_binds_list = [{"resp_content_body": "content.data"}] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) - self.assertEqual( - extract_binds_dict["resp_content_body"], - "abc" - ) + self.assertEqual(extract_binds_dict["resp_content_body"], "abc") def test_extract_text_response(self): resp = requests.post( - url="{}/anything".format(HTTPBIN_SERVER), - data="LB123abcRB789" + url="{}/anything".format(HTTPBIN_SERVER), data="LB123abcRB789" ) extract_binds_list = [ {"resp_content_key1": "LB123(.*)RB789"}, {"resp_content_key2": "LB[\d]*(.*)RB[\d]*"}, - {"resp_content_key3": "LB[\d]*(.*)9"} + {"resp_content_key3": "LB[\d]*(.*)9"}, ] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) - self.assertEqual( - extract_binds_dict["resp_content_key1"], - "abc" - ) - self.assertEqual( - extract_binds_dict["resp_content_key2"], - "abc" - ) - self.assertEqual( - extract_binds_dict["resp_content_key3"], - "abcRB78" - ) + self.assertEqual(extract_binds_dict["resp_content_key1"], "abc") + self.assertEqual(extract_binds_dict["resp_content_key2"], "abc") + self.assertEqual(extract_binds_dict["resp_content_key3"], "abcRB78") def test_extract_text_response_exception(self): resp = requests.post( - url="{}/anything".format(HTTPBIN_SERVER), - data="LB123abcRB789" + url="{}/anything".format(HTTPBIN_SERVER), data="LB123abcRB789" ) - extract_binds_list = [ - {"resp_content_key1": "LB123.*RB789"} - ] + extract_binds_list = [{"resp_content_key1": "LB123.*RB789"}] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) def test_extract_response_empty(self): - resp = requests.post( - url="{}/anything".format(HTTPBIN_SERVER), - data="abc" - ) + resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), data="abc") - extract_binds_list = [ - {"resp_content_body": "content.data"} - ] + extract_binds_list = [{"resp_content_body": "content.data"}] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) - self.assertEqual( - extract_binds_dict["resp_content_body"], - 'abc' - ) + self.assertEqual(extract_binds_dict["resp_content_body"], "abc") - extract_binds_list = [ - {"resp_content_body": "content.data.def"} - ] + extract_binds_list = [{"resp_content_body": "content.data.def"}] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list) diff --git a/tests/test_runner.py b/tests/test_runner.py index c724ab60..1fa61823 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -7,16 +7,11 @@ from tests.base import ApiServerUnittest class TestRunner(ApiServerUnittest): - def setUp(self): project_mapping = loader.load_project_data(os.path.join(os.getcwd(), "tests")) self.debugtalk_functions = project_mapping["functions"] - config = { - "name": "XXX", - "base_url": "http://127.0.0.1", - "verify": False - } + config = {"name": "XXX", "base_url": "http://127.0.0.1", "verify": False} self.test_runner = runner.Runner(config) self.reset_all() @@ -27,10 +22,8 @@ class TestRunner(ApiServerUnittest): def test_run_single_testcase(self): testcase_file_path_list = [ - os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.yml'), - os.path.join( - os.getcwd(), 'tests/data/demo_testcase_hardcode.json') + os.path.join(os.getcwd(), "tests/data/demo_testcase_hardcode.yml"), + os.path.join(os.getcwd(), "tests/data/demo_testcase_hardcode.json"), ] for testcase_file_path in testcase_file_path_list: @@ -50,14 +43,8 @@ class TestRunner(ApiServerUnittest): "config": { "name": "basic test with httpbin", "base_url": HTTPBIN_SERVER, - "setup_hooks": [ - "${sleep(0.5)}", - "${hook_print(setup)}" - ], - "teardown_hooks": [ - "${sleep(1)}", - "${hook_print(teardown)}" - ] + "setup_hooks": ["${sleep(0.5)}", "${hook_print(setup)}"], + "teardown_hooks": ["${sleep(1)}", "${hook_print(teardown)}"], }, "teststeps": [ { @@ -70,24 +57,20 @@ class TestRunner(ApiServerUnittest): "user_agent": "iOS/10.3", "device_sn": "HZfFBh6tU59EdXJ", "os_platform": "ios", - "app_version": "2.8.6" + "app_version": "2.8.6", }, "json": { "sign": "5188962c489d1a35effa99e9346dd5efd4fdabad" - } + }, }, - "validate": [ - {"check": "status_code", "expect": 200} - ] + "validate": [{"check": "status_code", "expect": 200}], } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -107,7 +90,7 @@ class TestRunner(ApiServerUnittest): { "config": { "name": "basic test with httpbin", - "base_url": HTTPBIN_SERVER + "base_url": HTTPBIN_SERVER, }, "teststeps": [ { @@ -116,27 +99,18 @@ class TestRunner(ApiServerUnittest): "request": { "url": "/anything", "method": "POST", - "headers": { - "user_agent": "iOS/10.3", - "os_platform": "ios" - }, - "data": "a=1&b=2" + "headers": {"user_agent": "iOS/10.3", "os_platform": "ios"}, + "data": "a=1&b=2", }, - "setup_hooks": [ - {"total": "${sum_two(1, 5)}"} - ], - "validate": [ - {"check": "status_code", "expect": 200} - ] + "setup_hooks": [{"total": "${sum_two(1, 5)}"}], + "validate": [{"check": "status_code", "expect": 200}], } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -151,7 +125,7 @@ class TestRunner(ApiServerUnittest): { "config": { "name": "basic test with httpbin", - "base_url": HTTPBIN_SERVER + "base_url": HTTPBIN_SERVER, }, "teststeps": [ { @@ -162,29 +136,25 @@ class TestRunner(ApiServerUnittest): "method": "POST", "headers": { "content-type": "application/json", - "user_agent": "iOS/10.3" + "user_agent": "iOS/10.3", }, "json": { "os_platform": "ios", - "sign": "5188962c489d1a35effa99e9346dd5efd4fdabad" - } + "sign": "5188962c489d1a35effa99e9346dd5efd4fdabad", + }, }, - "setup_hooks": [ - "${modify_request_json($request, android)}" - ], + "setup_hooks": ["${modify_request_json($request, android)}"], "validate": [ {"check": "status_code", "expect": 200}, - {"check": "content.json.os_platform", "expect": "android"} - ] + {"check": "content.json.os_platform", "expect": "android"}, + ], } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -194,9 +164,7 @@ class TestRunner(ApiServerUnittest): def test_run_testcase_with_teardown_hooks_success(self): testcases = [ { - "config": { - "name": "basic test with httpbin" - }, + "config": {"name": "basic test with httpbin"}, "teststeps": [ { "name": "get token", @@ -208,25 +176,23 @@ class TestRunner(ApiServerUnittest): "user_agent": "iOS/10.3", "device_sn": "HZfFBh6tU59EdXJ", "os_platform": "ios", - "app_version": "2.8.6" + "app_version": "2.8.6", }, "json": { "sign": "5188962c489d1a35effa99e9346dd5efd4fdabad" - } + }, }, - "validate": [ - {"check": "status_code", "expect": 200} + "validate": [{"check": "status_code", "expect": 200}], + "teardown_hooks": [ + "${teardown_hook_sleep_N_secs($response, 2)}" ], - "teardown_hooks": ["${teardown_hook_sleep_N_secs($response, 2)}"] } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -241,9 +207,7 @@ class TestRunner(ApiServerUnittest): def test_run_testcase_with_teardown_hooks_fail(self): testcases = [ { - "config": { - "name": "basic test with httpbin" - }, + "config": {"name": "basic test with httpbin"}, "teststeps": [ { "name": "get token", @@ -255,25 +219,23 @@ class TestRunner(ApiServerUnittest): "user_agent": "iOS/10.3", "device_sn": "HZfFBh6tU59EdXJ", "os_platform": "ios", - "app_version": "2.8.6" + "app_version": "2.8.6", }, "json": { "sign": "5188962c489d1a35effa99e9346dd5efd4fdabad" - } + }, }, - "validate": [ - {"check": "status_code", "expect": 404} + "validate": [{"check": "status_code", "expect": 404}], + "teardown_hooks": [ + "${teardown_hook_sleep_N_secs($response, 2)}" ], - "teardown_hooks": ["${teardown_hook_sleep_N_secs($response, 2)}"] } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -287,7 +249,8 @@ class TestRunner(ApiServerUnittest): def test_bugfix_type_match(self): testcase_file_path = os.path.join( - os.getcwd(), 'tests/data/bugfix_type_match.yml') + os.getcwd(), "tests/data/bugfix_type_match.yml" + ) tests_mapping = loader.load_cases(testcase_file_path) parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -309,28 +272,38 @@ class TestRunner(ApiServerUnittest): "user_agent": "iOS/10.3", "device_sn": "HZfFBh6tU59EdXJ", "os_platform": "ios", - "app_version": "2.8.6" + "app_version": "2.8.6", }, "json": { "sign": "5188962c489d1a35effa99e9346dd5efd4fdabad" - } + }, }, "validate": [ {"check": "status_code", "expect": 200}, - {"check": "elapsed.seconds", "comparator": "lt", "expect": 1}, + { + "check": "elapsed.seconds", + "comparator": "lt", + "expect": 1, + }, {"check": "elapsed.days", "comparator": "eq", "expect": 0}, - {"check": "elapsed.microseconds", "comparator": "gt", "expect": 1000}, - {"check": "elapsed.total_seconds", "comparator": "lt", "expect": 1} - ] + { + "check": "elapsed.microseconds", + "comparator": "gt", + "expect": 1000, + }, + { + "check": "elapsed.total_seconds", + "comparator": "lt", + "expect": 1, + }, + ], } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] @@ -343,7 +316,7 @@ class TestRunner(ApiServerUnittest): "config": { "name": "basic test with httpbin", "base_url": HTTPBIN_SERVER, - "variables": "${gen_variables()}" + "variables": "${gen_variables()}", }, "teststeps": [ { @@ -352,24 +325,17 @@ class TestRunner(ApiServerUnittest): "request": { "url": "/anything", "method": "POST", - "headers": { - "user_agent": "iOS/10.3", - "os_platform": "ios" - }, - "data": "a=1&b=2" + "headers": {"user_agent": "iOS/10.3", "os_platform": "ios"}, + "data": "a=1&b=2", }, - "validate": [ - {"check": "status_code", "expect": 200} - ] + "validate": [{"check": "status_code", "expect": 200}], } - ] + ], } ] tests_mapping = { - "project_mapping": { - "functions": self.debugtalk_functions - }, - "testcases": testcases + "project_mapping": {"functions": self.debugtalk_functions}, + "testcases": testcases, } parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcase = parsed_testcases[0] diff --git a/tests/test_utils.py b/tests/test_utils.py index 6675188f..10f1ed24 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -7,12 +7,9 @@ from tests.base import ApiServerUnittest class TestUtils(ApiServerUnittest): - def test_set_os_environ(self): self.assertNotIn("abc", os.environ) - variables_mapping = { - "abc": "123" - } + variables_mapping = {"abc": "123"} utils.set_os_environ(variables_mapping) self.assertIn("abc", os.environ) self.assertEqual(os.environ["abc"], "123") @@ -26,8 +23,8 @@ class TestUtils(ApiServerUnittest): "last_name": "Lee", }, "age": 29, - "cities": ["Guangzhou", "Shenzhen"] - } + "cities": ["Guangzhou", "Shenzhen"], + }, } query = "ids.2" result = utils.query_json(json_content, query) @@ -63,6 +60,7 @@ class TestUtils(ApiServerUnittest): def current_validators(self): from httprunner.builtin import comparators + functions_mapping = loader.load.load_module_functions(comparators) functions_mapping["equals"](None, None) @@ -80,17 +78,17 @@ class TestUtils(ApiServerUnittest): functions_mapping["not_equals"](123, "123") functions_mapping["length_equals"]("123", 3) - # Because the Numbers in a CSV file are by default treated as strings, + # Because the Numbers in a CSV file are by default treated as strings, # you need to convert them to Numbers, and we'll test that out here. - functions_mapping["length_equals"]("123", '3') + functions_mapping["length_equals"]("123", "3") with self.assertRaises(AssertionError): - functions_mapping["length_equals"]("123", 'abc') + functions_mapping["length_equals"]("123", "abc") functions_mapping["length_greater_than"]("123", 2) functions_mapping["length_greater_than_or_equals"]("123", 3) functions_mapping["contains"]("123abc456", "3ab") - functions_mapping["contains"](['1', '2'], "1") - functions_mapping["contains"]({'a':1, 'b':2}, "a") + functions_mapping["contains"](["1", "2"], "1") + functions_mapping["contains"]({"a": 1, "b": 2}, "a") functions_mapping["contained_by"]("3ab", "123abc456") functions_mapping["regex_match"]("123abc456", "^123\w+456$") @@ -119,11 +117,8 @@ class TestUtils(ApiServerUnittest): "Request": { "url": "http://127.0.0.1:5000", "METHOD": "POST", - "Headers": { - "Accept": "application/json", - "User-Agent": "ios/9.3" - } - } + "Headers": {"Accept": "application/json", "User-Agent": "ios/9.3"}, + }, } new_dict = utils.lower_test_dict_keys(origin_dict) self.assertIn("name", new_dict) @@ -133,10 +128,7 @@ class TestUtils(ApiServerUnittest): self.assertIn("Accept", new_dict["request"]["headers"]) self.assertIn("User-Agent", new_dict["request"]["headers"]) - origin_dict = { - "Name": "test", - "Request": "$default_request" - } + origin_dict = {"Name": "test", "Request": "$default_request"} new_dict = utils.lower_test_dict_keys(origin_dict) self.assertIn("$default_request", new_dict["request"]) @@ -144,10 +136,7 @@ class TestUtils(ApiServerUnittest): request_dict = { "url": "http://127.0.0.1:5000", "METHOD": "POST", - "Headers": { - "Accept": "application/json", - "User-Agent": "ios/9.3" - } + "Headers": {"Accept": "application/json", "User-Agent": "ios/9.3"}, } new_request_dict = utils.lower_dict_keys(request_dict) self.assertIn("method", new_request_dict) @@ -164,10 +153,7 @@ class TestUtils(ApiServerUnittest): self.assertEqual(None, request_dict) def test_ensure_mapping_format(self): - map_list = [ - {"a": 1}, - {"b": 2} - ] + map_list = [{"a": 1}, {"b": 2}] ordered_dict = utils.ensure_mapping_format(map_list) self.assertIsInstance(ordered_dict, dict) self.assertIn("a", ordered_dict) @@ -175,7 +161,9 @@ class TestUtils(ApiServerUnittest): def test_extend_variables(self): raw_variables = [{"var1": "val1"}, {"var2": "val2"}] override_variables = [{"var1": "val111"}, {"var3": "val3"}] - extended_variables_mapping = utils.extend_variables(raw_variables, override_variables) + extended_variables_mapping = utils.extend_variables( + raw_variables, override_variables + ) self.assertEqual(extended_variables_mapping["var1"], "val111") self.assertEqual(extended_variables_mapping["var2"], "val2") self.assertEqual(extended_variables_mapping["var3"], "val3") @@ -183,25 +171,27 @@ class TestUtils(ApiServerUnittest): def test_extend_variables_fix(self): raw_variables = [{"var1": "val1"}, {"var2": "val2"}] override_variables = {} - extended_variables_mapping = utils.extend_variables(raw_variables, override_variables) + extended_variables_mapping = utils.extend_variables( + raw_variables, override_variables + ) self.assertEqual(extended_variables_mapping["var1"], "val1") def test_deepcopy_dict(self): data = { - 'a': 1, - 'b': [2, 4], - 'c': lambda x: x+1, - 'd': open('LICENSE'), - 'f': { - 'f1': {'a1': 2}, - 'f2': io.open('LICENSE', 'rb'), - } + "a": 1, + "b": [2, 4], + "c": lambda x: x + 1, + "d": open("LICENSE"), + "f": { + "f1": {"a1": 2}, + "f2": io.open("LICENSE", "rb"), + }, } new_data = utils.deepcopy_dict(data) data["a"] = 0 self.assertEqual(new_data["a"], 1) data["f"]["f1"] = 123 - self.assertEqual(new_data["f"]["f1"], {'a1': 2}) + self.assertEqual(new_data["f"]["f1"], {"a1": 2}) self.assertNotEqual(id(new_data["b"]), id(data["b"])) self.assertEqual(id(new_data["c"]), id(data["c"])) # self.assertEqual(id(new_data["d"]), id(data["d"])) @@ -218,41 +208,24 @@ class TestUtils(ApiServerUnittest): shutil.rmtree(project_name) def test_cartesian_product_one(self): - parameters_content_list = [ - [ - {"a": 1}, - {"a": 2} - ] - ] + parameters_content_list = [[{"a": 1}, {"a": 2}]] product_list = utils.gen_cartesian_product(*parameters_content_list) - self.assertEqual( - product_list, - [ - {"a": 1}, - {"a": 2} - ] - ) + self.assertEqual(product_list, [{"a": 1}, {"a": 2}]) def test_cartesian_product_multiple(self): parameters_content_list = [ - [ - {"a": 1}, - {"a": 2} - ], - [ - {"x": 111, "y": 112}, - {"x": 121, "y": 122} - ] + [{"a": 1}, {"a": 2}], + [{"x": 111, "y": 112}, {"x": 121, "y": 122}], ] product_list = utils.gen_cartesian_product(*parameters_content_list) self.assertEqual( product_list, [ - {'a': 1, 'x': 111, 'y': 112}, - {'a': 1, 'x': 121, 'y': 122}, - {'a': 2, 'x': 111, 'y': 112}, - {'a': 2, 'x': 121, 'y': 122} - ] + {"a": 1, "x": 111, "y": 112}, + {"a": 1, "x": 121, "y": 122}, + {"a": 2, "x": 111, "y": 112}, + {"a": 2, "x": 121, "y": 122}, + ], ) def test_cartesian_product_empty(self): @@ -261,15 +234,7 @@ class TestUtils(ApiServerUnittest): self.assertEqual(product_list, []) def test_print_info(self): - info_mapping = { - "a": 1, - "t": (1, 2), - "b": { - "b1": 123 - }, - "c": None, - "d": [4, 5] - } + info_mapping = {"a": 1, "t": (1, 2), "b": {"b1": 123}, "c": None, "d": [4, 5]} utils.print_info(info_mapping) def test_prepare_dump_json_file_path_for_folder(self): @@ -277,11 +242,13 @@ class TestUtils(ApiServerUnittest): project_working_directory = os.path.join(os.getcwd(), "tests") project_mapping = { "PWD": project_working_directory, - "test_path": os.path.join(os.getcwd(), "tests", "httpbin", "a.b.c") + "test_path": os.path.join(os.getcwd(), "tests", "httpbin", "a.b.c"), } self.assertEqual( utils.prepare_dump_json_file_abs_path(project_mapping, "loaded"), - os.path.join(project_working_directory, "logs", "httpbin/a.b.c/all.loaded.json") + os.path.join( + project_working_directory, "logs", "httpbin/a.b.c/all.loaded.json" + ), ) def test_prepare_dump_json_file_path_for_file(self): @@ -289,19 +256,23 @@ class TestUtils(ApiServerUnittest): project_working_directory = os.path.join(os.getcwd(), "tests") project_mapping = { "PWD": project_working_directory, - "test_path": os.path.join(os.getcwd(), "tests", "httpbin", "a.b.c", "rpc.yml") + "test_path": os.path.join( + os.getcwd(), "tests", "httpbin", "a.b.c", "rpc.yml" + ), } self.assertEqual( utils.prepare_dump_json_file_abs_path(project_mapping, "loaded"), - os.path.join(project_working_directory, "logs", "httpbin/a.b.c/rpc.loaded.json") + os.path.join( + project_working_directory, "logs", "httpbin/a.b.c/rpc.loaded.json" + ), ) def test_prepare_dump_json_file_path_for_passed_testcase(self): project_working_directory = os.path.join(os.getcwd(), "tests") - project_mapping = { - "PWD": project_working_directory - } + project_mapping = {"PWD": project_working_directory} self.assertEqual( utils.prepare_dump_json_file_abs_path(project_mapping, "loaded"), - os.path.join(project_working_directory, "logs", "tests_mapping.loaded.json") + os.path.join( + project_working_directory, "logs", "tests_mapping.loaded.json" + ), )