作者 | 咪咪
创新互联-专业网站定制、快速模板网站建设、高性价比酉阳土家族苗族网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式酉阳土家族苗族网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖酉阳土家族苗族地区。费用合理售后完善,十多年实体公司更值得信赖。
wiremock-py 是基于 WireMock 实现的, 使用 Python 批量生成不同测试场景下不同HTTP API 的 mock 数据, 然后作为 mock server 快速全面地对 API 进行测试。
在数澜地产应用的前端测试中, 前端一般依赖于后端的数据, 前端通过后端在网关上发布的 HTTP API 获取数据. 要对前端进行充分的测试, 理想的做法是, 等待后端部署完成, 并且在数据层直接输入不同类型的数据源, 然后前端直接调用后端发布在网关上的 API 进行测试。
cdn.xitu.io/2019/7/18/16c03b5cfad2a16e?w=339&h=376&f=png&s=33802">
然而现实的情况是, 前端和后端的开发进度不完全一致, 如果前端先开发完成了, 必须要等后端对应的 API 开发完成后才能开始测试, 而且数据层的数据也不容易构造。
为了解决这个问题, 网关平台做了简单的 mock 功能, 每个 API 可以填写一个 mock数据, 然后前端调用 API 时直接使用这个 mock数据:
这种方式下, 网关充当了mock server:
但由于大家都使用同一个网关, 一个 API 只能保存一份 mock 数据, 所以有以下一些缺点:
不同的测试场景需要不同的 mock 数据来测试, 此时需要删掉上个测试场景的 mock 数据, 再创建新场景的 mock 数据才能进行测试
不能根据测试场景来按照一定的规则动态生成 API 对应的 mock 数据
wiremock-py 可以解决上述这些问题: wiremock-py 通过传入不同的测试场景参数来生成不同的 mock 数据, 同时不同测试场景下使用的 mock 数据可以保存起来; 生成 mock 数据时, wiremock-py 支持使用Python和js代码来动态生成 mock 数据(也支持直接使用 json 数据, 如果 mock 数据中的数据量很大, 人工手写 mock 时的数据量会很大, 使用代码生成则比较容易); 不同的测试人员使用各自自己的 mock server, 不会影响到其他测试人员的测试。
测试人员需要做的是: 确定哪些 API 需要进行 mock 以及不同测试场景下对应的 mock 规则是什么。
Java 1.8.0_144
Node v8.6.0
Python 3.4.3
快速开始
以贸数v1.1.0版本 测试环境为例演示使用 wiremock-py 对楼层客流分布和店铺客流分布两张图分布在3种场景下的测试方法
先确定本地浏览器能过正常访问 http://mall-data.com:9012
准备
克隆代码
git clone http://git.dtwave-inc.com:30000/baomi.wbm/wiremock-py.git
安装依赖
cd wiremock-py
pip install -r requirements.txt
npm install mockjs
生成目录
python mock.py -g "demo"
➜ wiremock-py git:(master)✗ python mock.py -g "demo"
DEBUG:root:mockdir=, scene=, target=, proxy_port=5506, generate=demo, wiremock=False, rewrite=False
DEBUG:root:正在生成目录 /Users/wangbaomi/autotest/wiremock-py/demo
DEBUG:root:创建目录成功: demo
DEBUG:root:创建目录成功: demo/js
DEBUG:root:创建目录成功: demo/json
DEBUG:root:创建目录成功: demo/python
DEBUG:root:创建目录成功: demo/wiremock
DEBUG:root:创建文件成功: demo/mappings.json
DEBUG:root:生成目录完成: /Users/wangbaomi/autotest/wiremock-py/demo
填写 mappings.json、json、python、js 数据
mappings.json 中填写内容:
[
{
"response": {
"default": {
"proxyBaseUrl": "target"
}
},
"mapping_name": "request url not start with /api",
"request": {
"method": "ANY",
"urlPattern": "/(?!api).*"
}
},
{
"mapping_name": "楼层客流分布",
"request": {
"urlPattern": "/api/v1/mall_data/customer_flow/every_floor\\?(.*)",
"method": "POST"
},
"response": {
"default": {
"proxyBaseUrl": "target"
},
"测试场景1": {
"bodyFileName": {
"json": "楼层客流分布.json"
}
},
"测试场景2": {
"bodyFileName": {
"python": "楼层客流分布.py",
"python_args": "测试场景2"
}
},
"测试场景3": {
"bodyFileName": {
"js": "楼层客流分布.js"
}
}
}
},
{
"mapping_name": "店铺客流分布",
"request": {
"urlPattern": "/api/v1/mall_data/customer_flow/every_shop\\?(.*)",
"method": "POST"
},
"response": {
"default": {
"proxyBaseUrl": "target"
},
"测试场景1": {
"bodyFileName": {
"js": "店铺客流分布.js"
}
},
"测试场景2": {
"bodyFileName": {
"json": "店铺客流分布.json"
}
},
"测试场景3": {
"bodyFileName": {
"python": "店铺客流分布.py",
"python_args": "测试场景3"
}
}
}
}
]
js 文件夹中新建店铺客流分布.js文件, 内容为:
var r = {
"success": true,
"code": null,
"message": null,
"content": {
"meta": {},
"multi": {
"group": [
{
"id": "rank",
"name": "排名",
"value": [
1,
2,
3,
4
]
}
],
"result": [
{
"id": "the_shop",
"name": "店铺",
"value": [
"店铺1",
"店铺2",
"店铺3",
"第4个店铺"
]
},
{
"id": "customer_count",
"name": "人数",
"value": [
10,
100,
1000,
3242
]
}
]
},
"single": []
}
};
console.log(JSON.stringify(r));
js 文件夹中新建楼层客流分布.js文件, 内容为:
var r = {
"success": true,
"code": null,
"message": null,
"content": {"meta": {},
"multi": {
"group": [
{
"id": "the_floor",
"name": "楼层",
"value": [
"-1楼",
"1楼",
"2楼",
"3楼",
]
}
],
"result": [
{
"id": "customer_count",
"name": "人数",
"value": [
100,
1000,
5000,
567
]
}
]
},
"single": []
}
};
console.log(JSON.stringify(r));
json 文件夹中新建店铺客流分布.json, 内容为:
{
"success": true,
"code": null,
"message": null,
"content": {
"meta": {},
"multi": {