我们在做自动化测试的时候,大家都是希望自己写的代码越简洁越好,代码重复量越少越好。那么,我们可以考虑将request的请求类型(如:Get、Post、Delect请求)都封装起来。这样,我们在编写用例的时候就可以直接进行请求了。
1. 源码分析
我们先来看一下Get、Post、Delect等请求的源码,看一下它们都有什么特点。
(1)Get请求源码
def get(self, url, **kwargs):r"""Sends a GET request. Returns :class:`Response` object.:param url: URL for the new :class:`Request` object.:param \*\*kwargs: Optional arguments that ``request`` takes.:rtype: requests.Response"""kwargs.setdefault('allow_redirects', True)return self.request('GET', url, **kwargs)
(2)Post请求源码
def post(self, url, data=None, json=None, **kwargs):r"""Sends a POST request. Returns :class:`Response` object.:param url: URL for the new :class:`Request` object.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :class:`Request`.:param json: (optional) json to send in the body of the :class:`Request`.:param \*\*kwargs: Optional arguments that ``request`` takes.:rtype: requests.Response"""return self.request('POST', url, data=data, json=json, **kwargs)
(3)Delect请求源码
def delete(self, url, **kwargs):r"""Sends a DELETE request. Returns :class:`Response` object.:param url: URL for the new :class:`Request` object.:param \*\*kwargs: Optional arguments that ``request`` takes.:rtype: requests.Response"""return self.request('DELETE', url, **kwargs)
(4)分析结果
我们发现,不管是Get请求、还是Post请求或者是Delect请求,它们到最后返回的都是request函数。那么,我们再去看一看request函数的源码。
def request(self, method, url,params=None, data=None, headers=None, cookies=None, files=None,auth=None, timeout=None, allow_redirects=True, proxies=None,hooks=None, stream=None, verify=None, cert=None, json=None):"""Constructs a :class:`Request <Request>`, prepares it and sends it.Returns :class:`Response <Response>` object.:param method: method for the new :class:`Request` object.:param url: URL for the new :class:`Request` object.:param params: (optional) Dictionary or bytes to be sent in the querystring for the :class:`Request`.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :class:`Request`.:param json: (optional) json to send in the body of the:class:`Request`.:param headers: (optional) Dictionary of HTTP Headers to send with the:class:`Request`.:param cookies: (optional) Dict or CookieJar object to send with the:class:`Request`.:param files: (optional) Dictionary of ``'filename': file-like-objects``for multipart encoding upload.:param auth: (optional) Auth tuple or callable to enableBasic/Digest/Custom HTTP Auth.:param timeout: (optional) How long to wait for the server to senddata before giving up, as a float, or a :ref:`(connect timeout,read timeout) <timeouts>` tuple.:type timeout: float or tuple:param allow_redirects: (optional) Set to True by default.:type allow_redirects: bool:param proxies: (optional) Dictionary mapping protocol or protocol andhostname to the URL of the proxy.:param stream: (optional) whether to immediately download the responsecontent. Defaults to ``False``.:param verify: (optional) Either a boolean, in which case it controls whether we verifythe server's TLS certificate, or a string, in which case it must be a pathto a CA bundle to use. Defaults to ``True``.:param cert: (optional) if String, path to ssl client cert file (.pem).If Tuple, ('cert', 'key') pair.:rtype: requests.Response"""# Create the Request.req = Request(method=method.upper(),url=url,headers=headers,files=files,data=data or {},json=json,params=params or {},auth=auth,cookies=cookies,hooks=hooks,)prep = self.prepare_request(req)proxies = proxies or {}settings = self.merge_environment_settings(prep.url, proxies, stream, verify, cert)# Send the request.send_kwargs = {'timeout': timeout,'allow_redirects': allow_redirects,}send_kwargs.update(settings)resp = self.send(prep, **send_kwargs)return resp
从request源码可以看出,它先创建一个Request,然后将传过来的所有参数放在里面,再接着调用self.send(),并将Request传过去。这里我们将不在分析后面的send等方法的源码了,有兴趣的同学可以自行了解。
分析完源码之后发现,我们可以不需要单独在一个类中去定义Get、Post等其他方法,然后在单独调用request。其实,我们直接调用request即可。
2. requests请求封装
代码示例:
import requestsclass RequestMain:def __init__(self):"""session管理器requests.session(): 维持会话,跨请求的时候保存参数"""# 实例化sessionself.session = requests.session()def request_main(self, method, url, params=None, data=None, json=None, headers=None, **kwargs):""":param method: 请求方式:param url: 请求地址:param params: 字典或bytes,作为参数增加到url中 :param data: data类型传参,字典、字节序列或文件对象,作为Request的内容:param json: json传参,作为Request的内容:param headers: 请求头,字典:param kwargs: 若还有其他的参数,使用可变参数字典形式进行传递:return:"""# 对异常进行捕获try:"""封装request请求,将请求方法、请求地址,请求参数、请求头等信息入参。注 :verify: True/False,默认为True,认证SSL证书开关;cert: 本地SSL证书。如果不需要ssl认证,可将这两个入参去掉"""re_data = self.session.request(method, url, params=params, data=data, json=json, headers=headers, cert=(client_crt, client_key), verify=False, **kwargs)# 异常处理 报错显示具体信息except Exception as e:# 打印异常print("请求失败:{0}".format(e))# 返回响应结果return re_dataif __name__ == '__main__':# 请求地址url = '请求地址'# 请求参数payload = {"请求参数"}# 请求头header = {"headers"}# 实例化 RequestMain()re = RequestMain()# 调用request_main,并将参数传过去request_data = re.request_main("请求方式", url, json=payload, headers=header)# 打印响应结果print(request_data.text)
注 :如果你调的接口不需要SSL认证,可将cert与verify两个参数去掉。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:【文末领取】
【下面是我整理的2023年最全的软件测试工程师学习知识架构体系图+全套资料】
一、Python编程入门到精通
二、接口自动化项目实战
三、Web自动化项目实战
四、App自动化项目实战
五、一线大厂简历
六、测试开发DevOps体系
七、常用自动化测试工具
八、JMeter性能测试
九、总结(尾部小惊喜)
生命不息,奋斗不止。每一份努力都不会被辜负,只要坚持不懈,终究会有回报。珍惜时间,追求梦想。不忘初心,砥砺前行。你的未来,由你掌握!
生命短暂,时间宝贵,我们无法预知未来会发生什么,但我们可以掌握当下。珍惜每一天,努力奋斗,让自己变得更加强大和优秀。坚定信念,执着追求,成功终将属于你!
只有不断地挑战自己,才能不断地超越自己。坚持追求梦想,勇敢前行,你就会发现奋斗的过程是如此美好而值得。相信自己,你一定可以做到!