基于py3从0到接口自动化测试应用系列(1)
写在前面的话
希望这些文章可以
- 帮助有一点代码基础的测试伙伴独立动手搭建一套完整、高效、可读性好、便于维护的接口自动化系统
- 帮助给出一些在自动化过程中因环境,业务,甚至人员配合等原因造成阻力的解决方案
- 回顾总结整个项目过程,帮助自己更好的对它进行优化和扩展
自卖自夸
- 目前这套系统已维护一家中大型互联网企业核心交易线服务1年半时间,累计用例数量2万条,覆盖率在85%以上,质量保障效果显著
- 在业务项目中不断演进优化,在脚本输出效率,代码覆盖率以及应对常见的开发设计模式都有较好的表现(非平台)
- 开发都觉得好才是真的好!!!
一套东西不可能应对所有情况,但也希望对大家有所帮助,废话不多数,开始。
准备篇
当我们做任何新产品测试时候,第一件事情就是要先认识被测体,接口测试也一样。
认识接口
什么是接口
接口的标准定义这里就不赘述了,那我们通常测试的接口是什么?举个例子,当我们点击打开一个商品页面时,客户端需要调用==商品详情接口==,目的是希望通过这个接口告诉服务端商品的ID(即唯一标识)并要求服务端返回这个商品的详细信息,这就是我们最长提到的接口
sequenceDiagram
客户端->>服务端: 商品A
服务端->>客户端: 商品A的详细信息
接口的组成
我们知道接口有很多概念包括:http接口、api接口、RPC接口、RMI、webservice、Restful等,下面以我们最常见的http接口为例,如果我们把一个接口看成一个对象那么它主要包含如下属性
class RequestUtil(object):
"""
接口基础类
"""
def __init__(self):
self.host = None # 域名:http://my-api-test.com
self.uri = None # /mydemo
self.url = None
# url host+uri+param
self.info = None # 接口描述
self.method = None # 请求方式 post get put等等
self.body = None
# 请求参数体 例如
{"product_id": 123456}
self.param = None
# get请求参数 例如 product_id=123456
self.resp = None
# 返回结果,例如
{"product_name":'abc',"price":5.11}
self.is_sign = None # 签名
self.key_token = None # token
self.headers = headers
# 请求头 例如
{'Content-Type': 'application/json'}
self.status = 0 # 期望的接口返回结果中代表失败、成功状值
self.success_status = 0 # 接口成功时的status值
self.http_status = 200 # http返回码
self.timeout = 15 # 最大超时时间
self.mock_info = BaseObj() # 如果接口中需要mock的话,存放mock信息
def send_request():
"""发送请求,使用requests库来实现该功能"""
pass
可以看到上面已经生成的我们接口最基础的类,包含了我们后续需要用到的所有属性,并且它还应该包含一个重要的功能就是组织好这些属性然后发送请求并记录请求的所有数据,这里使用的是requests库来实现这个功能。
如何获取接口结构
通常我们会根据每个公司不同的情况按照优先级从高到低排序有如下获取方式:
方式 | 推荐指数 | 推荐原因 |
---|---|---|
swagger | ⭐️⭐️⭐️ | 更新及时;输出格式统一,适合和脚本结合动态生成测试数据;比较主流; |
wiki | ⭐️⭐️ | 可规范输出格式;可对接口做更详细的描述; |
抓包工具 | ⭐️ | 不推荐,看不到完整接口结构,不能作为测试标准;另外到能抓包的时候才去生成接口数据时间上太晚; |
推动开发提供以上文档推荐直接接swagger,可以要求开发将参数是否必填和描述等信息写在会用到的参数后面,以此来弥补没有wiki的部分,这样我们解析拉出的脚本中参数就都有具体的描述信息了,非常方便,如下图中内容就是直接从swagger页面解析的脚本
# 以下代码从swagger拉取生成,可从swagger重新拉取更新
from common.objects import BaseObj
from ..__init__ import *
class MyServiceBaseDemoApi(BaseServiceDemo):
"""接口对象"""
def __init__(self, **kwargs):
super(MyServiceBaseDemoApi, self).__init__()
self.info = "my demo接口例子"
self.uri = "mydemo"
self.method = "post"
self.body = self.Body(**kwargs)
self.resp = self.Resp()
class Body(BaseObj):
def __init__(self, **kwargs):
self.name = None # 必填,用户姓名
self.age = None # 非必填,用户年龄
self.phone_num = None # 必填,用户手机号码 必填,用户手机号码
BaseObj.__init__(self, **kwargs)
class Resp(object):
def __init__(self):
super(MyServiceBaseDemoApi.Resp, self).__init__()
self.status = None # None
self.msg = None # 公司ID
self.data = self.Items() # 公司ID
class Items(object):
def __init__(self):
self.name = None
self.age = None
熟悉被测服务
除了认识单个的接口,我们还需要了解被测服务的架构以及该服务是如何和其他服务或客户端进行数据交换来完成产品的部分功能,举个例子:在交易流程中通常会包括以下几个服务
这快信息可以直接从开发那边获取,通常开发会有类似的业务架构图,只有了解了这快我们才可以比较准确的来制定相关项目的测试方案,避免漏测,错测。
熟悉一门语言
目前我使用的是python3,当然你们也可以选择java或者其他合适的语言,虽然语言不同,但很多思路和解决问题的方式都是互通的;以python为例,应用要求至少能熟悉到python对象的处理,具体语法这里就不赘述了,百度一下很多,自己比较推荐廖雪峰的python教程,因为比较容易入手。
了解相关依赖库
后面会主要用到以下依赖库,可以提前了解下基本的功能和调用方式
peewee>=2.10.2 # 数据库orm
peewee-mssql>=0.1.2
pymysql # mysql
redis>=2.10.6 # mock部分的key会存储在redis中
requests>=2.18.4 # http请求的发送,也可以使用aiohttp或其他类似库替换
selenium>=3.8.0 # 接口和ui自动化结合时候可能会需要用到
threadpool>=1.3.2 # 业务并发
pytest=4.3.1 # 自动化测试框架,也可以选择其他类似框架
pytest-html # pytest生成报告插件
parameterized # 参数化用例需要使用到
常见接口测试方案
抛开业务,广义上我们主要用到两种测试方案
方向 | 方案 |
---|---|
用例方向 | 1.单接口测试;2.多接口串流测试 |
断言部分 | 1.新老服务对比结果;2.根据业务逻辑计算期望结果和实际结果做对比; |
用例方面:
- 推荐大部分接口尽量都需要有单接口或短流程的测试用例;
- 流程型较强的业务例如拼团等,必须要加入全流程串流测试;
结果检查:
- 重构,分库分表等其他不改变业务逻辑的技术型项目非常适合新老服务接口对比测试。==优势==:脚本无需自行生成期望结果,只需对应新老结果即可,脚本量大幅度减少;期望结果可靠性非常高;
- 根据实际的业务逻辑来自行生成接口返回结果or落库数据的期望结果,一个接口仅包含一个check方法。==优势==: 维护成本稳定,不会随着用例的大幅增多而激增;可实现数据的全量对比,大幅度提高代码覆盖率。
最后会对上面提到的没提到的做比较详细的说明,大概后面内容如下,可能会有微调:
- 接口自动化准备篇
- 基于nosetests or pytest搭建自动化测试 。 (基础 +现有框架的整体简单介绍图)
- 测试数据:动静态测试数据的管理实践
- 用例1:测试数据载入及实例化接口对象 (比较几个框架自带参数化及三方参数话库在实际应用的优劣等)
- 用例2:利用装饰器来管理用例结构
- 请求发送:SentRequest 模块介绍
- 断言1: 利用装饰器来对比你的结果
- 断言2:从部分到全量的演进;消息,redis等部分的检查
- 如何加速你的脚本
- 业务1:利用mock解决业务方依赖实践
- 业务2强流程业务接口自动化该如何做才高效 (拼团 从用例到检查)
- 业务3:业务场景并发测试 (抢优惠券等)
- 其他:管理你的环境配置
- 其他:自动化生成测试脚本(接口对象,数据库表对象, 常用用例等)
- 其他:持续集成你的接口自动化
- 其他:特殊项目接口自动化方案介绍(转java,订单分表等)
如果有任何问题可以留言或私聊~会尽量回复~