예제 #1
0
 def test_parse_variables_mapping_dead_circle(self):
     variables = {"varA": "$varB", "varB": "123$varC"}
     check_variables_set = {"varA", "varB", "varC"}
     prepared_variables = parser.prepare_lazy_data(variables, {},
                                                   check_variables_set)
     with self.assertRaises(exceptions.VariableNotFound):
         parser.parse_variables_mapping(prepared_variables)
예제 #2
0
 def test_parse_variables_mapping_ref_self(self):
     variables = {
         "varC": "${sum_two($a, $b)}",
         "a": 1,
         "b": 2,
         "token": "$token"
     }
     functions = {"sum_two": sum_two}
     prepared_variables = parser.prepare_lazy_data(variables, functions,
                                                   variables.keys())
     with self.assertRaises(exceptions.VariableNotFound):
         parser.parse_variables_mapping(prepared_variables)
예제 #3
0
 def parse_config(config: TConfig):
     config.variables = parse_variables_mapping(
         config.variables, self.__project_meta.functions)
     config.name = parse_data(config.name, config.variables,
                              self.__project_meta.functions)
     config.base_url = parse_data(config.base_url, config.variables,
                                  self.__project_meta.functions)
예제 #4
0
    def run(self, testcase: TestCase):
        """run testcase"""
        self.config = testcase.config
        self.teststeps = testcase.teststeps

        # prepare
        self.__project_meta = self.__project_meta or load_project_meta(
            self.config.path)
        self.__parse_config(self.config)
        self.__start_at = time.time()
        self.__step_datas: List[StepData] = []
        self.__session = self.__session or HttpSession()
        self.__session_variables = {}

        # run teststeps
        for step in self.teststeps:
            # update with config variables
            step.variables.update(self.config.variables)
            # update with session variables extracted from pre step
            step.variables.update(self.__session_variables)
            # parse variables
            step.variables = parse_variables_mapping(
                step.variables, self.__project_meta.functions)
            # run step
            with allure.step(f"step: {step.name}"):
                extract_mapping = self.__run_step(step)
            # save extracted variables to session variables
            self.__session_variables.update(extract_mapping)

        self.__duration = time.time() - self.__start_at
        return self
예제 #5
0
    def init_test_variables(self, variables_mapping=None):
        """ init test variables, called when each test(api) starts.
            init测试变量,在每个测试(api)启动时调用
            variables_mapping will be evaluated first.
            首先计算变量映射

        Args:
            variables_mapping (dict)
                {
                    "random": "${gen_random_string(5)}",
                    "authorization": "${gen_md5($TOKEN, $data, $random)}",
                    "data": '{"name": "user", "password": "******"}',
                    "TOKEN": "debugtalk",
                }

        """
        variables_mapping = variables_mapping or {}
        variables_mapping = utils.ensure_mapping_format(variables_mapping)
        variables_mapping.update(self.session_variables_mapping)
        parsed_variables_mapping = parser.parse_variables_mapping(variables_mapping)

        self.test_variables_mapping = {}
        # priority: extracted variable > teststep variable
        # 优先级:提取的变量 > teststep变量
        self.test_variables_mapping.update(parsed_variables_mapping)
        self.test_variables_mapping.update(self.session_variables_mapping)
예제 #6
0
        def _add_test(test_runner, test_dict):
            """ add test to testcase.
            """
            def test(self):
                try:
                    test_runner.run_test(test_dict)
                except exceptions.MyBaseFailure as ex:
                    self.fail(str(ex))
                finally:
                    self.meta_datas = test_runner.meta_datas

            if "config" in test_dict:
                # run nested testcase
                test.__doc__ = test_dict["config"].get("name")
                variables = test_dict["config"].get("variables", {})
            else:
                # run api test
                test.__doc__ = test_dict.get("name")
                variables = test_dict.get("variables", {})

            if isinstance(test.__doc__, parser.LazyString):
                try:
                    parsed_variables = parser.parse_variables_mapping(
                        variables)
                    test.__doc__ = parser.parse_lazy_data(
                        test.__doc__, parsed_variables)
                except exceptions.VariableNotFound:
                    test.__doc__ = str(test.__doc__)

            return test
