pytest+yaml+allure接口自动化测试框架04.处理request

前言

​ 环境搭建配置、封装日志缓存、读取yaml测试文件,这些工作我们上几个章节已经都做完了,读取文件之后,我们已经成功拿到了测试yaml文件中的测试数据了,那我们接下来就通过这些数据去执行测试,主要就是对这些数据做HTTP请求的请求和响应。

​ 谈到HTTP请求,我们首先就会想到requests库,这个第三方库,以极其优雅的封装方式和简易的写法,在python界有着重要的地位,在这个接口自动化测试框架中,我们也会使用这个库进行二次封装。让其融入到我们的测试框架中来。

​ 对于这个库我就不做过多的介绍了,之前有一篇文章专门介绍,感兴趣可以点击:python requests由浅入深 - 随风挥手 - 博客园 (cnblogs.com)

执行测试的代码

上一章节已经讲了怎么读取测试用例数据,根据pytest官网的non-python test内容,我们还需要编写一个YamlTest类来执行测试。

继续打开conftest.py文件,在里面加上如下内容:

# +++
from common.request import HttpRequest
from common.exceptions import RequestException

# +++

class YamlTest(pytest.Item):
    def __init__(self, name, parent, spec):
        super(YamlTest, self).__init__(name, parent)
        self.spec = spec
        self.request = HttpRequest(exception=(RequestException, Exception))

    def runtest(self):
        """Some custom test execution (dumb example follows)."""
        self.request.send_request(**self.spec)

    def repr_failure(self, excinfo):
        """Called when self.runtest() raises an exception."""
        logger.critical(excinfo.value)
        logger.critical(excinfo.traceback[-6:-1])            

    def reportinfo(self):
        return self.fspath, 0, f"usecase: {self.name}"

通过继承pytest.Item类我们可以使用父类的运行测试的方法来执行测试。

__init__方法

在这个里面我们接收来自yamlfile类中collect方法的yield生成器传给我们的测试数据。

runtest

继承父类的runtest方法我们可以在这个里面执行我们的测试,把接受到的参数传入我们二次封装的HttpRequest类,就可以对我们在yaml文件中添加的接口进行测试了。

repr_failure

如果在运行中发生了用例失败的现象我们可以在这个方法中拦截并打印出相应的报错信息,方便我们排查问题。

reportinfo

通过reportinfo方法重写我们传入的name信息,就是我们在yaml文件中的测试用例名称信息。

这个就是我们通过对YamlTest的改造,组成了一个测试过程。这个类的核心是对requests的二次封装类。

二次封装requests

我们打开common/request.py,我们键入以下内容。

# -*- coding: utf-8 -*-
__author__ = 'wxhou'
__email__ = '1084502012@qq.com'
"""
requests二次封装
"""
import urllib3
from requests import Session, Response
from common.cache import cache
from utils.logger import logger

urllib3.disable_warnings()


class HttpRequest(Session):
    """requests方法二次封装"""

    def __init__(self, *args: t.Union[t.Set, t.List], **kwargs: t.Dict[t.Text, t.Any]):
        super(HttpRequest, self).__init__()
        self.exception = kwargs.get("exception", Exception)

    def send_request(self, **kwargs: t.Dict[t.Text, t.Any]) -> Response:
        """发送请求
        """
        try:
            logger.info("request data: {}".format(kwargs))
            method = kwargs.get('method', 'GET').upper()
            url = cache.get('baseurl') + kwargs.get('route')
            logger.info("Request Url: {}".format(url))
            logger.info("Request Method: {}".format(method))
            logger.info("Request Data: {}".format(kwargs))
            request_data = HttpRequest.mergedict(kwargs.get('RequestData'),
                                                 headers=cache.get('headers'),
                                                 timeout=cache.get('timeout'))
            response = self.dispatch(method, url, **request_data)
            logger.info("Request Result: {}{}".format(response, response.text))
            return response
        except self.exception as e:
            logger.exception(format(e))
            raise e

    def dispatch(self, method, *args, **kwargs):
        """请求分发"""
        handler = getattr(self, method.lower())
        return handler(*args, **kwargs)

    @staticmethod
    def mergedict(args, **kwargs):
        """合并字典"""
        for k, v in args.items():
            if k in kwargs:
                kwargs[k] = {**args[k], **kwargs.pop(k)}
        args.update(kwargs)
        return args

我们通过继承requests库的Session类,添加我们的定制化的一些方法。

send_request方法

我们把YamlTest类中的测试用例数据传入到我们的这个方法中来,然后打印日志记录,并将结果进行返回。

dispatch

在这个方法中我们根据传入的用例请求方法,去反射我们Session类中的相应的请求方法,从而实现get,post等HTTP请求。

mergedict

编写了一个合并字典的方法,用来合并我们定义的请求体或者请求参数,和我们自定义的一些测试配置,比如headers,timeout等。

对于requests的封装暂时就介绍到这里。

好几天没更新了是因为最近有点懒。

上一篇:linux ab压力测试示例


下一篇:【python爬虫】反爬解决方案