h1. 使用flask框架自定义mock接口,并与jmeter产生联动
h2. 一、了解flask
是python的一个轻量级web框架,简单说就是可以写python代码自定义接口。
关于flask的具体内容,可自行百度
h2. 二、为什么要自定义mock接口
mock本身是模拟一个请求的服务端,只需要做到收到消息,发出响应即可,无需考虑逻辑,
比较常用的mock软件,如wiremock、mockoon,功能比较有限,只能做到收发消息,在性能测试或者自动化测试中就比较局限,
而这里为什么要自定义接口呢,其实并不是想把这个接口设计得多么复杂(毕竟mock的原则就是开箱即用),
而是想通过python可以进行功能的扩展,比较自由.
h2. 三、为什么要和jmeter产生联动,哪种场景需要他们联动呢?
试想一下,现在要测试一个接口,而这个接口的业务逻辑又会去调用一个第三方接口,而第三方接口并没有部署,那就只能用mock进行代替;
在性能测试或者自动化测试中,我们可能需要获取这个第三方接口收到的业务请求内容,用于jmeter断言或者作为参数二次调用.
h2. 四、实际操作举例
1、业务部署
由于我没有直接可用的业务测试环境,所以这里就自己部署一个业务接口(也是用flask框架写的接口)
是在本地ip的5678端口部署的一个POST接口,收到请求后会响应200 ok,并发起请求调用mock接口,参数是[1、2、3]
from flask import Flask, request, jsonify
import requests
from datetime import datetime
app = Flask(__name__)
# 假设您的数据库查询逻辑在这里,这里我简单返回一个示例数据
def query_database(sql):
# TODO: 在这里编写数据库查询逻辑
sqlback = [1, 2, 3]
data = f"{sqlback}"
return {"data": data}
@app.route('/', methods=['POST'])
def handle_request():
# 接收jmeter发出的http消息并直接回200 ok
if request.method == 'POST':
print("Received a request from JMeter")
print(request.json)
response_data = {"message": "我是业务,我收到你发的消息啦"}
# 向mock的模拟接口发出消息
try:
# mock_url = "http://localhost:3001/test"
mock_url = "http://127.0.0.1:5000/mock_api"
data = query_database(request.json)
response = requests.post(mock_url, json=data)
# print(response.json())
# response_data["mock_response"] = response.json()
except Exception as e:
response_data["error"] = str(e)
return jsonify(response_data), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5678)
2、mock自定义接口+联动操作
非常简单的一个接口,会将收到请求的请求体参数写入csv文件,并输出csv文件的行数(用于统计请求发起的数量)
import csv
from flask import Flask, request, jsonify
app = Flask(__name__)
# 用于存储Mock请求的参数
mock_request_data = []
# 用于模拟第三方接口的Mock响应
mock_response = {"text": "您成功的调用了mock模拟的第三方接口!"}
@app.route('/mock_api', methods=['POST'])
def mock_api():
global mock_request_data
if request.method == 'POST':
# 接收请求数据,并将请求内容的参数保存到mock_request_data列表中
request_data = request.json
# mock_request_data.append(request_data)
with open(data_csv, 'a') as f:
f.write(f'{request_data}\n')
f.close()
# 返回Mock响应
return jsonify(mock_response)
# 统计csv文件行数
def count_csv_rows(file_path):
with open(file_path, 'r') as csvfile:
reader = csv.reader(csvfile)
row_count = sum(1 for row in reader)
csvfile.seek(0)
return row_count
if __name__ == '__main__':
data_csv = r'C:\Users\yaoji\PycharmProjects\mo\mock_request_data.csv'
with open(data_csv, 'w') as f:
f.write('')
f.close()
print("csv文件已经清空")
# mock地址
app.run(host='0.0.0.0', port=5000)
# 结束时调用函数获取CSV文件的行数
num_rows = count_csv_rows(data_csv)
print(f"CSV文件的行数为: {num_rows}")
3、jmeter读取csv文件并引入为变量使用
这个就是传到jmeter中变成一个变量供后续使用
h2. 五、总结
1、这种方式在后续使用起来可能没有那么方便,毕竟需要改代码,维护起来的成本可能有一点高
2、若在测试中有mock和别的软件联动的需求,都可以参考这种实现方式,并且使用flask框架自定义的接口是可以上量接受请求的,完全可以用于性能测试