예제 #7
0
    def init_test_variables(self, variables_mapping=None):
        """ init test variables, called when each test(api) starts.
            variables_mapping will be evaluated first.

        Args:
            variables_mapping (dict)
                {
                    "random": "${gen_random_string(5)}",
                    "authorization": "${gen_md5($TOKEN, $data, $random)}",
                    "data": '{"name": "user", "password": "******"}',
                    "TOKEN": "debugtalk",
                }

        """
        variables_mapping = variables_mapping or {}
        variables_mapping = utils.ensure_mapping_format(variables_mapping)
        if "m_encoder" in self.session_variables_mapping.keys(
        ):  # 增加判断,如果全局配置变量存在m_encoder,就删除掉
            self.session_variables_mapping.pop("m_encoder")
        variables_mapping.update(self.session_variables_mapping)
        parsed_variables_mapping = parser.parse_variables_mapping(
            variables_mapping)

        self.test_variables_mapping = {}
        # priority: extracted variable > teststep variable
        self.test_variables_mapping.update(parsed_variables_mapping)
        self.test_variables_mapping.update(self.session_variables_mapping)
예제 #8
0
        def _add_test(test_runner, test_dict):
            """ add test to testcase. 把步骤添加到用例,返回一个测试步骤
            test_dict = parsed_testcases[0][teststeps][0]
            test_dict = {
                "name": "/mgmt/store/checkBusinessAddressIsExist",
                "request": {
                    "headers": {"Authorization": "LazyString(${token_type} ${access_token})"},
                    "method": "GET",
                    "params": {
                        "provinceName": "LazyString(${provinceName})",
                        "cityName": "LazyString(${cityName})",
                        "areaName": LazyString(${areaName}),
                        "streetName": LazyString(${streetName}),
                        "detailAddress": LazyString(${detailAddress})},
                        "url": LazyString(${base_url}/mgmt/store/checkBusinessAddressIsExist),
                        "verify": True
                        },
                        "variables": {
                            "provinceName": "广东省",
                            "cityName": "广州市",
                            "areaName": "海珠区",
                            "streetName": "南州街道",
                            "detailAddress": "广州市海珠区南洲街道新滘中路88号唯品同创汇6区东三街17号自编23号",
                            "access_token": LazyString(${ENV(access_token)}),
                            "token_type": LazyString(${ENV(token_type)}),
                            "base_url": LazyString(${ENV(base_url)})
                        },
                        "validate": [LazyFunction(equals(status_code, 200))]
            }
            """
            def test(self):
                try:
                    test_runner.run_test(test_dict)
                    pprint(test_runner)
                except exceptions.MyBaseFailure as ex:
                    self.fail(str(ex))
                finally:
                    self.meta_datas = test_runner.meta_datas

            if "config" in test_dict:
                # run nested testcase 嵌套testcase运行:testcase引用了testcase
                test.__doc__ = test_dict["config"].get("name")
                variables = test_dict["config"].get("variables", {})
            else:
                # run api test  运行api测试  testcase引用了api
                test.__doc__ = test_dict.get("name")
                variables = test_dict.get("variables", {})

            if isinstance(test.__doc__, parser.LazyString):  #懒惰的字符串:名字中有引用的变量

                try:
                    parsed_variables = parser.parse_variables_mapping(
                        variables)  # 所有的变量字典
                    test.__doc__ = parser.parse_lazy_data(  # 找到引用变量对应的值
                        test.__doc__, parsed_variables)
                except exceptions.VariableNotFound:
                    test.__doc__ = str(test.__doc__)
            # 返回函数<function HttpRunner._add_tests.<locals>._add_test.<locals>.test at 0x000002D69C38A550>
            return test
