这篇文章主要介绍了简单几步教你学会Python接口自动化测试,本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势,期望读者可以通过本文对接口自动化测试有一个大致的了解,需要的朋友可以参考下
一、简介
本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势;
然后简单讨论了一下接口测试框架的要点;
最后介绍了一下我们目前正在使用的接口测试框架 pithy。
期望读者可以通过本文对接口自动化测试有一个大致的了解。
二、引言
为什么要做接口自动化测试?
在当前互联网产品迭代频繁的背景下,回归测试的时间越来越少,很难在每个迭代都对所有功能做完整回归。
但接口自动化测试因其实现简单、维护成本低,容易提高覆盖率等特点,越来越受重视。
为什么要自己写框架呢?
使用 requets + unittest 很容易实现接口自动化测试,而且 requests 的api已经非常人性化,非常简单。
但通过封装以后(特别是针对公司内特定接口),再加上对一些常用工具的封装,可以进一步提高业务脚本编写效率。
三、环境准备
确保本机已安装 python2.7 以上版本,然后安装如下库:
1 |
pip install flaskpip install requests |
后面我们会使用 flask 写一个用来测试的接口,使用requests去测试。
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036
四、测试接口准备
下面使用 flask 实现两个 http 接口,一个登录,另外一个查询详情,但需要登录后才可以,新建一个 demo.py 文件(注意,不要使用windows记事本),把下面代码 copy 进去,然后保存、关闭。
接口代码
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 !!' }) return jsonify({ 'code' : 200 , 'msg' : 'success' , 'data' : 'info' }) if __name__ = = '__main__' : app.run(debug = True ) |
最后执行如下命令:
响应如下:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with sta
大家可以看到服务已经起来了。
登录接口
/login
post
| 参数名称 | 参数类型 | 参数说明 |
| :————: | :——-: | :——: |
| username | String | 登录名称 |
| password | String | 登录密码 |
| 参数名称 | 参数类型 | 参数说明 |
| :————: | :——-: | :——: |
| code | Integer | 结果code |
| msg | String | 结果信息 |
详情接口
/info
get
| 参数名称 | 参数类型 | 参数说明 |
| :————: | :——-: | :——: |
| session | String | session |
| 参数名称 | 参数类型 | 参数说明 |
| :————: | :——-: | :——: |
| code | Integer | 结果code |
| msg | String | 结果信息 |
| data | String | 数据信息 |
五、编写接口测试
测试思路
- 使用 requests库模拟发送 HTTP 请求。
- 使用 python 标准库里 unittest 写测试 case。
脚本实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 ): """ 测试登录 """ 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' |
六、优化
封装接口调用
写完这个测试登录脚本,你或许会发现,在整个项目的测试过程,登录可能不止用到一次,如果每次都这么写,会不会太冗余了?
对,确实太冗余了,下面做一下简单的封装,把登录接口的调用封装到一个方法里,把调用参数暴漏出来,示例脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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): """ 登录接口 :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,在这一个版本中,我们不但在把登录接口的调用封装成了一个实例方法,实现了复用,而且还把 host(self.base_url)提取了出来。
但问题又来了,登录之后,登录接口的 http 响应会把 session 以 cookie 的形式 set 到客户端,之后的接口都会使用此 session 去请求。
还有,就是在接口调用过程中,希望可以把日志打印出来,以便调试或者出错时查看。
好吧,我们再来改一版。
保持 cookies &增加 log 信息
使用 requests 库里的同一个 Session 对象 (它也会在同一个 Session 实例发出的所有请求之间保持 cookie ),即可解决上面的问题,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 # 创建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' |
大功告成,我们把多个相关接口调用封装到一个类中,使用同一个 requests Session 实例来保持 cookies,并且在调用过程中打印出了日志,我们所有目标都实现了。
但再看下脚本,又会感觉不太舒服,在每个方法里,都要写一遍print 1、2、3… 要拼url、还要很多细节等等。
但其实我们 真正需要做的只是拼出关键的参数(url 参数、body 参数或者传入 headers 信息),可不可以只需定义必须的信息,然后把其它共性的东西都封装起来呢,统一放到一个地方去管理?
到此这篇关于简单几步教你学会Python接口自动化测试的文章就介绍到这了!
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。