mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-13 17:29:56 +08:00
Merge pull request #923 from httprunner/v3
3.0.9 bugfix - fix: ensure variables - fix: handle exception for loaded invalid format test content - change: do not capture exception for loading har file
This commit is contained in:
@@ -7,7 +7,7 @@ from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
|
||||
class TestCaseRequestWithFunctions(HttpRunner):
|
||||
config = (
|
||||
Config("request with functions")
|
||||
.variables(**{"foo1": "session_bar1", "var1": "testsuite_val1"})
|
||||
.variables(**{"var1": "testsuite_val1", "foo1": "session_bar1"})
|
||||
.base_url("https://postman-echo.com")
|
||||
.verify(False)
|
||||
.export(*["session_foo2"])
|
||||
|
||||
@@ -16,7 +16,7 @@ from examples.postman_echo.request_methods.request_with_functions_test import (
|
||||
class TestCaseRequestWithTestcaseReference(HttpRunner):
|
||||
config = (
|
||||
Config("request with referenced testcase")
|
||||
.variables(**{"foo1": "session_bar1", "var2": "testsuite_val2"})
|
||||
.variables(**{"var2": "testsuite_val2", "foo1": "session_bar1"})
|
||||
.base_url("https://postman-echo.com")
|
||||
.verify(False)
|
||||
)
|
||||
|
||||
@@ -3,15 +3,49 @@ This module handles compatibility issues between testcase format v2 and v3.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from typing import List, Dict, Text, Union
|
||||
from typing import List, Dict, Text, Union, Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from httprunner import exceptions
|
||||
from httprunner.loader import load_project_meta
|
||||
from httprunner.parser import parse_data
|
||||
from httprunner.utils import sort_dict_by_custom_order, ensure_file_path_valid
|
||||
|
||||
|
||||
def convert_variables(
|
||||
raw_variables: Union[Dict, List, Text], test_path: Text
|
||||
) -> Dict[Text, Any]:
|
||||
|
||||
if isinstance(raw_variables, Dict):
|
||||
return raw_variables
|
||||
|
||||
if isinstance(raw_variables, List):
|
||||
# [{"var1": 1}, {"var2": 2}]
|
||||
variables: Dict[Text, Any] = {}
|
||||
for var_item in raw_variables:
|
||||
if not isinstance(var_item, Dict) or len(var_item) != 1:
|
||||
raise exceptions.TestCaseFormatError(
|
||||
f"Invalid variables format: {raw_variables}"
|
||||
)
|
||||
|
||||
variables.update(var_item)
|
||||
|
||||
return variables
|
||||
|
||||
elif isinstance(raw_variables, Text):
|
||||
# get variables by function, e.g. ${get_variables()}
|
||||
project_meta = load_project_meta(test_path)
|
||||
variables = parse_data(raw_variables, {}, project_meta.functions)
|
||||
|
||||
return variables
|
||||
|
||||
else:
|
||||
raise exceptions.TestCaseFormatError(
|
||||
f"Invalid variables format: {raw_variables}"
|
||||
)
|
||||
|
||||
|
||||
def convert_jmespath(raw: Text) -> Text:
|
||||
# content.xx/json.xx => body.xx
|
||||
if raw.startswith("content"):
|
||||
|
||||
@@ -6,7 +6,6 @@ from urllib.parse import unquote
|
||||
|
||||
import yaml
|
||||
from loguru import logger
|
||||
from sentry_sdk import capture_exception
|
||||
|
||||
|
||||
def load_har_log_entries(file_path):
|
||||
@@ -33,9 +32,11 @@ def load_har_log_entries(file_path):
|
||||
try:
|
||||
content_json = json.loads(f.read())
|
||||
return content_json["log"]["entries"]
|
||||
except (KeyError, TypeError, JSONDecodeError) as ex:
|
||||
capture_exception(ex)
|
||||
logger.error("HAR file content error: {}".format(file_path))
|
||||
except (TypeError, JSONDecodeError) as ex:
|
||||
logger.error(f"failed to load HAR file {file_path}: {ex}")
|
||||
sys.exit(1)
|
||||
except KeyError:
|
||||
logger.error(f"log entries not found in HAR file: {content_json}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -53,7 +54,7 @@ def x_www_form_urlencoded(post_data):
|
||||
"""
|
||||
if isinstance(post_data, dict):
|
||||
return "&".join(
|
||||
[u"{}={}".format(key, value) for key, value in post_data.items()]
|
||||
["{}={}".format(key, value) for key, value in post_data.items()]
|
||||
)
|
||||
else:
|
||||
return post_data
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from shutil import copyfile
|
||||
from typing import Text, List, Tuple, Dict, Set, NoReturn
|
||||
|
||||
@@ -8,7 +9,11 @@ from loguru import logger
|
||||
from sentry_sdk import capture_exception
|
||||
|
||||
from httprunner import exceptions, __version__
|
||||
from httprunner.compat import ensure_testcase_v3_api, ensure_testcase_v3
|
||||
from httprunner.compat import (
|
||||
ensure_testcase_v3_api,
|
||||
ensure_testcase_v3,
|
||||
convert_variables,
|
||||
)
|
||||
from httprunner.loader import (
|
||||
load_folder_files,
|
||||
load_test_file,
|
||||
@@ -284,15 +289,9 @@ def make_testcase(testcase: Dict, dir_path: Text = None) -> Text:
|
||||
|
||||
config = testcase["config"]
|
||||
config["path"] = __ensure_cwd_relative(testcase_python_path)
|
||||
|
||||
# parse config variables
|
||||
config.setdefault("variables", {})
|
||||
if isinstance(config["variables"], Text):
|
||||
# get variables by function, e.g. ${get_variables()}
|
||||
project_meta = load_project_meta(testcase_abs_path)
|
||||
config["variables"] = parse_data(
|
||||
config["variables"], {}, project_meta.functions
|
||||
)
|
||||
config["variables"] = convert_variables(
|
||||
config.get("variables", {}), testcase_abs_path
|
||||
)
|
||||
|
||||
# prepare reference testcase
|
||||
imports_list = []
|
||||
@@ -356,14 +355,9 @@ def make_testsuite(testsuite: Dict) -> NoReturn:
|
||||
|
||||
testsuite_config = testsuite["config"]
|
||||
testsuite_path = testsuite_config["path"]
|
||||
|
||||
testsuite_variables = testsuite_config.get("variables", {})
|
||||
if isinstance(testsuite_variables, Text):
|
||||
# get variables by function, e.g. ${get_variables()}
|
||||
project_meta = load_project_meta(testsuite_path)
|
||||
testsuite_variables = parse_data(
|
||||
testsuite_variables, {}, project_meta.functions
|
||||
)
|
||||
testsuite_variables = convert_variables(
|
||||
testsuite_config.get("variables", {}), testsuite_path
|
||||
)
|
||||
|
||||
logger.info(f"start to make testsuite: {testsuite_path}")
|
||||
|
||||
@@ -391,9 +385,11 @@ def make_testsuite(testsuite: Dict) -> NoReturn:
|
||||
if "verify" in testsuite_config:
|
||||
testcase_dict["config"]["verify"] = testsuite_config["verify"]
|
||||
# override variables
|
||||
testcase_dict["config"].setdefault("variables", {})
|
||||
testcase_dict["config"]["variables"].update(testcase.get("variables", {}))
|
||||
testcase_dict["config"]["variables"].update(testsuite_variables)
|
||||
testcase_variables = convert_variables(
|
||||
testcase.get("variables", {}), testcase_path
|
||||
)
|
||||
testcase_variables.update(testsuite_variables)
|
||||
testcase_dict["config"]["variables"] = testcase_variables
|
||||
|
||||
# make testcase
|
||||
testcase_pytest_path = make_testcase(testcase_dict, testsuite_dir)
|
||||
@@ -428,12 +424,19 @@ def __make(tests_path: Text) -> NoReturn:
|
||||
logger.warning(ex)
|
||||
continue
|
||||
|
||||
if not isinstance(test_content, Dict):
|
||||
raise exceptions.FileFormatError(
|
||||
f"test content not in dict format: {test_content}"
|
||||
)
|
||||
|
||||
# api in v2 format, convert to v3 testcase
|
||||
if "request" in test_content:
|
||||
if "request" in test_content and "name" in test_content:
|
||||
test_content = ensure_testcase_v3_api(test_content)
|
||||
|
||||
if not (isinstance(test_content, Dict) and "config" in test_content):
|
||||
raise exceptions.FileFormatError("Invalid testcase/testsuite v2/v3 format!")
|
||||
if "config" not in test_content:
|
||||
raise exceptions.FileFormatError(
|
||||
f"miss config part in testcase/testsuite: {test_content}"
|
||||
)
|
||||
|
||||
test_content.setdefault("config", {})["path"] = test_file
|
||||
|
||||
@@ -465,7 +468,12 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
|
||||
if not os.path.isabs(tests_path):
|
||||
tests_path = os.path.join(os.getcwd(), tests_path)
|
||||
|
||||
__make(tests_path)
|
||||
try:
|
||||
__make(tests_path)
|
||||
except exceptions.MyBaseError as ex:
|
||||
logger.error(ex)
|
||||
sys.exit(1)
|
||||
|
||||
__ensure_project_meta_files(tests_path)
|
||||
|
||||
# format pytest files
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from httprunner import compat
|
||||
from httprunner import compat, exceptions
|
||||
from httprunner.compat import convert_variables
|
||||
|
||||
|
||||
class TestCompat(unittest.TestCase):
|
||||
def test_convert_variables(self):
|
||||
raw_variables = [{"var1": 1}, {"var2": "val2"}]
|
||||
self.assertEqual(
|
||||
convert_variables(raw_variables, "tests/data/a-b.c/1.yml"),
|
||||
{"var1": 1, "var2": "val2"},
|
||||
)
|
||||
raw_variables = {"var1": 1, "var2": "val2"}
|
||||
self.assertEqual(
|
||||
convert_variables(raw_variables, "tests/data/a-b.c/1.yml"),
|
||||
{"var1": 1, "var2": "val2"},
|
||||
)
|
||||
raw_variables = "${get_variables()}"
|
||||
self.assertEqual(
|
||||
convert_variables(raw_variables, "tests/data/a-b.c/1.yml"),
|
||||
{"foo1": "session_bar1"},
|
||||
)
|
||||
|
||||
with self.assertRaises(exceptions.TestCaseFormatError):
|
||||
raw_variables = [{"var1": 1}, {"var2": "val2", "var3": 3}]
|
||||
convert_variables(raw_variables, "tests/data/a-b.c/1.yml")
|
||||
with self.assertRaises(exceptions.TestCaseFormatError):
|
||||
convert_variables(None, "tests/data/a-b.c/1.yml")
|
||||
|
||||
def test_convert_jmespath(self):
|
||||
|
||||
self.assertEqual(compat.convert_jmespath("content.abc"), "body.abc")
|
||||
|
||||
Reference in New Issue
Block a user