基于 python 的接口自动化测试,让你轻松掌握接口自动化

article/2025/8/29 11:51:59

目录

目录

一、简介

               ​编辑二、引言

三、环境准备

四、测试接口准备

接口信息

五、编写接口测试

六、优化

封装接口调用


 

一、简介


本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势;
然后简单讨论了一下接口测试框架的要点;
最后介绍了一下我们目前正在使用的接口测试框架 pithy。
期望读者可以通过本文对接口自动化测试有一个大致的了解。

               
二、引言


为什么要做接口自动化测试?
在当前互联网产品迭代频繁的背景下,回归测试的时间越来越少,很难在每个迭代都对所有功能做完整回归。
但接口自动化测试因其实现简单、维护成本低,容易提高覆盖率等特点,越来越受重视。

为什么要自己写框架呢?
使用 requets + unittest 很容易实现接口自动化测试,而且 requests 的api已经非常人性化,非常简单。
但通过封装以后(特别是针对公司内特定接口),再加上对一些常用工具的封装,可以进一步提高业务脚本编写效率。

三、环境准备


确保本机已安装 python2.7 以上版本,然后安装如下库:

pip install flask
pip install requests

后面我们会使用 flask 写一个用来测试的接口,使用requests去测试。

四、测试接口准备


下面使用 flask 实现两个 http 接口,一个登录,另外一个查询详情,但需要登录后才可以,新建一个 demo.py 文件(注意,不要使用windows记事本),把下面代码 copy 进去,然后保存、关闭。
接口代码

#!/usr/bin/python# coding=utf-8from flask import Flask, request, session, jsonifyUSERNAME = 'admin'PASSWORD = '123456'app = Flask(__name__)
app.secret_key = 'pithy'@app.route('/login', methods=['GET', 'POST'])def login():error = Noneif request.method == 'POST':        if request.form['username'] != USERNAME:error = 'Invalid username'elif request.form['password'] != PASSWORD:error = 'Invalid password'else:session['logged_in'] = Truereturn 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)

最后执行如下命令:

python demo.py

响应如下:

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

大家可以看到服务已经起来了。

接口信息

登录接口

  • 请求url
  • /login
  • 请求方法
    post
  • 请求参数
    | 参数名称 | 参数类型 | 参数说明 |
    | :————: | :——-: | :——: |
    | username | String | 登录名称 |
    | password | String | 登录密码 |
  • 响应信息
    | 参数名称 | 参数类型 | 参数说明 |
    | :————: | :——-: | :——: |
    | code | Integer | 结果code |
    | msg | String | 结果信息 |

详情接口

  • 请求url
    /info
     
  • 请求方法
    get
     
  • 请求 cookies
    | 参数名称 | 参数类型 | 参数说明 |
    | :————: | :——-: | :——: |
    | session | String | session |
     
  • 响应信息
    | 参数名称 | 参数类型 | 参数说明 |
    | :————: | :——-: | :——: |
    | code | Integer | 结果code |
    | msg | String | 结果信息 |
    | data | String | 数据信息 |

                        

五、编写接口测试


测试思路

  • 使用 requests库模拟发送 HTTP 请求。
  • 使用 python 标准库里 unittest 写测试 case。

脚本实现

#!/usr/bin/python# coding=utf-8import requestsimport unittestclass TestLogin(unittest.TestCase):@classmethoddef 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'] == 200assert response['msg'] == 'success'def test_info(self):"""测试info接口"""data = {            'username': self.username,            'password': self.password}response_cookies = requests.post(self.login_url, data=data).cookiessession = response_cookies.get('session')        assert sessioninfo_cookies = {            'session': session}response = requests.get(self.info_url, cookies=info_cookies).json()        assert response['code'] == 200assert response['msg'] == 'success'assert response['data'] == 'info'

六、优化

封装接口调用

写完这个测试登录脚本,你或许会发现,在整个项目的测试过程,登录可能不止用到一次,如果每次都这么写,会不会太冗余了?

对,确实太冗余了,下面做一下简单的封装,把登录接口的调用封装到一个方法里,把调用参数暴漏出来,示例脚本如下:

#!/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):@classmethoddef 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'] == 200assert response['msg'] == 'success'def test_info(self):"""测试获取详情信息"""cookies = self.app.get_cookies(self.username, self.password)response = self.app.info(cookies)        assert response['code'] == 200assert response['msg'] == 'success'assert response['data'] == 'info'

