def prettify_json_file(file_list): """ prettify JSON testcase format """ for json_file in set(file_list): if not json_file.endswith(".json"): logger.log_warning( "Only JSON file format can be prettified, skip: {}".format( json_file)) continue logger.color_print("Start to prettify JSON file: {}".format(json_file), "GREEN") dir_path = os.path.dirname(json_file) file_name, file_suffix = os.path.splitext(os.path.basename(json_file)) outfile = os.path.join(dir_path, "{}.pretty.json".format(file_name)) with io.open(json_file, 'r', encoding='utf-8') as stream: try: obj = json.load(stream) except ValueError as e: raise SystemExit(e) with io.open(outfile, 'w', encoding='utf-8') as out: json.dump(obj, out, indent=4, separators=(',', ': ')) out.write('\n') print("success: {}".format(outfile))
def load_file(file_path): if not os.path.isfile(file_path): raise exceptions.FileNotFound("{} does not exist.".format(file_path)) file_suffix = os.path.splitext(file_path)[1].lower() if file_suffix == '.json': return _load_json_file(file_path) elif file_suffix in ['.yaml', '.yml']: return _load_yaml_file(file_path) elif file_suffix == ".csv": return load_csv_file(file_path) else: # '' or other suffix err_msg = u"Unsupported file format: {}".format(file_path) logger.log_warning(err_msg) return []
def load_testcase(raw_testcase): """ load testcase with api/testcase references. Args: raw_testcase (list): raw testcase content loaded from JSON/YAML file: [ # config part { "config": { "name": "XXXX", "base_url": "https://debugtalk.com" } }, # teststeps part { "test": {...} }, { "test": {...} } ] Returns: dict: loaded testcase content { "config": {}, "teststeps": [test11, test12] } """ JsonSchemaChecker.validate_testcase_v1_format(raw_testcase) config = {} tests = [] for item in raw_testcase: key, test_block = item.popitem() if key == "config": config.update(test_block) elif key == "test": tests.append(load_teststep(test_block)) else: logger.log_warning( "unexpected block key: {}. block key should only be 'config' or 'test'." .format(key)) return {"config": config, "teststeps": tests}
def export_variables(self, output_variables_list): """ export current testcase variables """ variables_mapping = self.session_context.session_variables_mapping output = {} for variable in output_variables_list: if variable not in variables_mapping: logger.log_warning( "variable '{}' can not be found in variables mapping, " "failed to export!".format(variable)) continue output[variable] = variables_mapping[variable] utils.print_info(output) return output
def __load_file_content(path): loaded_content = None try: loaded_content = load_test_file(path) except exceptions.ApiNotFound as ex: logger.log_warning("Invalid api reference in {}: {}".format( path, ex)) except exceptions.FileFormatError: logger.log_warning("Invalid test file format: {}".format(path)) if not loaded_content: pass elif loaded_content["type"] == "testsuite": tests_mapping.setdefault("testsuites", []).append(loaded_content) elif loaded_content["type"] == "testcase": tests_mapping.setdefault("testcases", []).append(loaded_content) elif loaded_content["type"] == "api": tests_mapping.setdefault("apis", []).append(loaded_content)
def run_tests(self, tests_mapping): """ run testcase/testsuite data """ capture_message("start to run tests") project_mapping = tests_mapping.get("project_mapping", {}) self.project_working_directory = project_mapping.get("PWD", os.getcwd()) if self.save_tests: utils.dump_logs(tests_mapping, project_mapping, "loaded") # parse tests self.exception_stage = "parse tests" parsed_testcases = parser.parse_tests(tests_mapping) parse_failed_testfiles = parser.get_parse_failed_testfiles() if parse_failed_testfiles: logger.log_warning("parse failures occurred ...") utils.dump_logs(parse_failed_testfiles, project_mapping, "parse_failed") if self.save_tests: utils.dump_logs(parsed_testcases, project_mapping, "parsed") # add tests to test suite self.exception_stage = "add tests to test suite" test_suite = self._add_tests(parsed_testcases) # run test suite self.exception_stage = "run test suite" results = self._run_suite(test_suite) # aggregate results self.exception_stage = "aggregate results" self._summary = self._aggregate(results) # generate html report self.exception_stage = "generate html report" report.stringify_summary(self._summary) if self.save_tests: utils.dump_logs(self._summary, project_mapping, "summary") return self._summary
def main(): """ Performance test with locust: parse command line options and run commands. """ sys.argv[0] = 'locust' if len(sys.argv) == 1: sys.argv.extend(["-h"]) if sys.argv[1] in ["-h", "--help", "-V", "--version"]: start_locust_main() def get_arg_index(*target_args): for arg in target_args: if arg not in sys.argv: continue return sys.argv.index(arg) + 1 return None # set logging level loglevel_index = get_arg_index("-L", "--loglevel") if loglevel_index and loglevel_index < len(sys.argv): loglevel = sys.argv[loglevel_index] else: # default loglevel = "WARNING" logger.setup_logger(loglevel) # get testcase file path try: testcase_index = get_arg_index("-f", "--locustfile") assert testcase_index and testcase_index < len(sys.argv) except AssertionError: print("Testcase file is not specified, exit.") sys.exit(1) testcase_file_path = sys.argv[testcase_index] sys.argv[testcase_index] = parse_locustfile(testcase_file_path) if "--processes" in sys.argv: """ locusts -f locustfile.py --processes 4 """ if "--no-web" in sys.argv: logger.log_error( "conflict parameter args: --processes & --no-web. \nexit.") sys.exit(1) processes_index = sys.argv.index('--processes') processes_count_index = processes_index + 1 if processes_count_index >= len(sys.argv): """ do not specify processes count explicitly locusts -f locustfile.py --processes """ processes_count = multiprocessing.cpu_count() logger.log_warning( "processes count not specified, use {} by default.".format( processes_count)) else: try: """ locusts -f locustfile.py --processes 4 """ processes_count = int(sys.argv[processes_count_index]) sys.argv.pop(processes_count_index) except ValueError: """ locusts -f locustfile.py --processes -P 8888 """ processes_count = multiprocessing.cpu_count() logger.log_warning( "processes count not specified, use {} by default.".format( processes_count)) sys.argv.pop(processes_index) run_locusts_with_processes(sys.argv, processes_count) else: start_locust_main()
def create_scaffold(project_name): """ create scaffold with specified project name. """ if os.path.isdir(project_name): logger.log_warning( u"Folder {} exists, please specify a new folder name.".format( project_name)) return logger.color_print("Start to create new project: {}".format(project_name), "GREEN") logger.color_print("CWD: {}\n".format(os.getcwd()), "BLUE") def create_folder(path): os.makedirs(path) msg = "created folder: {}".format(path) logger.color_print(msg, "BLUE") def create_file(path, file_content=""): with open(path, 'w') as f: f.write(file_content) msg = "created file: {}".format(path) logger.color_print(msg, "BLUE") demo_api_content = """ name: demo api variables: var1: value1 var2: value2 request: url: /api/path/$var1 method: POST headers: Content-Type: "application/json" json: key: $var2 validate: - eq: ["status_code", 200] """ demo_testcase_content = """ config: name: "demo testcase" variables: device_sn: "ABC" username: ${ENV(USERNAME)} password: ${ENV(PASSWORD)} base_url: "http://127.0.0.1:5000" teststeps: - name: demo step 1 api: path/to/api1.yml variables: user_agent: 'iOS/10.3' device_sn: $device_sn extract: - token: content.token validate: - eq: ["status_code", 200] - name: demo step 2 api: path/to/api2.yml variables: token: $token """ demo_testsuite_content = """ config: name: "demo testsuite" variables: device_sn: "XYZ" base_url: "http://127.0.0.1:5000" testcases: - name: call demo_testcase with data 1 testcase: path/to/demo_testcase.yml variables: device_sn: $device_sn - name: call demo_testcase with data 2 testcase: path/to/demo_testcase.yml variables: device_sn: $device_sn """ ignore_content = "\n".join([ ".env", "reports/*", "__pycache__/*", "*.pyc", ".python-version", "logs/*" ]) demo_debugtalk_content = """ import time def sleep(n_secs): time.sleep(n_secs) """ demo_env_content = "\n".join(["USERNAME=leolee", "PASSWORD=123456"]) create_folder(project_name) create_folder(os.path.join(project_name, "api")) create_folder(os.path.join(project_name, "testcases")) create_folder(os.path.join(project_name, "testsuites")) create_folder(os.path.join(project_name, "reports")) create_file(os.path.join(project_name, "api", "demo_api.yml"), demo_api_content) create_file(os.path.join(project_name, "testcases", "demo_testcase.yml"), demo_testcase_content) create_file(os.path.join(project_name, "testsuites", "demo_testsuite.yml"), demo_testsuite_content) create_file(os.path.join(project_name, "debugtalk.py"), demo_debugtalk_content) create_file(os.path.join(project_name, ".env"), demo_env_content) create_file(os.path.join(project_name, ".gitignore"), ignore_content)