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

在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 <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) <timeouts>` 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 <Response>` object
:rtype: requests.Response
    Usage::
      >>> import requests
      >>> req = requests.request('GET', 'https://httpbin.org/get')
      <Response [200]>
    """
# 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 <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  requests


class 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-8


import  pytest
import  yaml
import  os
import  requests
import  json


class 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"])

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

3293c1b9ac4915278ec153a194ed7c38.png

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

Python接口自动化测试实战 - 网易云课堂​study.163.com 《Python自动化测试实战》(无涯)【摘要 书评 试读】- 京东图书​item.jd.com Python测试与开发高薪特训班 - 网易云课堂​study.163.com


Python测试与开发高薪特训班 - 网易云课堂

b1381fe27c5424d77ffe20c8b18dfced.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值