OK,在这一个版本中,我们不但在把登录接口的调用封装成了一个实例方法,实现了复用,而且还把 host(self.base_url)提取了出来。
但问题又来了,登录之后,登录接口的 http 响应会把 session 以 cookie 的形式 set 到客户端,之后的接口都会使用此 session 去请求。
还有,就是在接口调用过程中,希望可以把日志打印出来,以便调试或者出错时查看。
好吧,我们再来改一版。
保持 cookies &增加 log 信息
使用 requests 库里的同一个 Session 对象 (它也会在同一个 Session 实例发出的所有请求之间保持 cookie ),即可解决上面的问题,示例代码如下:

#!/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):@classmethoddef 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'] == 200assert response['msg'] == 'success'def test_info(self):"""测试获取详情信息"""self.app.login(self.username, self.password)response = self.app.info()        assert response['code'] == 200assert response['msg'] == 'success'assert response['data'] == 'info'

大功告成,我们把多个相关接口调用封装到一个类中,使用同一个 requests Session 实例来保持 cookies,并且在调用过程中打印出了日志,我们所有目标都实现了。
但再看下脚本,又会感觉不太舒服,在每个方法里,都要写一遍print 1、2、3… 要拼url、还要很多细节等等。
但其实我们 真正需要做的只是拼出关键的参数(url 参数、body 参数或者传入 headers 信息),可不可以只需定义必须的信息,然后把其它共性的东西都封装起来呢,统一放到一个地方去管理?

感谢每一个认真阅读我文章的人!!!

我个人整理了我这几年软件测试生涯整理的一些技术资料,包含:电子书,简历模块,各种工作模板,面试宝典,自学项目等。需要的点击下方名片加我VX与我一起学习交流。谢谢大家。


http://chatgpt.dhexx.cn/article/dNL3em6V.shtml

相关文章

接口自动化测试工程化——了解接口测试

什么是接口测试 接口测试也是一种功能测试 我理解的接口测试,其实也是一种功能测试,只是平时大家说的功能测试更多代指 UI 层面的功能测试,而接口测试更偏向于服务端层面的功能测试。 接口测试的目的 测试左移,尽早介入测试&#…

接口自动化测试【完整版】

1. 什么是接口测试 顾名思义,接口测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型,测试类型又主…

接口自动化测试

接口自动化测试 1.基础知识1.接口测试原理2.接口测试点及用例设计方法3.接口测试要点4.常见HTTP状态码5.HTTP基础知识6.接口自动化测试工具7.token 2.抓包工具1.chrom抓包2.Fiddler抓包(PC端,手机端)1.原理2.下载安装3.抓取数据信息说明&…

接口自动化测试(Python+Requests+Unittest)

