mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-12 16:01:27 +08:00
fix #343: locate debugtalk.py and use as project working directory
This commit is contained in:
@@ -36,22 +36,6 @@ class HttpRunner(object):
|
|||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.http_client_session = self.kwargs.pop("http_client_session", None)
|
self.http_client_session = self.kwargs.pop("http_client_session", None)
|
||||||
|
|
||||||
self.__loader()
|
|
||||||
|
|
||||||
def __loader(self):
|
|
||||||
""" load project dependent files, including api/testcase definitions,
|
|
||||||
environment variables and builtin module.
|
|
||||||
|
|
||||||
"""
|
|
||||||
loader.reset_loader()
|
|
||||||
|
|
||||||
# load api/testcase definition and debugtalk.py module
|
|
||||||
project_folder_path = os.path.join(os.getcwd(), "tests") # TODO: remove tests
|
|
||||||
loader.load_project_tests(project_folder_path)
|
|
||||||
|
|
||||||
self.project_mapping = loader.project_mapping
|
|
||||||
utils.set_os_environ(self.project_mapping["env"])
|
|
||||||
|
|
||||||
def load_tests(self, path_or_testcases):
|
def load_tests(self, path_or_testcases):
|
||||||
""" load testcases, extend and merge with api/testcase definitions.
|
""" load testcases, extend and merge with api/testcase definitions.
|
||||||
|
|
||||||
@@ -94,14 +78,14 @@ class HttpRunner(object):
|
|||||||
if isinstance(path_or_testcases, list):
|
if isinstance(path_or_testcases, list):
|
||||||
for testcase in path_or_testcases:
|
for testcase in path_or_testcases:
|
||||||
try:
|
try:
|
||||||
dir_path = os.path.dirname(testcase["config"]["path"])
|
test_path = os.path.dirname(testcase["config"]["path"])
|
||||||
loader.load_debugtalk_module(dir_path)
|
loader.load_project_tests(test_path)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
dir_path = os.path.dirname(path_or_testcases["config"]["path"])
|
test_path = os.path.dirname(path_or_testcases["config"]["path"])
|
||||||
loader.load_debugtalk_module(dir_path)
|
loader.load_project_tests(test_path)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -109,6 +93,8 @@ class HttpRunner(object):
|
|||||||
else:
|
else:
|
||||||
testcases = loader.load_testcases(path_or_testcases)
|
testcases = loader.load_testcases(path_or_testcases)
|
||||||
|
|
||||||
|
self.project_mapping = loader.project_mapping
|
||||||
|
|
||||||
if not testcases:
|
if not testcases:
|
||||||
raise exceptions.TestcaseNotFound
|
raise exceptions.TestcaseNotFound
|
||||||
|
|
||||||
@@ -245,8 +231,9 @@ class HttpRunner(object):
|
|||||||
instance: HttpRunner() instance
|
instance: HttpRunner() instance
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# parser
|
# loader
|
||||||
testcases_list = self.load_tests(path_or_testcases)
|
testcases_list = self.load_tests(path_or_testcases)
|
||||||
|
# parser
|
||||||
parsed_testcases_list = self.parse_tests(testcases_list)
|
parsed_testcases_list = self.parse_tests(testcases_list)
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from httprunner import built_in, exceptions, logger, parser, validator
|
from httprunner import built_in, exceptions, logger, parser, utils, validator
|
||||||
from httprunner.compat import OrderedDict
|
from httprunner.compat import OrderedDict
|
||||||
|
|
||||||
project_mapping = {
|
project_mapping = {
|
||||||
@@ -192,6 +192,8 @@ def load_dot_env_file():
|
|||||||
env_variables_mapping[variable.strip()] = value.strip()
|
env_variables_mapping[variable.strip()] = value.strip()
|
||||||
|
|
||||||
project_mapping["env"] = env_variables_mapping
|
project_mapping["env"] = env_variables_mapping
|
||||||
|
utils.set_os_environ(env_variables_mapping)
|
||||||
|
|
||||||
return env_variables_mapping
|
return env_variables_mapping
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +233,23 @@ def locate_file(start_path, file_name):
|
|||||||
return locate_file(os.path.dirname(start_dir_path), file_name)
|
return locate_file(os.path.dirname(start_dir_path), file_name)
|
||||||
|
|
||||||
|
|
||||||
|
def locate_pwd(start_path):
|
||||||
|
""" locate project working directory.
|
||||||
|
The folder contains debugtalk.py will be used as PWD.
|
||||||
|
If debugtalk.py is not found, use os.getcwd() as default PWD.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
start_path (str): start locating path, maybe testcase file path or directory path
|
||||||
|
|
||||||
|
"""
|
||||||
|
global project_working_directory
|
||||||
|
try:
|
||||||
|
debugtalk_path = locate_file(start_path, "debugtalk.py")
|
||||||
|
project_working_directory = os.path.dirname(debugtalk_path)
|
||||||
|
except exceptions.FileNotFound:
|
||||||
|
project_working_directory = os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
## debugtalk.py module loader
|
## debugtalk.py module loader
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -297,25 +316,18 @@ def load_builtin_module():
|
|||||||
project_mapping["debugtalk"] = built_in_module
|
project_mapping["debugtalk"] = built_in_module
|
||||||
|
|
||||||
|
|
||||||
def load_debugtalk_module(start_path=None):
|
def load_debugtalk_module():
|
||||||
""" load project debugtalk.py module and merge with builtin module.
|
""" load project debugtalk.py module and merge with builtin module.
|
||||||
|
debugtalk.py should be located in project working directory.
|
||||||
Args:
|
variables and functions mapping for debugtalk.py
|
||||||
start_path (str, optional): start locating path, maybe file path or directory path.
|
|
||||||
Defaults to current working directory.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: variables and functions mapping for debugtalk.py
|
|
||||||
{
|
{
|
||||||
"variables": {},
|
"variables": {},
|
||||||
"functions": {}
|
"functions": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
start_path = start_path or os.getcwd()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
module_path = locate_file(start_path, "debugtalk.py")
|
module_path = locate_file(project_working_directory, "debugtalk.py")
|
||||||
module_name = convert_module_name(module_path)
|
module_name = convert_module_name(module_path)
|
||||||
except exceptions.FileNotFound:
|
except exceptions.FileNotFound:
|
||||||
return
|
return
|
||||||
@@ -734,7 +746,7 @@ def load_folder_content(folder_path):
|
|||||||
return items_mapping
|
return items_mapping
|
||||||
|
|
||||||
|
|
||||||
def load_api_folder(api_folder_path=None):
|
def load_api_folder(api_folder_path):
|
||||||
""" load api definitions from api folder.
|
""" load api definitions from api folder.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -775,7 +787,6 @@ def load_api_folder(api_folder_path=None):
|
|||||||
"""
|
"""
|
||||||
api_definition_mapping = {}
|
api_definition_mapping = {}
|
||||||
|
|
||||||
api_folder_path = api_folder_path or os.path.join(os.getcwd(), "api")
|
|
||||||
api_items_mapping = load_folder_content(api_folder_path)
|
api_items_mapping = load_folder_content(api_folder_path)
|
||||||
|
|
||||||
for api_file_path, api_items in api_items_mapping.items():
|
for api_file_path, api_items in api_items_mapping.items():
|
||||||
@@ -797,7 +808,7 @@ def load_api_folder(api_folder_path=None):
|
|||||||
return api_definition_mapping
|
return api_definition_mapping
|
||||||
|
|
||||||
|
|
||||||
def load_test_folder(test_folder_path=None):
|
def load_test_folder(test_folder_path):
|
||||||
""" load testcases definitions from folder.
|
""" load testcases definitions from folder.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -839,8 +850,6 @@ def load_test_folder(test_folder_path=None):
|
|||||||
"""
|
"""
|
||||||
test_definition_mapping = {}
|
test_definition_mapping = {}
|
||||||
|
|
||||||
# TODO: replace suite with testcases
|
|
||||||
test_folder_path = test_folder_path or os.path.join(os.getcwd(), "suite")
|
|
||||||
test_items_mapping = load_folder_content(test_folder_path)
|
test_items_mapping = load_folder_content(test_folder_path)
|
||||||
|
|
||||||
for test_file_path, items in test_items_mapping.items():
|
for test_file_path, items in test_items_mapping.items():
|
||||||
@@ -882,6 +891,9 @@ def load_test_folder(test_folder_path=None):
|
|||||||
def reset_loader():
|
def reset_loader():
|
||||||
""" reset project mapping.
|
""" reset project mapping.
|
||||||
"""
|
"""
|
||||||
|
global project_working_directory
|
||||||
|
project_working_directory = os.getcwd()
|
||||||
|
|
||||||
project_mapping["debugtalk"] = {
|
project_mapping["debugtalk"] = {
|
||||||
"variables": {},
|
"variables": {},
|
||||||
"functions": {}
|
"functions": {}
|
||||||
@@ -892,18 +904,22 @@ def reset_loader():
|
|||||||
testcases_cache_mapping.clear()
|
testcases_cache_mapping.clear()
|
||||||
|
|
||||||
|
|
||||||
def load_project_tests(folder_path):
|
def load_project_tests(test_path):
|
||||||
""" load api, testcases and builtin module.
|
""" load api, testcases, .env, builtin module and debugtalk.py.
|
||||||
|
api/testcases folder is relative to project_working_directory
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
folder_path (str): folder path.
|
test_path (str): test file/folder path, locate pwd from this path.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
reset_loader()
|
||||||
|
locate_pwd(test_path)
|
||||||
load_builtin_module()
|
load_builtin_module()
|
||||||
load_api_folder(os.path.join(folder_path, "api"))
|
load_api_folder(os.path.join(project_working_directory, "api"))
|
||||||
load_test_folder(os.path.join(folder_path, "suite"))
|
load_test_folder(os.path.join(project_working_directory, "suite"))
|
||||||
# load .env
|
# load .env
|
||||||
load_dot_env_file()
|
load_dot_env_file()
|
||||||
|
load_debugtalk_module()
|
||||||
|
|
||||||
|
|
||||||
def load_testcases(path):
|
def load_testcases(path):
|
||||||
@@ -942,14 +958,13 @@ def load_testcases(path):
|
|||||||
return testcases_cache_mapping[path]
|
return testcases_cache_mapping[path]
|
||||||
|
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
load_debugtalk_module(path)
|
load_project_tests(path)
|
||||||
files_list = load_folder_files(path)
|
files_list = load_folder_files(path)
|
||||||
testcases_list = load_testcases(files_list)
|
testcases_list = load_testcases(files_list)
|
||||||
|
|
||||||
elif os.path.isfile(path):
|
elif os.path.isfile(path):
|
||||||
try:
|
try:
|
||||||
dir_path = os.path.dirname(path)
|
load_project_tests(path)
|
||||||
load_debugtalk_module(dir_path)
|
|
||||||
testcase = _load_test_file(path)
|
testcase = _load_test_file(path)
|
||||||
if testcase["teststeps"]:
|
if testcase["teststeps"]:
|
||||||
testcases_list = [testcase]
|
testcases_list = [testcase]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from base64 import b64encode
|
|||||||
from collections import Iterable
|
from collections import Iterable
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from httprunner import logger
|
from httprunner import loader, logger
|
||||||
from httprunner.__about__ import __version__
|
from httprunner.__about__ import __version__
|
||||||
from httprunner.compat import basestring, bytes, json, numeric_types
|
from httprunner.compat import basestring, bytes, json, numeric_types
|
||||||
from jinja2 import Template, escape
|
from jinja2 import Template, escape
|
||||||
@@ -95,7 +95,7 @@ def render_html_report(summary, html_report_name=None, html_report_template=None
|
|||||||
logger.log_info("Start to render Html report ...")
|
logger.log_info("Start to render Html report ...")
|
||||||
logger.log_debug("render data: {}".format(summary))
|
logger.log_debug("render data: {}".format(summary))
|
||||||
|
|
||||||
report_dir_path = os.path.join(os.getcwd(), "reports")
|
report_dir_path = os.path.join(loader.project_working_directory, "reports")
|
||||||
start_at_timestamp = int(summary["time"]["start_at"])
|
start_at_timestamp = int(summary["time"]["start_at"])
|
||||||
summary["time"]["start_datetime"] = datetime.fromtimestamp(start_at_timestamp).strftime('%Y-%m-%d %H:%M:%S')
|
summary["time"]["start_datetime"] = datetime.fromtimestamp(start_at_timestamp).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
if html_report_name:
|
if html_report_name:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from httprunner import HttpRunner, LocustRunner
|
from httprunner import HttpRunner, LocustRunner, loader
|
||||||
from locust import HttpLocust
|
from locust import HttpLocust
|
||||||
from tests.api_server import HTTPBIN_SERVER
|
from tests.api_server import HTTPBIN_SERVER
|
||||||
from tests.base import ApiServerUnittest
|
from tests.base import ApiServerUnittest
|
||||||
@@ -89,7 +89,7 @@ class TestHttpRunner(ApiServerUnittest):
|
|||||||
self.assertEqual(summary["stat"]["skipped"], 4)
|
self.assertEqual(summary["stat"]["skipped"], 4)
|
||||||
|
|
||||||
runner.gen_html_report(html_report_name=output_folder_name)
|
runner.gen_html_report(html_report_name=output_folder_name)
|
||||||
report_save_dir = os.path.join(os.getcwd(), 'reports', output_folder_name)
|
report_save_dir = os.path.join(loader.project_working_directory, 'reports', output_folder_name)
|
||||||
self.assertGreater(len(os.listdir(report_save_dir)), 0)
|
self.assertGreater(len(os.listdir(report_save_dir)), 0)
|
||||||
shutil.rmtree(report_save_dir)
|
shutil.rmtree(report_save_dir)
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ class TestHttpRunner(ApiServerUnittest):
|
|||||||
output_folder_name = os.path.basename(os.path.splitext(testset_path)[0])
|
output_folder_name = os.path.basename(os.path.splitext(testset_path)[0])
|
||||||
report = runner.gen_html_report(html_report_name=output_folder_name)
|
report = runner.gen_html_report(html_report_name=output_folder_name)
|
||||||
self.assertTrue(os.path.isfile(report))
|
self.assertTrue(os.path.isfile(report))
|
||||||
report_save_dir = os.path.join(os.getcwd(), 'reports', output_folder_name)
|
report_save_dir = os.path.join(loader.project_working_directory, 'reports', output_folder_name)
|
||||||
shutil.rmtree(report_save_dir)
|
shutil.rmtree(report_save_dir)
|
||||||
|
|
||||||
def test_testcase_layer(self):
|
def test_testcase_layer(self):
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ from tests.base import ApiServerUnittest
|
|||||||
class TestContext(ApiServerUnittest):
|
class TestContext(ApiServerUnittest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
project_dir = os.path.join(os.getcwd(), "tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
|
||||||
loader.load_project_tests(project_dir)
|
|
||||||
loader.load_debugtalk_module(project_dir)
|
|
||||||
self.debugtalk_module = loader.project_mapping["debugtalk"]
|
self.debugtalk_module = loader.project_mapping["debugtalk"]
|
||||||
|
|
||||||
self.context = context.Context(
|
self.context = context.Context(
|
||||||
|
|||||||
@@ -185,15 +185,13 @@ class TestModuleLoader(unittest.TestCase):
|
|||||||
self.assertNotIn("is_py3", functions_dict)
|
self.assertNotIn("is_py3", functions_dict)
|
||||||
|
|
||||||
def test_load_debugtalk_module(self):
|
def test_load_debugtalk_module(self):
|
||||||
project_dir = os.path.join(os.getcwd(), "tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "httprunner"))
|
||||||
loader.load_project_tests(project_dir)
|
|
||||||
loader.load_debugtalk_module()
|
|
||||||
imported_module_items = loader.project_mapping["debugtalk"]
|
imported_module_items = loader.project_mapping["debugtalk"]
|
||||||
self.assertIn("equals", imported_module_items["functions"])
|
self.assertIn("equals", imported_module_items["functions"])
|
||||||
self.assertNotIn("SECRET_KEY", imported_module_items["variables"])
|
self.assertNotIn("SECRET_KEY", imported_module_items["variables"])
|
||||||
self.assertNotIn("alter_response", imported_module_items["functions"])
|
self.assertNotIn("alter_response", imported_module_items["functions"])
|
||||||
|
|
||||||
loader.load_debugtalk_module("tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
|
||||||
imported_module_items = loader.project_mapping["debugtalk"]
|
imported_module_items = loader.project_mapping["debugtalk"]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
imported_module_items["variables"]["SECRET_KEY"],
|
imported_module_items["variables"]["SECRET_KEY"],
|
||||||
@@ -228,13 +226,22 @@ class TestModuleLoader(unittest.TestCase):
|
|||||||
with self.assertRaises(exceptions.VariableNotFound):
|
with self.assertRaises(exceptions.VariableNotFound):
|
||||||
loader.get_module_item(module_mapping, "variables", "SECRET_KEY2")
|
loader.get_module_item(module_mapping, "variables", "SECRET_KEY2")
|
||||||
|
|
||||||
|
def test_locate_pwd(self):
|
||||||
|
loader.locate_pwd("tests/data/demo_testcase.yml")
|
||||||
|
self.assertEqual(loader.project_working_directory, "tests")
|
||||||
|
|
||||||
|
loader.locate_pwd("tests/base.py")
|
||||||
|
self.assertEqual(loader.project_working_directory, "tests")
|
||||||
|
|
||||||
|
loader.locate_pwd("httprunner/__init__.py")
|
||||||
|
self.assertEqual(loader.project_working_directory, os.getcwd())
|
||||||
|
|
||||||
|
|
||||||
class TestSuiteLoader(unittest.TestCase):
|
class TestSuiteLoader(unittest.TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
project_dir = os.path.join(os.getcwd(), "tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
|
||||||
loader.load_project_tests(project_dir)
|
|
||||||
|
|
||||||
def test_load_test_file_testcase(self):
|
def test_load_test_file_testcase(self):
|
||||||
testcase = loader._load_test_file("tests/testcases/smoketest.yml")
|
testcase = loader._load_test_file("tests/testcases/smoketest.yml")
|
||||||
@@ -483,9 +490,7 @@ class TestSuiteLoader(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_load_project_tests(self):
|
def test_load_project_tests(self):
|
||||||
loader.project_working_directory = os.path.join(os.getcwd(), "tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
|
||||||
loader.load_project_tests(loader.project_working_directory)
|
|
||||||
loader.load_debugtalk_module(loader.project_working_directory)
|
|
||||||
project_mapping = loader.project_mapping
|
project_mapping = loader.project_mapping
|
||||||
self.assertEqual(project_mapping["debugtalk"]["variables"]["SECRET_KEY"], "DebugTalk")
|
self.assertEqual(project_mapping["debugtalk"]["variables"]["SECRET_KEY"], "DebugTalk")
|
||||||
self.assertIn("get_token", project_mapping["def-api"])
|
self.assertIn("get_token", project_mapping["def-api"])
|
||||||
|
|||||||
@@ -412,8 +412,7 @@ class TestParser(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_parse_parameters_mix(self):
|
def test_parse_parameters_mix(self):
|
||||||
project_dir = os.path.join(os.getcwd(), "tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
|
||||||
loader.load_debugtalk_module(project_dir)
|
|
||||||
project_mapping = loader.project_mapping
|
project_mapping = loader.project_mapping
|
||||||
|
|
||||||
parameters = [
|
parameters = [
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ from tests.base import ApiServerUnittest
|
|||||||
class TestRunner(ApiServerUnittest):
|
class TestRunner(ApiServerUnittest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
project_dir = os.path.join(os.getcwd(), "tests")
|
loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
|
||||||
loader.load_project_tests(project_dir)
|
|
||||||
loader.load_debugtalk_module(project_dir)
|
|
||||||
self.debugtalk_module = loader.project_mapping["debugtalk"]
|
self.debugtalk_module = loader.project_mapping["debugtalk"]
|
||||||
config_dict = {
|
config_dict = {
|
||||||
"variables": self.debugtalk_module["variables"],
|
"variables": self.debugtalk_module["variables"],
|
||||||
|
|||||||
Reference in New Issue
Block a user