예제 #9
0
 def __parse_config(self, config: TConfig) -> NoReturn:
     config.variables.update(self.__session_variables)
     config.variables = parse_variables_mapping(
         config.variables, self.__project_meta.functions)
     config.name = parse_data(config.name, config.variables,
                              self.__project_meta.functions)
     config.base_url = parse_data(config.base_url, config.variables,
                                  self.__project_meta.functions)
예제 #10
0
 def test_parse_variables_mapping_fix_duplicate_function_call(self):
     # fix duplicate function calling
     variables = {"varA": "$varB", "varB": "${gen_random_string(5)}"}
     functions = {"gen_random_string": gen_random_string}
     prepared_variables = parser.prepare_lazy_data(variables, functions,
                                                   variables.keys())
     parsed_variables = parser.parse_variables_mapping(prepared_variables)
     self.assertEqual(parsed_variables["varA"], parsed_variables["varB"])
예제 #11
0
 def test_parse_variables_mapping(self):
     variables = {
         "varA": "$varB",
         "varB": "$varC",
         "varC": "123",
         "a": 1,
         "b": 2
     }
     parsed_variables = parser.parse_variables_mapping(variables)
     print(parsed_variables)
     self.assertEqual(parsed_variables["varA"], "123")
     self.assertEqual(parsed_variables["varB"], "123")
예제 #12
0
 def test_parse_tests_variable_with_function(self):
     tests_mapping = {
         "project_mapping": {
             "functions": {
                 "sum_two": sum_two,
                 "gen_random_string": gen_random_string
             }
         },
         'testcases': [
             {
                 "config": {
                     'name': '',
                     "base_url": "$host1",
                     'variables': {
                         "host1": "https://debugtalk.com",
                         "var_a": "${gen_random_string(5)}",
                         "var_b": "$var_a"
                     }
                 },
                 "teststeps": [
                     {
                         'name': 'testcase1',
                         "base_url": "$host2",
                         "variables": {
                             "host2": "https://httprunner.org",
                             "num3": "${sum_two($num2, 4)}",
                             "num2": "${sum_two($num1, 3)}",
                             "num1": "${sum_two(1, 2)}",
                             "str1": "${gen_random_string(5)}",
                             "str2": "$str1"
                         },
                         'request': {
                             'url': '/api1/?num1=$num1&num2=$num2&num3=$num3',
                             'method': 'GET'
                         }
                     }
                 ]
             }
         ]
     }
     parsed_testcases = parser.parse_tests(tests_mapping)
     test_dict = parsed_testcases[0]["teststeps"][0]
     variables = parser.parse_variables_mapping(test_dict["variables"])
     self.assertEqual(variables["num3"], 10)
     self.assertEqual(variables["num2"], 6)
     parsed_test_dict = parser.parse_lazy_data(test_dict, variables)
     self.assertEqual(parsed_test_dict["base_url"], "https://httprunner.org")
     self.assertEqual(
         parsed_test_dict["request"]["url"],
         "/api1/?num1=3&num2=6&num3=10"
     )
     self.assertEqual(variables["str1"], variables["str2"])
예제 #13
0
def prepare_upload_step(step: TStep,
                        functions: FunctionsMapping) -> "NoReturn":
    """ preprocess for upload test
        replace `upload` info with MultipartEncoder

    Args:
        step: teststep
            {
                "variables": {},
                "request": {
                    "url": "http://httpbin.org/upload",
                    "method": "POST",
                    "headers": {
                        "Cookie": "session=AAA-BBB-CCC"
                    },
                    "upload": {
                        "file": "data/file_to_upload"
                        "md5": "123"
                    }
                }
            }
        functions: functions mapping

    """
    if not step.request.upload:
        return

    if not UPLOAD_READY:
        msg = """
uploader extension dependencies uninstalled, install first and try again.
install with pip:
$ pip install requests_toolbelt filetype
"""
        logger.error(msg)
        sys.exit(1)

    params_list = []
    for key, value in step.request.upload.items():
        step.variables[key] = value
        params_list.append(f"{key}=${key}")

    params_str = ", ".join(params_list)
    step.variables["m_encoder"] = "${multipart_encoder(" + params_str + ")}"

    # parse variables
    step.variables = parse_variables_mapping(step.variables, functions)

    step.request.headers[
        "Content-Type"] = "${multipart_content_type($m_encoder)}"

    step.request.data = "$m_encoder"
