Analysis of Python Interface Automation Principle of requests Request Encapsulation

  • 2021-11-24 01:58:07
  • OfStack

Directory below mainly introduces how to encapsulate the request the commonly used get, post request encapsulated get request source code: post request source code: to study the next request source code: directly call request function

In the last Python interface automation test series articles: Python interface automation analysis Token application principle, introduced token basic concept, operation principle and how to carry token interface to access in automation.

The following mainly describes how to encapsulate requests

Remember the get request and post request we wrote before?

Everyone should realize that each request type is written as a separate function, and the code reusability is not strong.

Next, all request types are encapsulated, and all automation use cases can request with this encapsulated request class

Encapsulate the commonly used get and post requests


import requests
class RequestHandler:
    def get(self, url, **kwargs):
        """ Encapsulation get Method """
        #  Get request parameters 
        params = kwargs.get("params")
        headers = kwargs.get("headers")
        try:
            result = requests.get(url, params=params, headers=headers)
            return result
        except Exception as e:
            print("get Request error : %s" % e)
    def post(self, url, **kwargs):
        """ Encapsulation post Method """
        #  Get request parameters 
        params = kwargs.get("params")
        data = kwargs.get("data")
        json = kwargs.get("json")
        try:
            result = requests.post(url, params=params, data=data, json=json)
            return result
        except Exception as e:
            print("post Request error : %s" % e)
    def run_main(self, method, **kwargs):
        """
         Determine the request type 
        :param method:  Request interface type 
        :param kwargs:  Optional parameters 
        :return:  Interface returns content 
        """
        if method == 'get':
            result = self.get(**kwargs)
            return result
        elif method == 'post':
            result = self.post(**kwargs)
            return result
        else:
            print(' Wrong request interface type ')
if __name__ == '__main__':
    #  Here's the test code 
    # get Request interface 
    url = 'https://api.apiopen.top/getJoke?page=1&count=2&type=video'
    res = RequestHandler().get(url)
    # post Request interface 
    url2 = 'http://127.0.0.1:8000/user/login/'
    payload = {
        "username": "vivi",
        "password": "123456"
    }
    res2 = RequestHandler().post(url2,json=payload)
    print(res.json())
    print(res2.json())

The result of the request is as follows:


'message': ' Success !', 
'result': [{'sid': '31004305',
'text': ' Sheep: Master, get a haircut and trim it a little 1 Just get down ', 
'type': 'video',
'thumbnail': 'http://wimg.spriteapp.cn/picture/2020/0410/5e8fbf227c7f3_wpd.jpg', 
'video': 'http://uvideo.spriteapp.cn/video/2020/0410/5e8fbf227c7f3_wpd.mp4',
'images': None, 
'up': '95',
'down': '1', 
'forward': '0', 
'comment': '25', 
'uid': '23189193', 
'name': ' Qingchuan canoe ', 
'header': 'http://wimg.spriteapp.cn/profile/large/2019/12/24/5e01934bb01b5_mini.jpg', 
'top_comments_content':None, 
'top_comments_voiceuri': None,
'top_comments_uid': None, 
'top_comments_name': None,
'top_comments_header': None, 
'passtime': '2020-04-12 01:43:02'},
{'sid': '30559863', 
'text': ' Robot girlfriend, except that she can't have children, she can do anything else, and the price 239000 Yuan ',
'type': 'video', 
'thumbnail': 'http://wimg.spriteapp.cn/picture/2020/0306/5e61a41172a1b_wpd.jpg',
'video': 'http://uvideo.spriteapp.cn/video/2020/0306/5e61a41172a1b_wpd.mp4', 
'images': None, 'up': '80', 'down': '6',
'forward': '3',
'comment': '20', 
'uid': '23131273', 
'name': ' Follow the course ',
'header': 'http://wimg.spriteapp.cn/profile/large/2019/07/04/5d1d90349cd1a_mini.jpg', 
'top_comments_content': ' A show for the game ', 
'top_comments_voiceuri': '',
'top_comments_uid': '10250040', 
'top_comments_name': ' No sister user ', 
'top_comments_header': 'http://wimg.spriteapp.cn/profile',
'passtime': '2020-04-11 20:43:49'}]}
{'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4NTc0MzcsImVtYWlsIjoidml2aUBxcS5jb20ifQ.k6y0dAfNU2o9Hd9LFfxEk1HKgczlQfUaKE-imPfTsm4', 
'user_id': 1,
 'username': 'vivi'}

Is this perfect? no, no, no.

The pain points of the above code are as follows:

Large amount of code: only encapsulated get, post requests, plus other request types, large amount of code;

Lack of session management: How to maintain session state between requests.

Let's review the source code of get, post and other requests to see if there are any characteristics.

get request source code:


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 query string for 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)

post request source code:


def post(url, data=None, json=None, **kwargs):
    r"""Sends a POST request.
    :param url: URL for the new :class:`Request` object.
    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
        object to send in the body of the :class:`Request`.
    :param json: (optional) json data to send in the body of the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """
    return request('post', url, data=data, json=json, **kwargs)
 

After careful study, it is found that get and post requests return request functions.

Let's study the source code of request again:


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 query string for 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)

The source code looks very long, but it only has 3 lines, most of which are code comments.

As you can see from the source code, whether it is get or post or other request types, the request function is ultimately called.

In this case, instead of defining get method and post method in the class as before, we can define a general method

Call the request function directly

It looks a little round, so it is clear to implement it in code.


import requests
class RequestHandler:
    def __init__(self):
        """session Manager """
        self.session = requests.session()
    def visit(self, method, url, params=None, data=None, json=None, headers=None, **kwargs):
        return self.session.request(method,url, params=params, data=data, json=json, headers=headers,**kwargs)
    def close_session(self):
        """ Shut down session"""
        self.session.close()
if __name__ == '__main__':
    #  Here's the test code 
    # post Request interface 
    url = 'http://127.0.0.1:8000/user/login/'
    payload = {
        "username": "vivi",
        "password": "123456"
    }
    req = RequestHandler()
    login_res = req.visit("post", url, json=payload)
    print(login_res.text)

Response result:


{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4Njk3ODQsImVtYWlsIjoidml2aUBxcS5jb20ifQ.OD4HIv8G0HZ_RCk-GTVAZ9ADRjwqr3o0E32CC_2JMLg",
    "user_id": 1,
    "username": "vivi"
}

This request package is simple and practical, and of course, small partners can package themselves according to their own needs.

The above is Python interface automation analysis requests request encapsulation principle details, more about Python interface automation requests request encapsulation information please pay attention to other related articles on this site!


Related articles: