什么是接口测试,我们如何实现接口测试?
1. 什么是接口测试
顾名思义,接口测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型,测试类型又主要分为功能测试,性能测试,稳定性测试,安全性测试等。
在分层测试的“金字塔”模型中,接口测试属于第二层服务集成测试范畴。相比UI层(主要是WEB或APP)自动化测试而言,接口自动化测试收益更大,且容易实现,维护成本低,有着更高的投入产出比,是每个公司开展自动化测试的首选。
下面我们以一个HTTP接口为例,完整的介绍接口自动化测试流程:从需求分析到用例设计,从脚本编写、测试执行到结果分析,并提供完整的用例设计及测试脚本。

2. 基本流程
基本的接口功能自动化测试流程如下:
需求分析 -> 用例设计 -> 脚本开发 -> 测试执行 -> 结果分析
2.1 示例接口
接口名称:豆瓣电影搜索
接口文档地址:https://developers.douban.com/wiki/?title=movie_v2#search
接口调用示例:
1) 按演职人员搜索:https://api.douban.com/v2/movie/search?q=张艺谋
2) 按片名搜索:https://api.douban.com/v2/movie/search?q=大话西游
3) 按类型搜索:https://api.douban.com/v2/movie/search?tag=喜剧
3. 需求分析
需求分析是参考需求、设计等文档,在了解需求的基础上还需清楚内部的实现逻辑,并且可以在这一阶段提出需求、设计存在的不合理或遗漏之处。
如:豆瓣电影搜索接口,我理解的需求即是支持对片名,演职人员及标签的搜索,并分页返回搜索结果。
4. 用例设计
用例设计是在理解接口测试需求的基础上,使用MindManager或XMind等思维导图软件编写测试用例设计,主要内容包括参数校验,功能校验、业务场景校验、安全性及性能校验等,常用的用例设计方法有等价类划分法,边界值分析法,场景分析法,因果图,正交表等。
针对豆瓣电影搜索接口功能测试部分,我们主要从参数校验,功能校验,业务场景校验三方面,设计测试用例如下:

5. 脚本开发
依据上面编写的测试用例设计,我们使用python+nosetests框架编写了相关自动化测试脚本。可以完整实现接口自动化测试、自动执行及邮件发送测试报告功能。
5.1 相关lib安装
必要的lib库如下,使用pip命令安装即可:
pip install nose
pip install nose-html-reporting
pip install requests
5.2 接口调用
使用requests库,我们可以很方便的编写上述接口调用方法(如搜索q=刘德华,示例代码如下):
#coding=utf-8
import requests
import jsonurl = 'https://api.douban.com/v2/movie/search'
params=dict(q=u'刘德华')
r = requests.get(url, params=params)
print 'Search Params:\n', json.dumps(params, ensure_ascii=False)
print 'Search Response:\n', json.dumps(r.json(), ensure_ascii=False, indent=4)
在实际编写自动化测试脚本时,我们需要进行一些封装。如下代码中我们对豆瓣电影搜索接口进行了封装,test_q方法只需使用nosetests提供的yield方法即可很方便的循环执行列表qs中每一个测试集:
class test_doubanSearch(object):@staticmethoddef search(params, expectNum=None):url = 'https://api.douban.com/v2/movie/search'r = requests.get(url, params=params)print 'Search Params:\n', json.dumps(params, ensure_ascii=False)print 'Search Response:\n', json.dumps(r.json(), ensure_ascii=False, indent=4)def test_q(self):# 校验搜索条件 qqs = [u'白夜追凶', u'大话西游', u'周星驰', u'张艺谋', u'周星驰,吴孟达', u'张艺谋,巩俐', u'周星驰,大话西游', u'白夜追凶,潘粤明']for q in qs:params = dict(q=q)f = partial(test_doubanSearch.search, params)f.description = json.dumps(params, ensure_ascii=False).encode('utf-8')yield (f,)
我们按照测试用例设计,依次编写每个功能的自动化测试脚本即可。
5.3 结果校验
在手工测试接口的时候,我们需要通过接口返回的结果判断本次测试是否通过,自动化测试也是如此。
对于本次的接口,我们搜索“q=刘德华”,我们需要判断返回的结果中是否含有“演职人员刘德华或片名刘德华”,搜索“tag=喜剧”时,需要判断返回的结果中电影类型是否为“喜剧”,结果分页时需要校验返回的结果数是否正确等。完整结果校验代码如下:
class check_response():@staticmethoddef check_result(response, params, expectNum=None):# 由于搜索结果存在模糊匹配的情况,这里简单处理只校验第一个返回结果的正确性if expectNum is not None:# 期望结果数目不为None时,只判断返回结果数目eq_(expectNum, len(response['subjects']), '{0}!={1}'.format(expectNum, len(response['subjects'])))else:if not response['subjects']:# 结果为空,直接返回失败assert Falseelse:# 结果不为空,校验第一个结果subject = response['subjects'][0]# 先校验搜索条件tagif params.get('tag'):for word in params['tag'].split(','):genres = subject['genres']ok_(word in genres, 'Check {0} failed!'.format(word.encode('utf-8')))# 再校验搜索条件qelif params.get('q'):# 依次判断片名,导演或演员中是否含有搜索词,任意一个含有则返回成功for word in params['q'].split(','):title = [subject['title']]casts = [i['name'] for i in subject['casts']]directors = [i['name'] for i in subject['directors']]total = title + casts + directorsok_(any(word.lower() in i.lower() for i in total),'Check {0} failed!'.format(word.encode('utf-8')))@staticmethoddef check_pageSize(response):# 判断分页结果数目是否正确count = response.get('count')start = response.get('start')total = response.get('total')diff = total - startif diff >= count:expectPageSize = countelif count > diff > 0:expectPageSize = diffelse:expectPageSize = 0eq_(expectPageSize, len(response['subjects']), '{0}!={1}'.format(expectPageSize, len(response['subjects'])))
5.4 执行测试
对于上述测试脚本,我们使用nosetests命令可以方便的运行自动化测试,并可使用nose-html-reporting插件生成html格式测试报告。
运行命令如下:
nosetests -v test_doubanSearch.py:test_doubanSearch --with-html --html-report=TestReport.html
5.5 发送邮件报告
测试完成之后,我们可以使用smtplib模块提供的方法发送html格式测试报告。基本流程是读取测试报告 -> 添加邮件内容及附件 -> 连接邮件服务器 -> 发送邮件 -> 退出,示例代码如下:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipartdef send_mail():# 读取测试报告内容with open(report_file, 'r') as f:content = f.read().decode('utf-8')msg = MIMEMultipart('mixed')# 添加邮件内容msg_html = MIMEText(content, 'html', 'utf-8')msg.attach(msg_html)# 添加附件msg_attachment = MIMEText(content, 'html', 'utf-8')msg_attachment["Content-Disposition"] = 'attachment; filename="{0}"'.format(report_file)msg.attach(msg_attachment)msg['Subject'] = mail_subjetmsg['From'] = mail_usermsg['To'] = ';'.join(mail_to)try:# 连接邮件服务器s = smtplib.SMTP(mail_host, 25)# 登陆s.login(mail_user, mail_pwd)# 发送邮件s.sendmail(mail_user, mail_to, msg.as_string())# 退出s.quit()except Exception as e:print "Exceptioin ", e
6. 结果分析
打开nosetests运行完成后生成的测试报告,可以看出本次测试共执行了51条测试用例,50条成功,1条失败。

