mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
216 lines
6.4 KiB
Python
216 lines
6.4 KiB
Python
import io
|
|
import json
|
|
import os
|
|
import platform
|
|
|
|
import jsonschema
|
|
from loguru import logger
|
|
|
|
from httprunner import exceptions
|
|
|
|
schemas_root_dir = os.path.join(os.path.dirname(__file__), "schemas")
|
|
common_schema_path = os.path.join(schemas_root_dir, "common.schema.json")
|
|
api_schema_path = os.path.join(schemas_root_dir, "api.schema.json")
|
|
testcase_schema_v1_path = os.path.join(schemas_root_dir, "testcase.schema.v1.json")
|
|
testcase_schema_v2_path = os.path.join(schemas_root_dir, "testcase.schema.v2.json")
|
|
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:
|
|
api_schema = json.load(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("\\", "/") + '/'
|
|
else:
|
|
# Linux, Darwin
|
|
absolute_base_path = "file://" + os.path.abspath(schemas_root_dir) + "/"
|
|
|
|
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:
|
|
testcase_schema_v1 = json.load(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:
|
|
testsuite_schema_v1 = json.load(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
|
|
"""
|
|
try:
|
|
jsonschema.validate(content, scheme, resolver=resolver)
|
|
except jsonschema.exceptions.ValidationError as ex:
|
|
logger.error(str(ex))
|
|
raise exceptions.FileFormatError
|
|
|
|
return True
|
|
|
|
@staticmethod
|
|
def validate_api_format(content):
|
|
""" 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
|
|
"""
|
|
return JsonSchemaChecker.validate_format(content, testcase_schema_v1)
|
|
|
|
@staticmethod
|
|
def validate_testcase_v2_format(content):
|
|
""" 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
|
|
"""
|
|
return JsonSchemaChecker.validate_format(content, testsuite_schema_v1)
|
|
|
|
@staticmethod
|
|
def validate_testsuite_v2_format(content):
|
|
""" 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.
|
|
|
|
Args:
|
|
path (str/list/tuple): file path/directory or file path list.
|
|
|
|
Returns:
|
|
bool: True if path is valid file path or path list, otherwise False.
|
|
|
|
"""
|
|
if not isinstance(path, (str, list, tuple)):
|
|
return False
|
|
|
|
elif isinstance(path, (list, tuple)):
|
|
for p in path:
|
|
if not is_test_path(p):
|
|
return False
|
|
|
|
return True
|
|
|
|
else:
|
|
# path is string
|
|
if not os.path.exists(path):
|
|
return False
|
|
|
|
# path exists
|
|
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']:
|
|
# path is not json/yaml file
|
|
return False
|
|
else:
|
|
return True
|
|
elif os.path.isdir(path):
|
|
# path is a directory
|
|
return True
|
|
else:
|
|
# path is neither a folder nor a file, maybe a symbol link or something else
|
|
return False
|
|
|
|
|
|
def is_test_content(data_structure):
|
|
""" check if data_structure is apis/testcases/testsuites.
|
|
|
|
Args:
|
|
data_structure (dict): should include keys, apis or testcases or testsuites
|
|
|
|
Returns:
|
|
bool: True if data_structure is valid apis/testcases/testsuites, otherwise False.
|
|
|
|
"""
|
|
if not isinstance(data_structure, dict):
|
|
return False
|
|
|
|
if "apis" in data_structure:
|
|
# maybe a group of api content
|
|
apis = data_structure["apis"]
|
|
if not isinstance(apis, list):
|
|
return False
|
|
|
|
for item in apis:
|
|
is_testcase = False
|
|
try:
|
|
JsonSchemaChecker.validate_api_format(item)
|
|
is_testcase = True
|
|
except exceptions.FileFormatError:
|
|
pass
|
|
|
|
if not is_testcase:
|
|
return False
|
|
|
|
return True
|
|
|
|
elif "testcases" in data_structure:
|
|
# maybe a testsuite, containing a group of testcases
|
|
testcases = data_structure["testcases"]
|
|
if not isinstance(testcases, list):
|
|
return False
|
|
|
|
for item in testcases:
|
|
is_testcase = False
|
|
try:
|
|
JsonSchemaChecker.validate_testcase_v2_format(item)
|
|
is_testcase = True
|
|
except exceptions.FileFormatError:
|
|
pass
|
|
|
|
try:
|
|
JsonSchemaChecker.validate_testcase_v2_format(item)
|
|
is_testcase = True
|
|
except exceptions.FileFormatError:
|
|
pass
|
|
|
|
if not is_testcase:
|
|
return False
|
|
|
|
return True
|
|
|
|
elif "testsuites" in data_structure:
|
|
# maybe a group of testsuites
|
|
testsuites = data_structure["testsuites"]
|
|
if not isinstance(testsuites, list):
|
|
return False
|
|
|
|
for item in testsuites:
|
|
is_testcase = False
|
|
try:
|
|
JsonSchemaChecker.validate_testsuite_v1_format(item)
|
|
is_testcase = True
|
|
except exceptions.FileFormatError:
|
|
pass
|
|
|
|
try:
|
|
JsonSchemaChecker.validate_testsuite_v2_format(item)
|
|
is_testcase = True
|
|
except exceptions.FileFormatError:
|
|
pass
|
|
|
|
if not is_testcase:
|
|
return False
|
|
|
|
return True
|
|
|
|
else:
|
|
return False
|