mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-09 06:23:52 +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):
|
class TestCaseRequestWithFunctions(HttpRunner):
|
||||||
config = (
|
config = (
|
||||||
Config("request with functions")
|
Config("request with functions")
|
||||||
.variables(**{"foo1": "session_bar1", "var1": "testsuite_val1"})
|
.variables(**{"var1": "testsuite_val1", "foo1": "session_bar1"})
|
||||||
.base_url("https://postman-echo.com")
|
.base_url("https://postman-echo.com")
|
||||||
.verify(False)
|
.verify(False)
|
||||||
.export(*["session_foo2"])
|
.export(*["session_foo2"])
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from examples.postman_echo.request_methods.request_with_functions_test import (
|
|||||||
class TestCaseRequestWithTestcaseReference(HttpRunner):
|
class TestCaseRequestWithTestcaseReference(HttpRunner):
|
||||||
config = (
|
config = (
|
||||||
Config("request with referenced testcase")
|
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")
|
.base_url("https://postman-echo.com")
|
||||||
.verify(False)
|
.verify(False)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,15 +3,49 @@ This module handles compatibility issues between testcase format v2 and v3.
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from typing import List, Dict, Text, Union
|
from typing import List, Dict, Text, Union, Any
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from httprunner import exceptions
|
from httprunner import exceptions
|
||||||
from httprunner.loader import load_project_meta
|
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
|
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:
|
def convert_jmespath(raw: Text) -> Text:
|
||||||
# content.xx/json.xx => body.xx
|
# content.xx/json.xx => body.xx
|
||||||
if raw.startswith("content"):
|
if raw.startswith("content"):
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from urllib.parse import unquote
|
|||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from sentry_sdk import capture_exception
|
|
||||||
|
|
||||||
|
|
||||||
def load_har_log_entries(file_path):
|
def load_har_log_entries(file_path):
|
||||||
@@ -33,9 +32,11 @@ def load_har_log_entries(file_path):
|
|||||||
try:
|
try:
|
||||||
content_json = json.loads(f.read())
|
content_json = json.loads(f.read())
|
||||||
return content_json["log"]["entries"]
|
return content_json["log"]["entries"]
|
||||||
except (KeyError, TypeError, JSONDecodeError) as ex:
|
except (TypeError, JSONDecodeError) as ex:
|
||||||
capture_exception(ex)
|
logger.error(f"failed to load HAR file {file_path}: {ex}")
|
||||||
logger.error("HAR file content error: {}".format(file_path))
|
sys.exit(1)
|
||||||
|
except KeyError:
|
||||||
|
logger.error(f"log entries not found in HAR file: {content_json}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ def x_www_form_urlencoded(post_data):
|
|||||||
"""
|
"""
|
||||||
if isinstance(post_data, dict):
|
if isinstance(post_data, dict):
|
||||||
return "&".join(
|
return "&".join(
|
||||||
[u"{}={}".format(key, value) for key, value in post_data.items()]
|
["{}={}".format(key, value) for key, value in post_data.items()]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return post_data
|
return post_data
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from typing import Text, List, Tuple, Dict, Set, NoReturn
|
from typing import Text, List, Tuple, Dict, Set, NoReturn
|
||||||
|
|
||||||
@@ -8,7 +9,11 @@ from loguru import logger
|
|||||||
from sentry_sdk import capture_exception
|
from sentry_sdk import capture_exception
|
||||||
|
|
||||||
from httprunner import exceptions, __version__
|
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 (
|
from httprunner.loader import (
|
||||||
load_folder_files,
|
load_folder_files,
|
||||||
load_test_file,
|
load_test_file,
|
||||||
@@ -284,15 +289,9 @@ def make_testcase(testcase: Dict, dir_path: Text = None) -> Text:
|
|||||||
|
|
||||||
config = testcase["config"]
|
config = testcase["config"]
|
||||||
config["path"] = __ensure_cwd_relative(testcase_python_path)
|
config["path"] = __ensure_cwd_relative(testcase_python_path)
|
||||||
|
config["variables"] = convert_variables(
|
||||||
# parse config variables
|
config.get("variables", {}), testcase_abs_path
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
# prepare reference testcase
|
# prepare reference testcase
|
||||||
imports_list = []
|
imports_list = []
|
||||||
@@ -356,14 +355,9 @@ def make_testsuite(testsuite: Dict) -> NoReturn:
|
|||||||
|
|
||||||
testsuite_config = testsuite["config"]
|
testsuite_config = testsuite["config"]
|
||||||
testsuite_path = testsuite_config["path"]
|
testsuite_path = testsuite_config["path"]
|
||||||
|
testsuite_variables = convert_variables(
|
||||||
testsuite_variables = testsuite_config.get("variables", {})
|
testsuite_config.get("variables", {}), testsuite_path
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(f"start to make testsuite: {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:
|
if "verify" in testsuite_config:
|
||||||
testcase_dict["config"]["verify"] = testsuite_config["verify"]
|
testcase_dict["config"]["verify"] = testsuite_config["verify"]
|
||||||
# override variables
|
# override variables
|
||||||
testcase_dict["config"].setdefault("variables", {})
|
testcase_variables = convert_variables(
|
||||||
testcase_dict["config"]["variables"].update(testcase.get("variables", {}))
|
testcase.get("variables", {}), testcase_path
|
||||||
testcase_dict["config"]["variables"].update(testsuite_variables)
|
)
|
||||||
|
testcase_variables.update(testsuite_variables)
|
||||||
|
testcase_dict["config"]["variables"] = testcase_variables
|
||||||
|
|
||||||
# make testcase
|
# make testcase
|
||||||
testcase_pytest_path = make_testcase(testcase_dict, testsuite_dir)
|
testcase_pytest_path = make_testcase(testcase_dict, testsuite_dir)
|
||||||
@@ -428,12 +424,19 @@ def __make(tests_path: Text) -> NoReturn:
|
|||||||
logger.warning(ex)
|
logger.warning(ex)
|
||||||
continue
|
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
|
# 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)
|
test_content = ensure_testcase_v3_api(test_content)
|
||||||
|
|
||||||
if not (isinstance(test_content, Dict) and "config" in test_content):
|
if "config" not in test_content:
|
||||||
raise exceptions.FileFormatError("Invalid testcase/testsuite v2/v3 format!")
|
raise exceptions.FileFormatError(
|
||||||
|
f"miss config part in testcase/testsuite: {test_content}"
|
||||||
|
)
|
||||||
|
|
||||||
test_content.setdefault("config", {})["path"] = test_file
|
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):
|
if not os.path.isabs(tests_path):
|
||||||
tests_path = os.path.join(os.getcwd(), 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)
|
__ensure_project_meta_files(tests_path)
|
||||||
|
|
||||||
# format pytest files
|
# format pytest files
|
||||||
|
|||||||
@@ -1,10 +1,34 @@
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from httprunner import compat
|
from httprunner import compat, exceptions
|
||||||
|
from httprunner.compat import convert_variables
|
||||||
|
|
||||||
|
|
||||||
class TestCompat(unittest.TestCase):
|
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):
|
def test_convert_jmespath(self):
|
||||||
|
|
||||||
self.assertEqual(compat.convert_jmespath("content.abc"), "body.abc")
|
self.assertEqual(compat.convert_jmespath("content.abc"), "body.abc")
|
||||||
|
|||||||
Reference in New Issue
Block a user