我们在做自动化测试的时候,大家都是希望自己写的代码越简洁越好,代码重复量越少越好。那么,我们可以考虑将request的请求类型(如:Get、Post、Delect请求)都封装起来。这样,我们在编写用例的时候就可以直接进行请求了。

1. 源码分析

我们先来看一下Get、Post、Delect等请求的源码,看一下它们都有什么特点。

(1)Get请求源码

  1. def get(self, url, **kwargs):

  2. r"""Sends a GET request. Returns :class:`Response` object.

  3. :param url: URL for the new :class:`Request` object.

  4. :param \*\*kwargs: Optional arguments that ``request`` takes.

  5. :rtype: requests.Response

  6. """

  7. kwargs.setdefault('allow_redirects', True)

  8. return self.request('GET', url, **kwargs)

(2)Post请求源码

  1. def post(self, url, data=None, json=None, **kwargs):

  2. r"""Sends a POST request. Returns :class:`Response` object.

  3. :param url: URL for the new :class:`Request` object.

  4. :param data: (optional) Dictionary, list of tuples, bytes, or file-like

  5. object to send in the body of the :class:`Request`.

  6. :param json: (optional) json to send in the body of the :class:`Request`.

  7. :param \*\*kwargs: Optional arguments that ``request`` takes.

  8. :rtype: requests.Response

  9. """

  10. return self.request('POST', url, data=data, json=json, **kwargs)

(3)Delect请求源码

  1. def delete(self, url, **kwargs):

  2. r"""Sends a DELETE request. Returns :class:`Response` object.

  3. :param url: URL for the new :class:`Request` object.

  4. :param \*\*kwargs: Optional arguments that ``request`` takes.

  5. :rtype: requests.Response

  6. """

  7. return self.request('DELETE', url, **kwargs)

(4)分析结果

我们发现,不管是Get请求、还是Post请求或者是Delect请求,它们到最后返回的都是request函数。那么,我们再去看一看request函数的源码。

  1. def request(self, method, url,

  2. params=None, data=None, headers=None, cookies=None, files=None,

  3. auth=None, timeout=None, allow_redirects=True, proxies=None,

  4. hooks=None, stream=None, verify=None, cert=None, json=None):

  5. """Constructs a :class:`Request <Request>`, prepares it and sends it.

  6. Returns :class:`Response <Response>` object.

  7. :param method: method for the new :class:`Request` object.

  8. :param url: URL for the new :class:`Request` object.

  9. :param params: (optional) Dictionary or bytes to be sent in the query

  10. string for the :class:`Request`.

  11. :param data: (optional) Dictionary, list of tuples, bytes, or file-like

  12. object to send in the body of the :class:`Request`.

  13. :param json: (optional) json to send in the body of the

  14. :class:`Request`.

  15. :param headers: (optional) Dictionary of HTTP Headers to send with the

  16. :class:`Request`.

  17. :param cookies: (optional) Dict or CookieJar object to send with the

  18. :class:`Request`.

  19. :param files: (optional) Dictionary of ``'filename': file-like-objects``

  20. for multipart encoding upload.

  21. :param auth: (optional) Auth tuple or callable to enable

  22. Basic/Digest/Custom HTTP Auth.

  23. :param timeout: (optional) How long to wait for the server to send

  24. data before giving up, as a float, or a :ref:`(connect timeout,

  25. read timeout) <timeouts>` tuple.

  26. :type timeout: float or tuple

  27. :param allow_redirects: (optional) Set to True by default.

  28. :type allow_redirects: bool

  29. :param proxies: (optional) Dictionary mapping protocol or protocol and

  30. hostname to the URL of the proxy.

  31. :param stream: (optional) whether to immediately download the response

  32. content. Defaults to ``False``.

  33. :param verify: (optional) Either a boolean, in which case it controls whether we verify

  34. the server's TLS certificate, or a string, in which case it must be a path

  35. to a CA bundle to use. Defaults to ``True``.

  36. :param cert: (optional) if String, path to ssl client cert file (.pem).

  37. If Tuple, ('cert', 'key') pair.

  38. :rtype: requests.Response

  39. """

  40. # Create the Request.

  41. req = Request(

  42. method=method.upper(),

  43. url=url,

  44. headers=headers,

  45. files=files,

  46. data=data or {},

  47. json=json,

  48. params=params or {},

  49. auth=auth,

  50. cookies=cookies,

  51. hooks=hooks,

  52. )

  53. prep = self.prepare_request(req)

  54. proxies = proxies or {}

  55. settings = self.merge_environment_settings(

  56. prep.url, proxies, stream, verify, cert

  57. )

  58. # Send the request.

  59. send_kwargs = {

  60. 'timeout': timeout,

  61. 'allow_redirects': allow_redirects,

  62. }

  63. send_kwargs.update(settings)

  64. resp = self.send(prep, **send_kwargs)

  65. return resp

从request源码可以看出,它先创建一个Request,然后将传过来的所有参数放在里面,再接着调用self.send(),并将Request传过去。这里我们将不在分析后面的send等方法的源码了,有兴趣的同学可以自行了解。

分析完源码之后发现,我们可以不需要单独在一个类中去定义Get、Post等其他方法,然后在单独调用request。其实,我们直接调用request即可。

2. requests请求封装

代码示例:

  1. import requests

  2. class RequestMain:

  3. def __init__(self):

  4. """

  5. session管理器

  6. requests.session(): 维持会话,跨请求的时候保存参数

  7. """

  8. # 实例化session

  9. self.session = requests.session()

  10. def request_main(self, method, url, params=None, data=None, json=None, headers=None, **kwargs):

  11. """

  12. :param method: 请求方式

  13. :param url: 请求地址

  14. :param params: 字典或bytes,作为参数增加到url中

  15. :param data: data类型传参,字典、字节序列或文件对象,作为Request的内容

  16. :param json: json传参,作为Request的内容

  17. :param headers: 请求头,字典

  18. :param kwargs: 若还有其他的参数,使用可变参数字典形式进行传递

  19. :return:

  20. """

  21. # 对异常进行捕获

  22. try:

  23. """

  24. 封装request请求,将请求方法、请求地址,请求参数、请求头等信息入参。

  25. 注 :verify: True/False,默认为True,认证SSL证书开关;cert: 本地SSL证书。如果不需要ssl认证,可将这两个入参去掉

  26. """

  27. re_data = self.session.request(method, url, params=params, data=data, json=json, headers=headers, cert=(client_crt, client_key), verify=False, **kwargs)

  28. # 异常处理 报错显示具体信息

  29. except Exception as e:

  30. # 打印异常

  31. print("请求失败:{0}".format(e))

  32. # 返回响应结果

  33. return re_data

  34. if __name__ == '__main__':

  35. # 请求地址

  36. url = '请求地址'

  37. # 请求参数

  38. payload = {"请求参数"}

  39. # 请求头

  40. header = {"headers"}

  41. # 实例化 RequestMain()

  42. re = RequestMain()

  43. # 调用request_main,并将参数传过去

  44. request_data = re.request_main("请求方式", url, json=payload, headers=header)

  45. # 打印响应结果

  46. print(request_data.text)

注 :如果你调的接口不需要SSL认证,可将cert与verify两个参数去掉。

 感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

更多推荐