예제 #14
0
 def test_parse_variables_mapping_2(self):
     variables = {
         "host2": "https://httprunner.org",
         "num3": "${sum_two($num2, 4)}",
         "num2": "${sum_two($num1, 3)}",
         "num1": "${sum_two(1, 2)}"
     }
     functions = {"sum_two": sum_two}
     prepared_variables = parser.prepare_lazy_data(variables, functions,
                                                   variables.keys())
     parsed_testcase = parser.parse_variables_mapping(prepared_variables)
     self.assertEqual(parsed_testcase["num3"], 10)
     self.assertEqual(parsed_testcase["num2"], 6)
     self.assertEqual(parsed_testcase["num1"], 3)
예제 #15
0
 def test_parse_variables_mapping(self):
     variables = {
         "varA": "123$varB",
         "varB": "456$varC",
         "varC": "${sum_two($a, $b)}",
         "a": 1,
         "b": 2
     }
     functions = {"sum_two": sum_two}
     prepared_variables = parser.prepare_lazy_data(variables, functions,
                                                   variables.keys())
     parsed_variables = parser.parse_variables_mapping(prepared_variables)
     self.assertEqual(parsed_variables["varA"], "1234563")
     self.assertEqual(parsed_variables["varB"], "4563")
     self.assertEqual(parsed_variables["varC"], 3)
예제 #16
0
    def run_testcase(self, testcase: TestCase) -> "HttpRunner":
        """run specified testcase

        Examples:
            >>> testcase_obj = TestCase(config=TConfig(...), teststeps=[TStep(...)])
            >>> HttpRunner().with_project_meta(project_meta).run_testcase(testcase_obj)

        """
        self.__config = testcase.config
        self.__teststeps = testcase.teststeps

        # prepare
        self.__project_meta = self.__project_meta or load_project_meta(
            self.__config.path
        )
        self.__parse_config(self.__config)
        self.__start_at = time.time()
        self.__step_datas: List[StepData] = []
        self.__session = self.__session or HttpSession()
        self.__session_variables = {}

        # run teststeps
        for step in self.__teststeps:
            # override variables
            # session variables (extracted from pre step) > step variables
            step.variables.update(self.__session_variables)
            # step variables > testcase config variables
            step.variables = override_config_variables(
                step.variables, self.__config.variables
            )

            # parse variables
            step.variables = parse_variables_mapping(
                step.variables, self.__project_meta.functions
            )

            # run step
            if USE_ALLURE:
                with allure.step(f"step: {step.name}"):
                    extract_mapping = self.__run_step(step)
            else:
                extract_mapping = self.__run_step(step)

            # save extracted variables to session variables
            self.__session_variables.update(extract_mapping)

        self.__duration = time.time() - self.__start_at
        return self
예제 #17
0
 def test_parse_variables_mapping_dollar_notation(self):
     variables = {
         "varA": "123$varB",
         "varB": "456$$0",
         "varC": "${sum_two($a, $b)}",
         "a": 1,
         "b": 2,
         "c": "abc"
     }
     functions = {"sum_two": sum_two}
     prepared_variables = parser.prepare_lazy_data(variables, functions,
                                                   variables.keys())
     parsed_testcase = parser.parse_variables_mapping(prepared_variables)
     self.assertEqual(parsed_testcase["varA"], "123456$0")
     self.assertEqual(parsed_testcase["varB"], "456$0")
     self.assertEqual(parsed_testcase["varC"], 3)
예제 #18
0
    def test_prepare_lazy_data_dual_dollar(self):
        variables = {
            "num0": 123,
            "var1": "abc$$num0",
            "var2": "abc$$$num0",
            "var3": "abc$$$$num0",
        }
        functions = {"sum_two": sum_two}
        prepared_variables = parser.prepare_lazy_data(variables, functions,
                                                      variables.keys())
        self.assertEqual(prepared_variables["var1"], "abc$num0")
        self.assertIsInstance(prepared_variables["var2"], parser.LazyString)
        self.assertEqual(prepared_variables["var3"], "abc$$num0")

        parsed_variables = parser.parse_variables_mapping(prepared_variables)
        self.assertEqual(parsed_variables["var1"], "abc$num0")
        self.assertEqual(parsed_variables["var2"], "abc$123")
        self.assertEqual(parsed_variables["var3"], "abc$$num0")
예제 #19
0
def prepare_upload_step(step: TStep, functions: FunctionsMapping):
    """preprocess for upload test
        replace `upload` info with MultipartEncoder

    Args:
        step: teststep
            {
                "variables": {},
                "request": {
                    "url": "http://httpbin.org/upload",
                    "method": "POST",
                    "headers": {
                        "Cookie": "session=AAA-BBB-CCC"
                    },
                    "upload": {
                        "file": "data/file_to_upload"
                        "md5": "123"
                    }
                }
            }
        functions: functions mapping

    """
    if not step.request.upload:
        return

    # parse upload info
    step.request.upload = parse_data(step.request.upload, step.variables, functions)

    ensure_upload_ready()
    params_list = []
    for key, value in step.request.upload.items():
        step.variables[key] = value
        params_list.append(f"{key}=${key}")

    params_str = ", ".join(params_list)
    step.variables["m_encoder"] = "${multipart_encoder(" + params_str + ")}"

    # parse variables
    step.variables = parse_variables_mapping(step.variables, functions)

    step.request.headers["Content-Type"] = "${multipart_content_type($m_encoder)}"

    step.request.data = "$m_encoder"
예제 #20
0
    def test_get_parsed_request(self):
        variables = {
            "random": "${gen_random_string(5)}",
            "data": '{"name": "user", "password": "******"}',
            "authorization": "${gen_md5($TOKEN, $data, $random)}",
            "TOKEN": "debugtalk"
        }
        functions = {
            "gen_random_string": gen_random_string,
            "gen_md5": gen_md5
        }
        variables = parser.prepare_lazy_data(variables, functions,
                                             variables.keys())
        variables = parser.parse_variables_mapping(variables)
        self.context.init_test_variables(variables)

        request = {
            "url": "http://127.0.0.1:5000/api/users/1000",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json",
                "authorization": "$authorization",
                "random": "$random",
                "secret_key": "$SECRET_KEY"
            },
            "data": "$data"
        }
        prepared_request = parser.prepare_lazy_data(
            request, functions,
            {"authorization", "random", "SECRET_KEY", "data"})
        parsed_request = self.context.eval_content(prepared_request)
        self.assertIn("authorization", parsed_request["headers"])
        self.assertEqual(len(parsed_request["headers"]["authorization"]), 32)
        self.assertIn("random", parsed_request["headers"])
        self.assertEqual(len(parsed_request["headers"]["random"]), 5)
        self.assertIn("data", parsed_request)
        self.assertEqual(parsed_request["data"],
                         '{"name": "user", "password": "******"}')
        self.assertEqual(parsed_request["headers"]["secret_key"], "DebugTalk")
예제 #21
0
    def run(self, testcase: TestCase):
        """main entrance"""
        self.config = testcase.config
        self.teststeps = testcase.teststeps
        self.config.variables.update(self.__session_variables)

        if self.config.path:
            self.__project_meta = load_project_meta(self.config.path)
        elif not self.__project_meta:
            self.__project_meta = ProjectMeta()

        def parse_config(config: TConfig):
            config.variables = parse_variables_mapping(
                config.variables, self.__project_meta.functions)
            config.name = parse_data(config.name, config.variables,
                                     self.__project_meta.functions)
            config.base_url = parse_data(config.base_url, config.variables,
                                         self.__project_meta.functions)

        parse_config(self.config)
        self.__start_at = time.time()
        self.__step_datas: List[StepData] = []
        self.__session_variables = {}
        for step in self.teststeps:
            # update with config variables
            step.variables.update(self.config.variables)
            # update with session variables extracted from pre step
            step.variables.update(self.__session_variables)
            # parse variables
            step.variables = parse_variables_mapping(
                step.variables, self.__project_meta.functions)
            # run step
            extract_mapping = self.__run_step(step)
            # save extracted variables to session variables
            self.__session_variables.update(extract_mapping)

        self.__duration = time.time() - self.__start_at
        return self
