pytest测试实战pdf_Pytest测试实战(十)

在Pytest测试实战系列中,上文将接口请求数据存储到yaml文件并利用参数化进行测试。本篇增加了对不同请求方法(如GET, POST)的处理,通过在yaml文件中定义method字段来区分请求类型。文章详细介绍了如何基于requests库的源码封装请求方法,并在测试代码中根据请求方法选择相应调用,确保测试覆盖。" 117139309,10540807,管理C语言环境下的TEMP文件夹,"['C语言', '系统管理', '注册表编辑', '环境变量', '文件清理']
摘要由CSDN通过智能技术生成

       在Pytest测试实战(九)里面,把接口请求的的请求地址,请求参数这些都存储到了yaml文件中,然后使用Pytest的参数化可以很轻松的实现几行代码就能够覆盖多个测试场景,关于测试场景的维护只需要在yaml文件中维护就可以了。下来需要思考的是在前面的文章体系中所有的请求都是GET的请求方法,但是请求方法除了GET还有POST等请求方法,所以在本文章中,加入对请求方法的处理机制,维护的yaml文件的内容为:

---#查看所有书籍信息"url": "http://localhost:5000/v1/api/books""method": "get""expect": '"name": "Python接口自动化测试实战"'---#创建书籍信息"url": "http://localhost:5000/v1/api/books""method": "post"dict1:"author": "无涯"  "done": true"name": "Python测试实战""expect": '"msg": "添加书籍成功", "status": 1002'---#查看id为1的书籍信息"url": "http://localhost:5000/v1/api/book/1""method": "get""expect": '"author": "wuya"'---#修改id为1的书籍信息"url": "http://localhost:5000/v1/api/book/1""method": "put"dict1:"author": "无涯"  "done": true"name": "Python测试实战""expect": '"msg": "更新书的信息成功", "status": 1008'---#删除id为1的书籍信息"url": "http://localhost:5000/v1/api/book/1""method": "delete""expect": '"msg": "删除书籍成功", "status": 1009'

在如上的yaml文件中可以看到我们刻意的增加了method的字段,通过它我们就很轻松的知道场景对应的请求方法是什么。

        下来需要思考的是对请求方法如何封装,在requests的库中,我们可以对request的方法进行二次封装和改造,首先来看源码部分,具体如下:

def request(method, url, **kwargs):"""Constructs and sends a :class:`Request `.    :param method: method for the new :class:`Request` object.    :param url: URL for the new :class:`Request` object.    :param params: (optional) Dictionary, list of tuples or bytes to send        in the body of the :class:`Request`.    :param data: (optional) Dictionary, list of tuples, bytes, or file-like        object to send in the body of the :class:`Request`.    :param json: (optional) A JSON serializable Python object 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 ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.        ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``        or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string        defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers        to add for the file.    :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.    :param timeout: (optional) How many seconds to wait for the server to send data        before giving up, as a float, or a :ref:`(connect timeout, read        timeout) ` tuple.    :type timeout: float or tuple    :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.    :type allow_redirects: bool    :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.    :param verify: (optional) Either a boolean, in which case it controls whether we verify            the server's TLS certificate, or a string, in which case it must be a path            to a CA bundle to use. Defaults to ``True``.    :param stream: (optional) if ``False``, the response content will be immediately downloaded.    :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.    :return: :class:`Response ` object    :rtype: requests.Response    Usage::      >>> import requests      >>> req = requests.request('GET', 'https://httpbin.org/get')          """    # By using the 'with' statement we are sure the session is closed, thus we    # avoid leaving sockets open which can trigger a ResourceWarning in some    # cases, and look like a memory leak in others.    with sessions.Session() as session:return session.request(method=method, url=url, **kwargs)

如上的代码是来源于requests库的源码,这部分代码非常的核心,它显示了在requests的请求中关于地址,方法,以及请求头等很多的信息,如json,data,params,verify,cookies的信息。其实在源码中不需要刻意的去关心GET和POST请求方法,因为它都是来自request的方法之上,GET方法的源码如下:

def get(url, params=None, **kwargs):r"""Sends a GET request.    :param url: URL for the new :class:`Request` object.    :param params: (optional) Dictionary, list of tuples or bytes to send        in the body of the :class:`Request`.    :param \*\*kwargs: Optional arguments that ``request`` takes.    :return: :class:`Response ` object    :rtype: requests.Response    """    kwargs.setdefault('allow_redirects', True)return request('get', url, params=params, **kwargs)

可以看到,在GET的方法中调用了request的方法,只不对针对GET请求又做了特殊的处理,那么**kwargs是什么,它可能是headers,也可能是cookie,verify的信息等信息。依据如上的信息,封装后的请求方法代码如下:

#!/usr/bin/python3

#coding:utf-8

#author:无涯

import requestsclass Request:def request(self,url,method='get',**kwargs):if method=='get':return requests.request(url=url,method=method,**kwargs)elif method=='post':return requests.request(url=url,method=method,**kwargs)elif method=='put':return requests.request(url=url,method=method,**kwargs)elif method=='delete':return requests.request(url=url,method=method,**kwargs)def get(self,url,**kwargs):return self.request(url=url,method='get',**kwargs)def post(self,url,**kwargs):return self.request(url=url,method='post',**kwargs)def put(self,url,**kwargs):return self.request(url=url,method='put',**kwargs)def delete(self,url,**kwargs):return self.request(url=url,method='delete',**kwargs)

     在前面两个步骤的基础上,下来在测试的代码中增加对请求方法的判断,如果是GET请求就去调用GET的请求方法,其他的也是如此,完整的代码如下:

#!/usr/bin/python3#coding:utf-8import  pytestimport  yamlimport  osimport  requestsimport  jsonclass Request:def request(self,url,method='get',**kwargs):if method=='get':return requests.request(url=url,method=method,**kwargs)elif method=='post':return requests.request(url=url,method=method,**kwargs)elif method=='put':return requests.request(url=url,method=method,**kwargs)elif method=='delete':return requests.request(url=url,method=method,**kwargs)def get(self,url,**kwargs):return self.request(url=url,method='get',**kwargs)def post(self,url,**kwargs):return self.request(url=url,method='post',**kwargs)def put(self,url,**kwargs):return self.request(url=url,method='put',**kwargs)def delete(self,url,**kwargs):return self.request(url=url,method='delete',**kwargs)def readYaml():with  open('config.yaml','r')  as f:return list(yaml.safe_load_all(f))@pytest.mark.parametrize('datas',readYaml())def test_books(datas):if datas['method']=='get':
r=Request().get(url=datas['url'])assert datas['expect'] in json.dumps(r.json(),ensure_ascii=False)elif datas['method']=='post':
r=Request().post(url=datas['url'],json=datas['dict1'])assert datas['expect'] in json.dumps(r.json(),ensure_ascii=False)elif datas['method']=='put':
r=Request().put(url=datas['url'],json=datas['dict1'])assert datas['expect'] in json.dumps(r.json(), ensure_ascii=False)elif datas['method']=='delete':
r=Request().delete(url=datas['url'])assert datas['expect'] in json.dumps(r.json(), ensure_ascii=False)if __name__ == '__main__':
pytest.main(["-v","-s","wxPytest.py"])

执行如上的代码,输出的结果信息如下:

2300d316aaf98e313d4fe9aaf6e9fc4a.png

    谢谢您的阅读和关注,后续会持续更新。您也可以购买本人出版的书籍和视频实战课程,谢谢!

1dc6f66c7104f836ac958e9739f16e2e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值