Interface automation testing based on python, the simplest and most practical teaching!

1. Introduction

This article starts with a simple login interface test, and adjusts and optimizes the interface calling posture step by step;
then briefly discusses the key points of the interface testing framework;
and finally introduces pity, the interface testing framework we are currently using.
It is hoped that readers can have a general understanding of interface automation testing through this article.

2. Introduction

Why do we need to do interface automation testing?

In the current context of frequent iterations of Internet products, the time for regression testing is getting less and less, and it is difficult to complete regression of all functions in every iteration.

However, interface automated testing has attracted more and more attention due to its simple implementation, low maintenance cost, and easy improvement of coverage.

Why write the framework yourself?

It is easy to implement automated interface testing using requests + unittest, and the requests API is very user-friendly and simple.

However, through encapsulation (especially for specific interfaces within the company) and the encapsulation of some common tools, the efficiency of business script writing can be further improved.

3. Environmental preparation

Make sure that python2.7 or above is installed on this machine, and then install the following libraries:

pip install flask
pip install requests

Later we will use flask to write an interface for testing and use requests to test.

现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036

 

4. Test interface preparation

Below, we use flask to implement two http interfaces, one for logging in and the other for querying details, but only after logging in. Create a new demo.py file (note, do not use Windows Notepad), copy the following code into it, and then save and close it. .

Interface code

#!/usr/bin/python# coding=utf-8from flask import Flask, request, session, jsonify
 
USERNAME = 'admin'PASSWORD = '123456'app = Flask(__name__)
app.secret_key = 'pithy'@app.route('/login', methods=['GET', 'POST'])def login():
    error = None
    if request.method == 'POST':        if request.form['username'] != USERNAME:
            error = 'Invalid username'
        elif request.form['password'] != PASSWORD:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            return jsonify({'code': 200, 'msg': 'success'})    return jsonify({'code': 401, 'msg': error}), [email protected]('/info', methods=['get'])def info():
    if not session.get('logged_in'):        return jsonify({'code': 401, 'msg': 'please login !!'})    return jsonify({'code': 200, 'msg': 'success', 'data': 'info'})if __name__ == '__main__':
    app.run(debug=True)

Finally execute the following command:

python demo.py

The response is as follows:

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with sta

As you can see, the service has started.

Interface information

Login interface

request url

/login

Request method

post

Request parameters

| Parameter name | Parameter type | Parameter description |

| :————: | :——-: | :——: |

| username | String | Login name |

| password | String | Login password |

response message

| Parameter name | Parameter type | Parameter description |

| :————: | :——-: | :——: |

| code | Integer | result code |

| msg | String | Result information |

Details interface

request url

/info

Request method

get

request cookies

| Parameter name | Parameter type | Parameter description |

| :————: | :——-: | :——: |

| session | String | session |

response message

| Parameter name | Parameter type | Parameter description |

| :————: | :——-: | :——: |

| code | Integer | result code |

| msg | String | Result information |

| data | String | data information |

5. Write interface tests


Test ideas

  • Use the requests library to simulate sending HTTP requests.
  • Use unittest in the Python standard library to write test cases.

Script implementation

#!/usr/bin/python# coding=utf-8import requestsimport unittestclass TestLogin(unittest.TestCase):
 
    @classmethod
    def setUpClass(cls):
        cls.login_url = 'http://127.0.0.1:5000/login'
        cls.info_url = 'http://127.0.0.1:5000/info'
        cls.username = 'admin'
        cls.password = '123456'
 
    def test_login(self):
        """
        测试登录
        """
        data = {            'username': self.username,            'password': self.password
        }
 
        response = requests.post(self.login_url, data=data).json()        assert response['code'] == 200
        assert response['msg'] == 'success'
 
    def test_info(self):
        """
        测试info接口
        """
 
        data = {            'username': self.username,            'password': self.password
        }
 
        response_cookies = requests.post(self.login_url, data=data).cookies
        session = response_cookies.get('session')        assert session
 
        info_cookies = {            'session': session
        }
 
        response = requests.get(self.info_url, cookies=info_cookies).json()        assert response['code'] == 200
        assert response['msg'] == 'success'
        assert response['data'] == 'info'

6. Optimization

Encapsulated interface call

After writing this test login script, you may find that login may be used more than once during the entire project testing process. Would it be too redundant if written like this every time?

Yes, it is indeed too redundant. Let’s do a simple encapsulation, encapsulate the login interface call into a method, and expose the call parameters. The sample script is as follows:

#!/usr/bin/python# coding=utf-8import requestsimport unittesttry:    from urlparse import urljoinexcept ImportError:    from urllib.parse import urljoinclass DemoApi(object):
 
    def __init__(self, base_url):
        self.base_url = base_url    def login(self, username, password):
        """
        登录接口
        :param username: 用户名
        :param password: 密码
        """
        url = urljoin(self.base_url, 'login')
        data = {            'username': username,            'password': password
        }        return requests.post(url, data=data).json()    def get_cookies(self, username, password):
        """
        获取登录cookies
        """
        url = urljoin(self.base_url, 'login')
        data = {            'username': username,            'password': password
        }        return requests.post(url, data=data).cookies    def info(self, cookies):
        """
        详情接口
        """
        url = urljoin(self.base_url, 'info')        return requests.get(url, cookies=cookies).json()class TestLogin(unittest.TestCase):
 
    @classmethod
    def setUpClass(cls):
        cls.base_url = 'http://127.0.0.1:5000'
        cls.username = 'admin'
        cls.password = '123456'
        cls.app = DemoApi(cls.base_url)    def test_login(self):
        """
        测试登录
        """
        response = self.app.login(self.username, self.password)        assert response['code'] == 200
        assert response['msg'] == 'success'
 
    def test_info(self):
        """
        测试获取详情信息
        """
        cookies = self.app.get_cookies(self.username, self.password)
        response = self.app.info(cookies)        assert response['code'] == 200
        assert response['msg'] == 'success'
        assert response['data'] == 'info'

OK, in this version, we not only encapsulate the login interface call into an instance method to achieve reuse, but also extract the host (self.base_url).

But the problem comes again. After logging in, the http response of the login interface will set the session to the client in the form of a cookie, and subsequent interfaces will use this session to make requests.

Also, during the interface calling process, I hope that the log can be printed out for debugging or viewing when an error occurs.

Okay, let's do another version.

Keep cookies & add log information

Using the same Session object in the requests library (it will also maintain cookies between all requests issued by the same Session instance), you can solve the above problem. The sample code is as follows:

#!/usr/bin/python# coding=utf-8import unittestfrom pprint import pprintfrom requests.sessions import Sessiontry:    from urlparse import urljoinexcept ImportError:    from urllib.parse import urljoinclass DemoApi(object):
 
    def __init__(self, base_url):
        self.base_url = base_url        # 创建session实例
        self.session = Session()    def login(self, username, password):
        """
        登录接口
        :param username: 用户名
        :param password: 密码
        """
        url = urljoin(self.base_url, 'login')
        data = {            'username': username,            'password': password
        }
 
        response = self.session.post(url, data=data).json()
        print('\n*****************************************')
        print(u'\n1、请求url: \n%s' % url)
        print(u'\n2、请求头信息:')
        pprint(self.session.headers)
        print(u'\n3、请求参数:')
        pprint(data)
        print(u'\n4、响应:')
        pprint(response)        return response    def info(self):
        """
        详情接口
        """
        url = urljoin(self.base_url, 'info')
        response = self.session.get(url).json()
 
        print('\n*****************************************')
        print(u'\n1、请求url: \n%s' % url)
        print(u'\n2、请求头信息:')
        pprint(self.session.headers)
        print(u'\n3、请求cookies:')
        pprint(dict(self.session.cookies))
        print(u'\n4、响应:')
        pprint(response)        return responseclass TestLogin(unittest.TestCase):
 
    @classmethod
    def setUpClass(cls):
        cls.base_url = 'http://127.0.0.1:5000'
        cls.username = 'admin'
        cls.password = '123456'
        cls.app = DemoApi(cls.base_url)    def test_login(self):
        """
        测试登录
        """
        response = self.app.login(self.username, self.password)        assert response['code'] == 200
        assert response['msg'] == 'success'
 
    def test_info(self):
        """
        测试获取详情信息
        """
        self.app.login(self.username, self.password)
        response = self.app.info()        assert response['code'] == 200
        assert response['msg'] == 'success'
        assert response['data'] == 'info'

We're done. We encapsulated multiple related interface calls into a class, used the same requests Session instance to hold cookies, and printed out logs during the call. All our goals were achieved.

But if you look at the script again, you will feel uncomfortable. In each method, you have to write print 1, 2, 3... You need to spell the url, and there are a lot of details, etc.

But in fact, what we really need to do is to spell out the key parameters (url parameters, body parameters or incoming headers information). Can we just define the necessary information, and then encapsulate other common things and put them into one Where to manage?

Finally, I would like to thank everyone who read my article carefully. Looking at the increase in fans and attention, there is always some courtesy. Although it is not a very valuable thing, if you can use it, you can take it directly!

Software Testing Interview Document

We must study to find a high-paying job. The following interview questions are from the latest interview materials from first-tier Internet companies such as Alibaba, Tencent, Byte, etc., and some Byte bosses have given authoritative answers. After finishing this set I believe everyone can find a satisfactory job based on the interview information.
 

Insert image description here

Guess you like

Origin blog.csdn.net/jiangjunsss/article/details/133048290