예제 #22
0
 def test_init_test_variables(self):
     variables = {
         "random": "${gen_random_string($num)}",
         "authorization": "${gen_md5($TOKEN, $data, $random)}",
         "data": "$username",
         # TODO: escape '{' and '}'
         # "data": '{"name": "$username", "password": "******"}',
         "TOKEN": "debugtalk",
         "username": "******",
         "num": 6
     }
     functions = {
         "gen_random_string": gen_random_string,
         "gen_md5": gen_md5
     }
     variables = parser.prepare_lazy_data(variables, functions,
                                          variables.keys())
     variables = parser.parse_variables_mapping(variables)
     self.context.init_test_variables(variables)
     variables_mapping = self.context.test_variables_mapping
     self.assertEqual(len(variables_mapping["random"]), 6)
     self.assertEqual(len(variables_mapping["authorization"]), 32)
     self.assertEqual(variables_mapping["data"], 'user1')
예제 #23
0
    def _aggregate(self, testcases_results, testcase_details=None):
        """ aggregate results

        Args:
            testcases_results (list): list of (test_case, result)

        """
        summary = {
            "success": True,
            "stat": {
                "testcases": {
                    "total": len(testcases_results),
                    "success": 0,
                    "fail": 0
                },
                "teststeps": {}
            },
            "time": {},
            "platform": report.get_platform(),
            "details": []
        }

        # custom
        for index_case, tests_result in enumerate(testcases_results):
            testcase, result = tests_result
            testcase_summary = report.get_summary(result)

            if testcase_summary["success"]:
                summary["stat"]["testcases"]["success"] += 1
            else:
                summary["stat"]["testcases"]["fail"] += 1

            summary["success"] &= testcase_summary["success"]
            testcase_summary["name"] = testcase.config.get("name")
            testcase_summary["in_out"] = utils.get_testcase_io(testcase)

            report.aggregate_stat(
                summary["stat"]["teststeps"], testcase_summary["stat"])
            report.aggregate_stat(summary["time"], testcase_summary["time"])

            # ==================================================
            # custom: add step detail to summary, by zheng.zhang
            # step detail path in summary: summary.details[i].records[j].step_detail
            teststeps = testcase.teststeps
            for index_step, teststep in enumerate(teststeps):
                try:
                    step_detail = parser.parse_variables_mapping(teststep["variables"])
                    testcase_summary["records"][index_step]["step_detail"] = step_detail
                except exceptions.VariableNotFound as e:
                    # TODO: deal with various built-in Exception
                    testcase_summary["records"][index_step]["step_detail"] = {
                        "internel error message": \
                            "error during adding step details: VariableNotFound",
                        "Exception message": e
                    }
                    # print("error during adding step detail to summary,  \
                    #     in {}".format(__file__))
            
            # ==================================================

            summary["details"].append(testcase_summary)

        return summary
예제 #24
0
 def test_parse_variables_mapping_exception(self):
     variables = {"varA": "$varB", "varB": "$varC", "a": 1, "b": 2}
     with self.assertRaises(VariableNotFound):
         parser.parse_variables_mapping(variables)
예제 #25
0
 def __init__(self, variables=None):
     variables_mapping = utils.ensure_mapping_format(variables or {})
     self.session_variables_mapping = parser.parse_variables_mapping(
         variables_mapping)
     self.test_variables_mapping = {}
     self.init_test_variables()
예제 #26
0
    def run_testcase(self, testcase: TestCase) -> "HttpRunner":
        """run specified testcase

        Examples:
            >>> testcase_obj = TestCase(config=TConfig(...), teststeps=[TStep(...)])
            >>> HttpRunner().with_project_meta(project_meta).run_testcase(testcase_obj)

        """
        self.__config = testcase.config
        self.__teststeps = testcase.teststeps

        # prepare
        self.__project_meta = self.__project_meta or load_project_meta(
            self.__config.path)
        self.__parse_config(self.__config)
        self.__start_at = time.time()
        self.__step_datas: List[StepData] = []
        self.__session = self.__session or HttpSession()
        # save extracted variables of teststeps
        extracted_variables: VariablesMapping = {}

        # run teststeps
        for step in self.__teststeps:
            # override variables
            # step variables > extracted variables from previous steps
            step.variables = merge_variables(step.variables,
                                             extracted_variables)
            # step variables > testcase config variables
            step.variables = merge_variables(step.variables,
                                             self.__config.variables)

            # parse variables
            step.variables = parse_variables_mapping(
                step.variables, self.__project_meta.functions)

            while True:
                # run step
                if USE_ALLURE:
                    with allure.step(f"step: {step.name}"):
                        extract_mapping = self.__run_step(step)
                else:
                    extract_mapping = self.__run_step(step)

                if step.retry_whens:
                    variables_mapping = step.variables
                    variables_mapping.update(extract_mapping)

                    try:
                        response = step.variables.get(
                            'response') or ResponseObject(requests.Response())
                        if isinstance(response, ResponseObject):
                            response.validate(step.retry_whens,
                                              variables_mapping,
                                              self.__project_meta.functions)
                        else:
                            break
                    except ValidationFailure:
                        break
                else:
                    break

            # save extracted variables to session variables
            extracted_variables.update(extract_mapping)

        self.__session_variables.update(extracted_variables)
        self.__duration = time.time() - self.__start_at
        return self
예제 #27
0
    def run_testcase(self, testcase: TestCase) -> "HttpRunner":
        """run specified testcase

        Examples:
            >>> testcase_obj = TestCase(config=TConfig(...), teststeps=[TStep(...)])
            >>> HttpRunner().with_project_meta(project_meta).run_testcase(testcase_obj)

        """
        self.__config = testcase.config
        self.__teststeps = testcase.teststeps

        # prepare
        self.__project_meta = self.__project_meta or load_project_meta(
            self.__config.path)
        self.__parse_config(self.__config)
        self.__start_at = time.time()
        self.__step_datas: List[StepData] = []
        self.__session = self.__session or HttpSession()
        # save extracted variables of teststeps
        extracted_variables: VariablesMapping = {}

        # run teststeps
        for step in self.__teststeps:
            # override variables
            # step variables > extracted variables from previous steps
            step.variables = merge_variables(step.variables,
                                             extracted_variables)
            # step variables > testcase config variables
            step.variables = merge_variables(step.variables,
                                             self.__config.variables)

            # parse variables
            step.variables = parse_variables_mapping(
                step.variables, self.__project_meta.functions)

            step.skipif = parse_data(step.skipif, step.variables,
                                     self.__project_meta.functions)

            # 跳过满足条件的步骤
            logger.debug(f"[跳过步骤] skipif={step.skipif}")
            if step.skipif == '':
                continue

            if step.skipif and eval(step.skipif):
                logger.debug(
                    f"[满足条件,跳过步骤] skipif={step.skipif} | step_name={step.name}"
                )
                continue

            # run step
            if USE_ALLURE:
                with allure.step(f"step: {step.name}"):
                    extract_mapping = self.__run_step(step)
            else:
                extract_mapping = self.__run_step(step)

            # 每运行一个步骤就重新加载公共变量
            logger.debug(f"step.variables={step.variables}")
            step.variables.clear()

            # save extracted variables to session variables
            extracted_variables.update(extract_mapping)

        self.__session_variables.update(extracted_variables)
        self.__duration = time.time() - self.__start_at
        return self