(1)接口自动化测试的意义、前后端分离思想 接口自动化测试的优缺点: 优点: 测试复用性。 维护成本相对UI自动化低一些。 为什么UI自动化维护成本更高? 因为前端页面变化太快,而且UI自动化比较耗时(比如等待页面元素的…

接口自动化测试,一看就会

引言 与UI相比,接口一旦研发完成,通常变更或重构的频率和幅度相对较小。因此做接口自动化的性价比更高,通常运用于迭代版本上线前的回归测试中。 手工做接口测试,测试数据和参数都可以由测试人员手动填写和更新。 因此我们在考…

Pytorch损失函数(nn.L1Loss、nn.SmoothL1Loss、nn.MSELoss 、nn.CrossEntropyLoss、nn.NLLLoss)

文章目录 nn.L1Lossnn.SmoothL1Lossnn.MSELossnn.CrossEntropyLossnn.NLLLoss 损失函数,是编译一个神经网络模型必须的两个参数之一,另一个是优化器。损失函数是指用于计算标签值和预测值之间差异的函数,常见的有多种损失函数可供选择&#x…

链表L->next

2020/10/26更新 #include <iostream> using namespace std;struct MyStruct {int data 0;MyStruct* next; }; int main() {MyStruct* L;MyStruct head ,firstNode;head.data 1;firstNode.data 2;head.next &firstNode;L &head;cout << L->next-&g…

L多样化

为了解决同质性攻击和背景知识攻击所带来的隐私泄露&#xff0c;Machanavajjhala等人提出了L-多样性(l-diversity)模型。简单来说&#xff0c;就是在公开的数据中&#xff0c;每一个等价类里的敏感属性必须具有多样性&#xff0c;即L-多样性保证每一个等价类里&#xff0c;敏感…

L'Hospital法则

1.LHospital法则利用柯西中值定理证明 2.该法则适用f与g同时为无穷小量或g为无穷大量的情况 3.注意该法则只给出了充分不必要条件 今天我们介绍一种函数求极限的方法——LHospital法则。它主要用在求解"待定型"极限 1 首先阐述定理: 我们证明这个定理: 微分中值定理…

李沐老师 d2l库画图在 pycharm 动态显示问题(已解决)

修改 d2l.Animator 类的部分代码 1. 在 Animator 类中的 add() 方法中添加两行代码 plt.draw() plt.pause(0.001) 2. 在 Animator 添加 show() 方法 def show(self):display.display(self.fig) 3. 在需要显示的时候调用 animator.show() 结果

L298N——真正的玄学驱动板

总结 L298N 电机就是不转问题&#xff01;&#xff01;&#xff01; 目录 前言 1、共地问题 PWM 不能直接控制电机转动&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;别把PWM直接接电机&#xff01;&…

QMC5883L说明文档

个人博客&#xff1a;http://brainware360.cn/ QMC5883L源于Honeywell的HMC5883L&#xff0c;是一款表面贴装的集成了信号处理电路的三轴磁性传感器&#xff0c;应用场景主要包括罗盘、导航、无人机、机器人和手持设备等一些高精度的场合。 外形如下图所示&#xff1a; Figur…

安装 d2l

1.下载whl &#xff1a;https://www.cnpython.com/pypi/d2l/download 下载后放在哪个目录下都行 2.切换到刚刚下载的这个文件的所在目录&#xff0c;打开cmd 3.如上图标示&#xff0c;打开cmd&#xff0c;在cmd窗口中输入安装命令&#xff1a;pip install whl文件的名字 4.…

L298n

一时兴起&#xff0c;把之前的东西整一下。L298N资料&#xff08;非原创&#xff0c;贴出来便于日后查阅&#xff0c;或许能给给初学者一点帮助&#xff09;

L9110电机驱动电路

我需要设计一个驱动电路去驱动这样一个电机。电机的两个端子的输入波形如图&#xff1a; 驱动的波形为50%占空比的方波&#xff0c;频率为5Hz&#xff0c;额定电压12V。 单片机IO口可以输出3.3V/5V的PWM波&#xff0c;不过电压不够&#xff0c;驱动能力也不够&#xff0c;电机…

canon l11121e驱动_佳能L11121e驱动

佳能L11121e驱动可以帮助用户解决同型号打印机无法被电脑识别或者打印异常的问题&#xff0c;如果你在使用该型号打印机时遇到了上述问题&#xff0c;可以来本站下载使用该驱动&#xff0c;正确安装一下即可解决问题&#xff0c;让打印机恢复正常工作&#xff01; 佳能L11121e驱…

A2L文件介绍

文章目录 一、概述二、图2中不同块的意义如下&#xff1a;三、 A2L块示例补充知识参考文章 一、概述 A2L文件定义了标定过程中&#xff0c;上位机与ECU之间的通信所需的信息&#xff0c;可以是XCPonCAN&#xff0c;XCPonUSB、XCPonSPI等。 A2L标准分为三个部分&#xff0c;分别…

目标检测:损失函数之SmoothL1Loss

fasterRCNN中的RPN的回归框的loss计算方法 再次深入的解读SmoothL1Loss损失函数&#xff1a; fasterRCNN中SmoothL1Loss的详解

s905l android5,魔百盒CM201-1-YS-S905L纯净安卓系统固件包

魔百盒CM201-1-YS-S905L纯净安卓系统固件包是一个魔百盒易视腾YS代工魔百盒cm201-1免拆线刷固件系统纯净包&#xff0c;盒子是广东移动宽带定制的&#xff0c;其他地方只要硬件相同&#xff0c;应该也能够。不过还是提醒一句&#xff0c;刷机有风险&#xff0c;动手需谨慎。 固…

L1和L2简单易懂的理解

一、正则化&#xff08;Regularization&#xff09; 机器学习中几乎都可以看到损失函数后面会添加一个额外项&#xff0c;常用的额外项一般有两种&#xff0c;一般英文称作ℓ1ℓ1-norm和ℓ2ℓ2-norm&#xff0c;中文称作L1正则化和L2正则化&#xff0c;或者L1范数和L2范数。 L1…