一、Mock 技术
1. 使用场景
- 第一个后端没有开发好,自动化测试的脚本需要提前开发与调试可以使用mock技术
- 提供执行效率:调用第3方接口—-响应特别的长(有不稳定的情况)—10s——在自动化脚本调试的前期
2. 实现方案
- 自己开发一个后端—-使用django flask—-对于一般的测试人员有很大的挑战!
- 使用
moco
框架 减轻测试人员的开发的成本
二、 Mock 服务搭建(moco 框架)
1. moco 框架
实现mock的技术可以分为两类,mock数据和mock服务:
mock数据
:即 mock 一个对象,写入一些预期的值,通过它进行自己想要的测试。- 常见的有:EasyMock、Mockito 、WireMock、JMockit。主要适用于单元测试。
mock 服务
:即mock 一个 sever,构造一个依赖的服务并给予他预期的服务返回值,适用范围广,更加适合集成测试。
2. mock 服务搭建
1. 下载 moco 框架
在github上获取 moco 的jar包,当前版本是:V1.2.0
Github 地址 :https://github.com/dreamhead/moco
2. 配置 json 文件
创建一个json
文件,用来模拟不同的请求,返回不同的响应。
1 2 3 4 5 6 7 8 9
| [{ "description":"demo", "request":{ "uri":"/demo1" }, "response":{ "text":"Hello,demo1" } }]
|
description
: 是注释(描述),由于json无法写注释,所以提供了用这个keyuri
: 就是我们这个接口的统一资源标识符,可以根据模拟的接口自行定义response
: 里的内容即为返回的值
3. 服务启动
moco项目是采用java开发的,所以启动moco前,需要安装jdk
JDK安装文档:http://vip.ytesting.com/q.do?a&id=10005
1. 使用 启动文件 启动服务
启动文件、json 文件、 moco 框架文件 必须在同一路径下
创建记事本,输入以下代码:
1 2 3 4 5 6 7 8 9 10 11
| @echo off echo 接口自动化实战-Mock服务准备启动...... @echo on
java -jar moco-runner-1.2.0-standalone.jar http -p 9999 -c order_shop.json
@echo off echo Mock服务启动成功 echo 端口号-9999 echo 执行文件-order_shop.json pause
|
将文件 重命名 为 Mock_server_run.bat
2. 使用 命令 启动
打开 cmd 窗口,切换地址到 cmco 路径下,输入启动服务命令
1
| java -jar moco-runner-1.2.0-standalone.jar http -p 9999 -c order_shop.json
|
jar 包
: 名称根据自己下载的 jar 包 版本修改http
: 表示模拟的是 http 请求-p 9999
: 表示 定义的端口-c order_shop.json
: 表示 使用模拟返回的 json 文件
服务开启后,可以通过浏览器访问 http://127.0.0.1:9999/demo1 来访问
demo1
为 json 文件中的 uri
4. 配置不同的 请求
demo1: 约定 uri
1 2 3 4 5 6 7 8 9
| [{ "description":"demo1=约定URI", "request":{ "uri":"/demo1" }, "response":{ "text":"Hello,demo1" } }]
|
demo2: 约定请求参数
1 2 3 4 5 6 7 8 9 10 11 12
| [{ "description":"demo2=约定请求参数", "request":{ "queries":{ "key1":"abc", "key2":"123" } }, "response":{ "text":"Hello,demo2" } }]
|
demo3: 约定请求方法
1 2 3 4 5 6 7 8 9
| [{ "description":"demo3=约定请求方法", "request":{ "method":"DELETE" }, "response":{ "text":"Hello,demo3" } }]
|
demo4: 约定请求头
1 2 3 4 5 6 7 8 9 10 11
| [{ "description":"demo4=约定请求头", "request":{ "headers":{ "Content-Type":"application/xml" } }, "response":{ "text":"Hello,demo4" } }]
|
demo5: 约定请求体参数 - form
1 2 3 4 5 6 7 8 9 10 11
| [{ "description":"demo5=约定请求体参数-form", "request":{ "forms":{ "key1":"abc" } }, "response":{ "text":"Hello,demo5" } }]
|
demo6: 约定请求体参数 - json
1 2 3 4 5 6 7 8 9 10 11 12
| [{ "description":"demo6=约定请求体参数-json", "request":{ "json":{ "key1":"value1", "key2":"value2" } }, "response":{ "text":"Hello,demo6" } }]
|
Demo7:uri-startsWith匹配
1 2 3 4 5 6 7 8 9 10 11
| [{ "description":"demo7=uri-startsWith匹配", "request":{ "uri":{ "startsWith":"/sq" } }, "response":{ "text":"Hello,demo7" } }]
|
Demo8:uri-endWith匹配
1 2 3 4 5 6 7 8 9 10 11
| [{ "description":"demo8=uri-endsWith匹配", "request":{ "uri":{ "endsWith":"sq" } }, "response":{ "text":"Hello,demo8" } }]
|
Demo9:uri-contain包含
1 2 3 4 5 6 7 8 9 10 11
| [{ "description":"demo9=uri-contain匹配", "request":{ "uri":{ "contain":"fcl" } }, "response":{ "text":"Hello,demo9" } }]
|
Demo10:返回状态码
1 2 3 4 5 6 7 8 9
| [{ "description":"demo10=响应状态码", "request":{ "uri":"demo10" }, "response":{ "status":200 } }]
|
Demo11:返回响应头
1 2 3 4 5 6 7 8 9 10 11
| [{ "description":"demo11=响应头", "request":{ "uri":"demo11" }, "response":{ "headers":{ "ContentType":"application/json" } } }]
|
Demo12:重定向
1 2 3 4 5 6 7
| [{ "description":"demo12=重定向", "request":{ "uri":"demo12" }, "redirectTo":"http://www.baidu.com" }]
|
Demo13:返回JSON格式的数据
1 2 3 4 5 6 7 8 9 10
| [{ "description":"demo13=返回json格式的数据", "request":{ "uri":"/demo13" }, "response":{ "json": {"key1":"value1","key2":"value2"} } }]
|
二、 异步 接口
同步,是所有的操作都做完,才返回给用户结果。即写完数据库之后,在相应用户,用户体验不好 。
异步,不用等所有操作等做完,就相应用户请求。即先相应用户请求,然后慢慢去写数据库,用户体验较好
一般流程:
当你请求一个异步接口,接口会立刻返回你一个结果告诉你已经开始处理,结果中一般会包含一个任务id类似的东西用于追踪结果, 另外会提供一个查询结果的接口, 当结果未处理完查询接口会返回相应的”未完成”状态, 如果已经处理完,则会返回相应的数据。
处理方法:
- 异步接口我们一般采取轮询的方法,每隔一定时间间隔取请求一下查询结果的接口,直到接口返回的状态是已完成/查询到指定数据或超时
- 如果异步接口没有提供追踪id和查询接口,我们可以通过同样的方法轮询查取数据库数据或日志数据直到获取到指定结果或超时
接口示例
1. 订单退出申请接口
请求地址 : /api/order/create/
请求方法 : POST
请求格式 : Json
参数 | 类型 | 说明 |
---|
user_id | String | 用户id |
goods_id | String | 商品id |
num | int | 数量 |
amount | float | 总价 |
响应示例
缺少参数:
成功:
2、获取订单结果接口
请求地址 : /api/order/get_result/
请求方法 : GET
响应示例
创建中:
创建成功:
1 2 3 4 5 6 7
| { "user_id": "sq123456", "goods_id": "20200815", "num": 1, "amount": 200.6 "msg": "success" }
|
2. 配置 json 文件
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
| [ { "description":"提交申请接口", "request":{ "method":"POST", "uri":"/api/order/create/", "json":{ "user_id":"sq001", "goods_id":"20201012", "num":2, "amount":100.8 } }, "response":{ "headers":{ "Content-Type":"application/json" }, "status":200, "json":{ "order_id": "6666" } } }, { "description":"查询申请结果接口", "request":{ "method":"GET", "uri":"/api/order/get_result/", "queries":{ "order_id": "6666" } }, "response":{ "headers":{ "Content-Type":"application/json" }, "status":200, "json":{ "user_id":"sq001", "goods_id":"20201012", "num":2, "amount":100.8, "msg":"成功" } } } ]
|
3. python 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import requests
HOST = 'http://127.0.0.1:9999'
def create_order(): url = f'{HOST}/api/order/create/' payload = { "user_id": "sq001", "goods_id": "20201012", "num": 2, "amount": 100.8 } resp = requests.post(url, json=payload) return resp.json()['order_id']
|
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
|
import time
def get_order_result(orderId, interval=5, time_out=30): ''' :param orderId: id :param interval: 查询频率 5s查询频率 :param time_out: 查询的超时时间 :return: ''' payload = {'order_id': orderId} url = f'{HOST}/api/order/get_result01/'
start_time = time.time() end_time = start_time + time_out cnt = 0 while time.time() < end_time: resp = requests.get(url, params=payload) cnt += 1 print(f'第{cnt}次查询', '结果是:--->', resp.text) if resp.text: break time.sleep(interval) return resp.text
|