失败的用例可以看到传入的参数是:{"count": -10, "tag": "喜剧"},此时返回的结果数与我们的期望结果不一致(count为负数时,期望结果是接口报错或使用默认值20,但实际返回的结果数目是189。赶紧去给豆瓣提bug啦- -)

7. 完整脚本
豆瓣电影搜索接口的完整自动化测试脚本,我已上传到的GitHub。下载地址:test_demo/test_douban at master · lovesoo/test_demo · GitHub
下载完成之后,使用如下命令即可进行完整的接口自动化测试并通过邮件发送最终的测试报告:
python test_doubanSearch.py
最终发送测试报告邮件,截图如下:

相关文章:
什么是接口测试,我们如何实现接口测试?
1. 什么是接口测试 顾名思义,接口测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型,测试类型又主…...
随机森林在sklearn中的实现
目录 一.集成算法 二.sklearn中的集成算法模块ensemble 三.RandomForestClassifier(随机森林分类器) 四.重要参数 1.基评估器参数 2.随机森林参数 五.重要属性和接口 六.Bagging的另一个必要条件 七.RandomForestRegressor(随机森林回归器) 八.机器学习中调参的基本思…...
[论文总结] 深度学习在农业领域应用论文笔记11
深度学习在农业上的应用笔记11 最近发表的相关论文数量不多,质量普遍也不尽如人意,尤其是《Computers and Electronics in Agriculture》这个期刊。这些论文的方法都很简单,只是强行将深度学习应用于某个问题上,而没有考虑到农业…...
Android 9.0 SystemUI 状态栏屏蔽弹出的悬浮式通知
1.概述 在9.0的系统ROM产品定制化开发中,在systemui的状态栏中,会在有闹钟 wifi连接等特殊弹窗通知的时候,会在接收到系统通知时,弹窗悬浮式弹窗通知,然后过几秒中, 就消失了,所以像这样的悬浮式通知,在有些产品中是不需要的,要求屏蔽掉,这就需要按照悬浮式流程来分析…...
商简智能计划与排程SPS在纺织行业中的应用
企业背景 某织造、染色及后整理一体化工艺的纺织面料企业,主要从事户外功能运动服装、内衣、泳衣、汽车内饰等面料的研发和销售,年产值在20亿左右,是迪卡侬运动面料最优质供应商之一。 纺织行业特点 印染具有典型的流程行业特性,…...
549、RocketMQ详细入门教程系列 -【消息队列之 RocketMQ(三)】 2023.02.28
目录一、Spring 整合 RocketMQ1.1 消息生产者1.2 消息消费者1.3 Spring 配置文件1.4 运行实例程序二、参考链接一、Spring 整合 RocketMQ 不同于 RabbitMQ、ActiveMQ、Kafka 等消息中间件,Spring 社区已经通过多种方式提供了对这些中间件产品集成,例如通…...
如何使用SpringBoot ⽇志?
Spring Boot自定义日志的打印:在一个类中先获取到打印日志对象(日志框架提供的日志对象,而日志框架默认已经集成到Spring Boot里了,springboot默认使用 slf4jlogback);注意:得到日志对象Logger ->来自于slf4j2、使用目志对象提…...
山东大学数字图像处理实验:MATLAB的图像显示方法
文章目录MATLAB 学习实验目的实验原理及方法实验内容MATLAB的图像显示方法实验目的实验内容MATLAB 学习 实验目的 了解 MATLAB 的基本功能及操作方法。掌握典型离散信号的 Matlab 产生和显示。 实验原理及方法 在 MATLAB 中, 序列是用矩阵向量表示, 但它没有包含采样信息, …...
Java缓存面试题——Redis解决方案
文章目录1、什么是缓存击穿?该如何解决2、什么是缓存穿透?该如何解决3、什么是缓存雪崩?该如何解决4、什么是BigKey?该如何解决bigkey的危害发现bigkey解决bigkey5、redis过期策略都有哪些?6、讲一讲Redis缓存的数据一…...
Flink:The generic type parameters of ‘Collector‘ are missing 类型擦除
类型擦除问题处理报错日志描述问题描述报错解决其他方法方法一:TypeInformation方法二:TypeHint报错日志描述 报错日志: The generic type parameters of Collector are missing. In many cases lambda methods dont provide enough informa…...
MySQL查询操作
系列文章目录前言一、简单查询SELECT子句SELECT后面之间跟列名DISTINCT,ALL列表达式列更名WHERE子句WHERE子句中可以使用的查询条件比较运算BETWEEN...AND...集合查询:IN模糊查询LIKE空值比较:IS NULL多重条件查询SELECT 的基本结构ORDER BY子句排序聚集…...
Redis-day01-note
Redis-day01-note 文章目录**Redis-day01-note****安装****配置文件详解****数据类型****字符串类型(string)**列表数据类型(List)****与python交互**Redis介绍特点及优点 1、开源的,使用C编写,基于内存且支持持久化 2、高性能的…...
嵌入式C基础知识(19)
时序在前面我们说到当处理器要向外设芯片写数据时,需要先将所需访问的外设的地址放在地址总线上,然后,由译码器将地址总线上的数据转换成片选信号,片选信号则使能目标外设芯片,接下来处理器写数据到数据总线上…...
java 2(程序流程控制)【含例题详解】
java ——程序流程控制 ✍作者:电子科大不知名程序员 🌲专栏:java学习指导 各位读者如果觉得博主写的不错,请诸位多多支持;如果有错误的地方,欢迎在评论区指出 目录java ——程序流程控制分支结构if-elsesw…...
基于Conda完成创建多版本python环境
文章目录基于Conda完成创建多版本python环境基于Conda完成创建多版本python环境 通过cmd打开conda环境 d:\ProgramData\Anaconda3\Scripts\activate创建python3.7的环境 conda create -n py3.7 python3.7产生错误 Collecting package metadata (repodata.json): failed Unav…...
35岁的测试被裁,公司地位还不如00后...
国内的互联网行业发展较快,所以造成了技术研发类员工工作强度比较大,同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高,超过35岁的基层研发类员工,往往因为家庭原因、身体原因,比较难以跟得上工作…...
vue H5跳转小程序报错:config:fail,Error: 系统错误,错误码:63002,invalid signature
微信开发者工具下载地址与更新日志 错误码:63002,invalid signature 无效的签名 附录5 微信网页开发 /JS-SDK说明文档 微信 JS 接口签名校验工具 全局返回码说明 排查步骤 确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sand…...
来面试阿里测开工程师,HR问我未来3-5年规划,我给HR画个大饼。
在面试的过程中是不是经常被面试官问未来几年的职业规划?你会答吗?是不是经常脑袋里一片空白,未来规划?我只是想赚更多的钱啊,哈哈哈,今天我来教大家,如何给面试官画一个大饼,让他吃的不亦乐乎…...
【2373. 矩阵中的局部最大值】
来源:力扣(LeetCode) 描述: 给你一个大小为 n x n 的整数矩阵 grid 。 生成一个大小为 (n - 2) x (n - 2) 的整数矩阵 maxLocal ,并满足: maxLocal[i][j] 等于 grid 中以 i 1 行和 j 1 列为中心的 3 …...
Read book Netty in action(Chapter VII)--ChannelHandler和ChannelPipeline
序言 我们曾经学过了ByteBuf – netty的数据容器,还有ChannelHandler和ChannelPipeline,这一把将他们组合起来,这些组件的交互正是Netty的灵魂所在! ChannelHanlder家族 在详细地学习ChannelHanlder之前,我们将在Ne…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
