httprunner2.x--用例中提取数据:delimiter 界定符方式源码解读

在 HttpRunner 中提取数据时,根据界定符的方式进行提取,涉及到的内容包括如下:

["status_code", "encoding", "ok", "reason", "url"]
cookies
elapsed
headers
["content", "text", "json"]

从源码角度分析 httprunner\httprunner\response.py:

def _extract_field_with_delimiter(self, field):
        """ response content could be json or html text.

        Args:
            field (str): string joined by delimiter.
            e.g.
                "status_code"
                "headers"
                "cookies"
                "content"
                "headers.content-type"
                "content.person.name.first_name"

        """
        # string.split(sep=None, maxsplit=1) -> list of strings
        # e.g. "content.person.name" => ["content", "person.name"]
        try:
            top_query, sub_query = field.split('.', 1)
        except ValueError:
            top_query = field
            sub_query = None

        # status_code
        # 1.......如果是顶级项,提取数据的目标区域为列表中的内容
        if top_query in ["status_code", "encoding", "ok", "reason", "url"]:
            # 如果有子项,返回子项
            if sub_query:
                # status_code.XX
                # 子项的取值
                err_msg = u"Failed to extract: {}\n".format(field)
                logger.log_error(err_msg)
                raise exceptions.ParamsError(err_msg)
            
            # 没有子项返回 顶级项
            return getattr(self, top_query)

        # cookies
        # 2...提取数据的目标区域为cookies
        elif top_query == "cookies":
            cookies = self.cookies
            # 如果没有子项,返回全部cookies内容(cookies有可能多个)
            if not sub_query:
                # extract cookies
                return cookies

            try:
                # 如果有子项,返回指定子项
                return cookies[sub_query]
            except KeyError:
                err_msg = u"Failed to extract cookie! => {}\n".format(field)
                err_msg += u"response cookies: {}\n".format(cookies)
                logger.log_error(err_msg)
                raise exceptions.ExtractFailure(err_msg)

        # elapsed
        # 3.....提取数据的目标为相应时间
        elif top_query == "elapsed":
            # 支持的时间格式
            available_attributes = u"available attributes: days, seconds, microseconds, total_seconds"
            if not sub_query:
                err_msg = u"elapsed is datetime.timedelta instance, attribute should also be specified!\n"
                err_msg += available_attributes
                logger.log_error(err_msg)
                raise exceptions.ParamsError(err_msg)
            # 以天,秒,微秒为子项
            elif sub_query in ["days", "seconds", "microseconds"]:
                return getattr(self.elapsed, sub_query)
            # 以总秒为子项
            elif sub_query == "total_seconds":
                return self.elapsed.total_seconds()
            else:
                err_msg = "{} is not valid datetime.timedelta attribute.\n".format(sub_query)
                err_msg += available_attributes
                logger.log_error(err_msg)
                raise exceptions.ParamsError(err_msg)

        # headers
        # 4....提取数据的目标为相应头部区域
        elif top_query == "headers":
            headers = self.headers
            # 如果没有子项,返回整个头域
            if not sub_query:
                # extract headers
                return headers

            try:
                # 如果有子项,返回头域中该子项的值
                return headers[sub_query]
            except KeyError:
                err_msg = u"Failed to extract header! => {}\n".format(field)
                err_msg += u"response headers: {}\n".format(headers)
                logger.log_error(err_msg)
                raise exceptions.ExtractFailure(err_msg)

        # response body
        # 如果顶级项为列表中内容
        elif top_query in ["content", "text", "json"]:
            try:
                # 返回json类型响应实体
                body = self.json
            except exceptions.JSONDecodeError:
                # 如果响应实体不是json类型,则返回text类型
                body = self.text

            if not sub_query:
                # extract response body
                # 如果没有子项,返回整个实体内容
                return body

            # 如果实体属于dict或list类型
            if isinstance(body, (dict, list)):
                # content = {"xxx": 123}, content.xxx
                # 返回子项对应的值
                return utils.query_json(body, sub_query)
            elif sub_query.isdigit():
                # content = "abcdefg", content.3 => d
                # 如果子项是数字,返回该数字序号位置的字符串
                return utils.query_json(body, sub_query)
            else:
                # content = "<html>abcdefg</html>", content.xxx
                err_msg = u"Failed to extract attribute from response body! => {}\n".format(field)
                err_msg += u"response body: {}\n".format(body)
                logger.log_error(err_msg)
                raise exceptions.ExtractFailure(err_msg)

        # new set response attributes in teardown_hooks
        elif top_query in self.__dict__:
            attributes = self.__dict__[top_query]

            if not sub_query:
                # extract response attributes
                return attributes

            if isinstance(attributes, (dict, list)):
                # attributes = {"xxx": 123}, content.xxx
                return utils.query_json(attributes, sub_query)
            elif sub_query.isdigit():
                # attributes = "abcdefg", attributes.3 => d
                return utils.query_json(attributes, sub_query)
            else:
                # content = "attributes.new_attribute_not_exist"
                err_msg = u"Failed to extract cumstom set attribute from teardown hooks! => {}\n".format(field)
                err_msg += u"response set attributes: {}\n".format(attributes)
                logger.log_error(err_msg)
                raise exceptions.TeardownHooksFailure(err_msg)

        # others
        else:
            err_msg = u"Failed to extract attribute from response! => {}\n".format(field)
            err_msg += u"available response attributes: status_code, cookies, elapsed, headers, content, text, json, encoding, ok, reason, url.\n\n"
            err_msg += u"If you want to set attribute in teardown_hooks, take the following example as reference:\n"
            err_msg += u"response.new_attribute = 'new_attribute_value'\n"
            logger.log_error(err_msg)
            raise exceptions.ParamsError(err_msg)

  

 

posted @ 2021-06-04 10:03  莫使娇躯空对月  阅读(241)  评论(0编辑  收藏  举报