Teach you how to automate Python interface testing in a few simple steps

This article mainly introduces a few simple steps to teach you how to test Python interface automation. This article starts with a simple login interface test, and adjusts and optimizes the interface calling posture step by step. It is hoped that readers can have a general understanding of interface automation testing through this article. Friends in need can refer to it

1. Introduction

This article starts with a simple login interface test, and adjusts and optimizes the interface calling posture step by step;

Then we briefly discussed the key points of the interface testing framework;

Finally, we introduce the interface testing framework Pithy 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 requets + unittest, and the API of requests is already very user-friendly and very 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. Environment preparation

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

1

pip install flaskpip install requests

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

Now I have also found a lot of test friends and created a communication group to share technology, sharing a lot of technical documents and video tutorials we collected.
If you don’t want to experience the feeling of not being able to find resources when self-study, having no one to answer your questions, and persisting for a few days before giving up.
You can join us to communicate. And there are many technical experts who have made certain achievements in automation, performance, security, test development, etc.
Share their experience, and also share many live lectures and technical salons
You can learn for free! Focus on it! Open source! ! !
QQ group number: 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

1

2

3

4

5

6

7

8

9

10

11

12

13

#!/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}), 401@app.route( '/info', methods=['get' ])def info():

if not session.get('logged_in'): return jsonify({'code': 401 , 'msg': 'please login!!'}) code>return jsonify({'code': 200, 'msg': 'success', 'data': 'info'})if __name__ == '__main__':

app.run(debug=True)

Finally execute the following command:

1

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 |

Detail 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. Writing 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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

25

26

27

28

#!/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):

"""

Test login

"""

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):

"""

Test info interface

"""

data = { 'username': self.username, 'password': self.password

}

response_cookies = requests.post(self.login_url, data=data).cookies

session = response_cookies.get('session') code>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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

#!/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):

"""

Login interface

:param username: username

:param password: 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):

"""

Get login cookies

"""

url = urljoin(self.base_url, 'login')

data = { 'username': username, 'password': password

} return requests.post(url, data=data) .cookies def info(self, cookies):

"""

Details interface

"""

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):

"""

Test login

"""

response = self.app.login(self.username, self.password) assert response[' code'] == 200

assert response['msg'] = = 'success'

def test_info(self):

"""

Test to obtain detailed information

"""

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

#!/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 # Create session instance

self.session = Session() def login(self, username, password):

"""

Login interface

:param username: username

:param password: password

"""

url = urljoin(self.base_url, 'login')

data = { 'username': username, 'password': password

}

response = self.session.post(url, data= data).json()

print('\
************************ ************************'
)

print(u'\
1. Request url: \
%s'
% url)

print(u'\
2. Request header information:'
)

pprint(self.session.headers)

print(u'\
3. Request parameters:'
)

pprint(data)

print(u'\
4, response:'
)

pprint(response) return response def info(self):

"""

Details interface

"""

url = urljoin(self.base_url, 'info')

response = self.session.get(url).json()

print('\
********************** ************************'
)

print(u'\
1. Request url: \
%s'
% url)

print(u'\
2. Request header information:'
)

pprint(self.session.headers)

print(u'\
3. Request cookies:'
)

pprint(dict(self.session.cookies))

print(u'\
4, response:'
)

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):

"""

Test login

"""

response = self.app.login(self.username, self.password) assert response[' code'] == 200

assert response['msg'] = = 'success'

def test_info(self):

"""

Test to obtain detailed information

"""

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 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?

That’s it for this article about teaching you how to automate Python interface testing in a few simple steps!

Finally, I would like to thank everyone who has 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 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.

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Python entry skill treeWeb crawlerSelenium388009 people are learning the system