refactor lib function interface

This commit is contained in:
debugtalk
2018-04-17 16:37:41 +08:00
parent 9d3c5c5ef7
commit b6450afd0b
6 changed files with 137 additions and 139 deletions

View File

@@ -1,7 +1,7 @@
__title__ = 'HttpRunner'
__description__ = 'One-stop solution for HTTP(S) testing.'
__url__ = 'https://github.com/HttpRunner/HttpRunner'
__version__ = '1.3.8.beta.3'
__version__ = '1.3.9'
__author__ = 'debugtalk'
__author_email__ = 'mail@debugtalk.com'
__license__ = 'MIT'

View File

@@ -26,6 +26,9 @@ def main_hrun():
parser.add_argument(
'testset_paths', nargs='*',
help="testset file path")
parser.add_argument(
'--no-html-report', action='store_true', default=False,
help="do not generate html report.")
parser.add_argument(
'--html-report-name',
help="specify html report name, only effective when generating html report.")
@@ -78,13 +81,17 @@ def main_hrun():
create_scaffold(project_path)
exit(0)
result = HttpRunner(args.testset_paths, failfast=args.failfast).run(
html_report_name=args.html_report_name,
html_report_template=args.html_report_template
)
runner = HttpRunner(failfast=args.failfast).run(args.testset_paths)
print_output(result["output"])
return 0 if result["success"] else 1
if not args.no_html_report:
runner.gen_html_report(
html_report_name=args.html_report_name,
html_report_template=args.html_report_template
)
summary = runner.summary
print_output(summary["output"])
return 0 if summary["success"] else 1
def main_locust():
""" Performance test with locust: parse command line options and run commands.

View File

@@ -53,9 +53,56 @@ def get_summary(result):
'duration': result.duration
}
summary["records"] = result.records
else:
summary["records"] = []
return summary
def render_html_report(summary, html_report_name=None, html_report_template=None):
""" render html report with specified report name and template
if html_report_name is not specified, use current datetime
if html_report_template is not specified, use default report template
"""
if not html_report_template:
html_report_template = os.path.join(
os.path.abspath(os.path.dirname(__file__)),
"templates",
"default_report_template.html"
)
logger.log_debug("No html report template specified, use default.")
else:
logger.log_info("render with html report template: {}".format(html_report_template))
logger.log_info("Start to render Html report ...")
logger.log_debug("render data: {}".format(summary))
report_dir_path = os.path.join(os.getcwd(), "reports")
start_datetime = summary["time"]["start_at"].strftime('%Y-%m-%d-%H-%M-%S')
if html_report_name:
summary["html_report_name"] = html_report_name
report_dir_path = os.path.join(report_dir_path, html_report_name)
html_report_name += "-{}.html".format(start_datetime)
else:
summary["html_report_name"] = ""
html_report_name = "{}.html".format(start_datetime)
if not os.path.isdir(report_dir_path):
os.makedirs(report_dir_path)
for record in summary.get("records"):
record["meta_data"] = make_json_serializable(record["meta_data"])
with io.open(html_report_template, "r", encoding='utf-8') as fp_r:
template_content = fp_r.read()
report_path = os.path.join(report_dir_path, html_report_name)
with io.open(report_path, 'w', encoding='utf-8') as fp_w:
rendered_content = Template(template_content).render(summary)
fp_w.write(rendered_content)
logger.log_info("Generated Html report: {}".format(report_path))
return report_path
def make_json_serializable(raw_json):
serializable_json = {}
for key, value in raw_json.items():
@@ -86,12 +133,6 @@ class HtmlTestResult(unittest.TextTestResult):
def __init__(self, stream, descriptions, verbosity):
super(HtmlTestResult, self).__init__(stream, descriptions, verbosity)
self.records = []
self.default_report_template_path = os.path.join(
os.path.abspath(os.path.dirname(__file__)),
"templates",
"default_report_template.html"
)
self.report_path = None
def _record_test(self, test, status, attachment=''):
self.records.append({
@@ -99,7 +140,7 @@ class HtmlTestResult(unittest.TextTestResult):
'status': status,
'response_time_ms': test.meta_data.get("response_time(ms)", 0),
'attachment': attachment,
"meta_data": make_json_serializable(test.meta_data)
"meta_data": test.meta_data
})
def startTestRun(self):
@@ -143,46 +184,3 @@ class HtmlTestResult(unittest.TextTestResult):
@property
def duration(self):
return time.time() - self.start_at
@property
def summary(self):
return get_summary(self)
def render_html_report(self, html_report_name=None, html_report_template=None):
""" render html report with specified report name and template
if html_report_name is not specified, use current datetime
if html_report_template is not specified, use default report template
"""
if not html_report_template:
html_report_template = self.default_report_template_path
logger.log_debug("No html report template specified, use default.")
else:
logger.log_info("render with html report template: {}".format(html_report_template))
summary = self.summary
logger.log_info("Start to render Html report ...")
logger.log_debug("render data: {}".format(summary))
report_dir_path = os.path.join(os.getcwd(), "reports")
start_datetime = summary["time"]["start_at"].strftime('%Y-%m-%d-%H-%M-%S')
if html_report_name:
summary["html_report_name"] = html_report_name
report_dir_path = os.path.join(report_dir_path, html_report_name)
html_report_name += "-{}.html".format(start_datetime)
else:
summary["html_report_name"] = ""
html_report_name = "{}.html".format(start_datetime)
if not os.path.isdir(report_dir_path):
os.makedirs(report_dir_path)
with io.open(html_report_template, "r", encoding='utf-8') as fp_r:
template_content = fp_r.read()
report_path = os.path.join(report_dir_path, html_report_name)
with io.open(report_path, 'w', encoding='utf-8') as fp_w:
rendered_content = Template(template_content).render(summary)
fp_w.write(rendered_content)
logger.log_info("Generated Html report: {}".format(report_path))
return report_path

View File

@@ -6,7 +6,7 @@ import unittest
from httprunner import exception, logger, runner, testcase, utils
from httprunner.compat import is_py3
from httprunner.report import HtmlTestResult, get_summary
from httprunner.report import HtmlTestResult, get_summary, render_html_report
class TestCase(unittest.TestCase):
@@ -189,58 +189,51 @@ class TaskSuite(unittest.TestSuite):
class HttpRunner(object):
def __init__(self, path, gen_html_report=True, **kwargs):
""" initialize HttpRunner with specified testset file path and test runner
@param (str) path:
YAML/JSON testset file path
@param (boolean) gen_html_report:
True: use HtmlTestResult and generate html report
False: use TextTestResult and do not generate report file
@param (dict) kwargs:
key-value arguments used to initialize TextTestRunner
- failfast: False/True, stop the test run on the first error or failure.
def __init__(self, **kwargs):
""" initialize test runner
@param (dict) kwargs: key-value arguments used to initialize TextTestRunner
- resultclass: HtmlTestResult or TextTestResult
- failfast: False/True, stop the test run on the first error or failure.
"""
self.path = path
self.gen_html_report = gen_html_report
if self.gen_html_report:
kwargs["resultclass"] = HtmlTestResult
kwargs.setdefault("resultclass", HtmlTestResult)
self.runner = unittest.TextTestRunner(**kwargs)
def run(self, mapping=None, html_report_name=None, html_report_template=None):
""" start to run suite
def run(self, path, mapping=None):
""" start to run specified testset file with varaibles mapping
@param (str) path:
YAML/JSON testset file path
@param (dict) mapping:
if mapping specified, it will override variables in config block
@param (str) html_report_name:
output html report file name
@param (str) html_report_template:
report template file path, template should be in Jinja2 format
"""
try:
mapping = mapping or {}
task_suite = TaskSuite(self.path, mapping)
task_suite = TaskSuite(path, mapping)
except exception.TestcaseNotFound:
logger.log_error("Testcases not found in {}".format(self.path))
logger.log_error("Testcases not found in {}".format(path))
sys.exit(1)
result = self.runner.run(task_suite)
self.summary = get_summary(result)
output = []
for task in task_suite.tasks:
output.extend(task.output)
if self.gen_html_report:
summary = result.summary
summary["report_path"] = result.render_html_report(
html_report_name,
html_report_template
)
else:
summary = get_summary(result)
self.summary["output"] = output
return self
summary["output"] = output
return summary
def gen_html_report(self, html_report_name=None, html_report_template=None):
""" generate html report and return report path
@param (str) html_report_name:
output html report file name
@param (str) html_report_template:
report template file path, template should be in Jinja2 format
"""
return render_html_report(
self.summary,
html_report_name,
html_report_template
)
class LocustTask(object):

View File

@@ -17,30 +17,21 @@ class TestHttpRunner(ApiServerUnittest):
return self.api_client.get(url, headers=headers)
def test_text_run_times(self):
kwargs = {
"gen_html_report": False
}
result = HttpRunner(self.testset_path, **kwargs).run()
self.assertEqual(result["stat"]["testsRun"], 10)
runner = HttpRunner().run(self.testset_path)
self.assertEqual(runner.summary["stat"]["testsRun"], 10)
def test_text_skip(self):
kwargs = {
"gen_html_report": False
}
result = HttpRunner(self.testset_path, **kwargs).run()
self.assertEqual(result["stat"]["skipped"], 4)
runner = HttpRunner().run(self.testset_path)
self.assertEqual(runner.summary["stat"]["skipped"], 4)
def test_html_report(self):
kwargs = {
"gen_html_report": True
}
kwargs = {}
output_folder_name = os.path.basename(os.path.splitext(self.testset_path)[0])
run_kwargs = {
"html_report_name": output_folder_name
}
result = HttpRunner(self.testset_path).run(**run_kwargs)
self.assertEqual(result["stat"]["testsRun"], 10)
self.assertEqual(result["stat"]["skipped"], 4)
runner = HttpRunner().run(self.testset_path)
summary = runner.summary
self.assertEqual(summary["stat"]["testsRun"], 10)
self.assertEqual(summary["stat"]["skipped"], 4)
runner.gen_html_report(html_report_name=output_folder_name)
report_save_dir = os.path.join(os.getcwd(), 'reports', output_folder_name)
shutil.rmtree(report_save_dir)

View File

@@ -77,52 +77,59 @@ class TestRunner(ApiServerUnittest):
def test_run_testset_hardcode(self):
for testcase_file_path in self.testcase_file_path_list:
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
runner = HttpRunner().run(testcase_file_path)
self.assertTrue(runner.summary["success"])
def test_run_testsets_hardcode(self):
result = HttpRunner(self.testcase_file_path_list).run()
self.assertTrue(result["success"])
self.assertEqual(result["stat"]["testsRun"], 6)
self.assertEqual(result["stat"]["successes"], 6)
runner = HttpRunner().run(self.testcase_file_path_list)
summary = runner.summary
self.assertTrue(summary["success"])
self.assertEqual(summary["stat"]["testsRun"], 6)
self.assertEqual(summary["stat"]["successes"], 6)
def test_run_testset_template_variables(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_testset_variables.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
def test_run_testset_template_import_functions(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_testset_template_import_functions.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
def test_run_testsets_template_import_functions(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_testset_template_import_functions.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
def test_run_testsets_template_lambda_functions(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_testset_template_lambda_functions.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
def test_run_testset_layered(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_testset_layer.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
def test_run_testset_output(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_testset_layer.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
self.assertIn("token", result["output"][0]["out"])
self.assertEqual(len(result["output"]), 13)
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
self.assertIn("token", summary["output"][0]["out"])
self.assertEqual(len(summary["output"]), 13)
def test_run_testset_with_variables_mapping(self):
testcase_file_path = os.path.join(
@@ -130,10 +137,11 @@ class TestRunner(ApiServerUnittest):
variables_mapping = {
"app_version": '2.9.7'
}
result = HttpRunner(testcase_file_path).run(mapping=variables_mapping)
self.assertTrue(result["success"])
self.assertIn("token", result["output"][0]["out"])
self.assertEqual(len(result["output"]), 13)
runner = HttpRunner().run(testcase_file_path, mapping=variables_mapping)
summary = runner.summary
self.assertTrue(summary["success"])
self.assertIn("token", summary["output"][0]["out"])
self.assertEqual(len(summary["output"]), 13)
def test_run_testcase_with_empty_header(self):
testcase_file_path = os.path.join(
@@ -163,7 +171,8 @@ class TestRunner(ApiServerUnittest):
def test_run_testset_with_parameters(self):
testcase_file_path = os.path.join(
os.getcwd(), 'tests/data/demo_parameters.yml')
result = HttpRunner(testcase_file_path).run()
self.assertTrue(result["success"])
self.assertEqual(len(result["output"]), 3 * 2 * 2)
self.assertEqual(result["stat"]["testsRun"], 3 * 2 * 2)
runner = HttpRunner().run(testcase_file_path)
summary = runner.summary
self.assertTrue(summary["success"])
self.assertEqual(len(summary["output"]), 3 * 2 * 2)
self.assertEqual(summary["stat"]["testsRun"], 3 * 2 * 2)