如果需要对接口进行接口进行压力测试,在 python 中有一个依赖 locust 可供使用。
对接口进行压测,无非是并发之类的性能测试,那么 locust 提供了一个高并发的途径供我们进行压测。
这片博客,记录的点主要有如下几点:基本使用方式、登陆后测试接口、GET 和 POST 方法的自动调用。
1、基本使用方式
我这边安装的 locust 版本是 1.4.1,不同的版本使用差别还是挺大的,可以查阅一下官方文档。
以下是一个小 demo:
# locustfile.py
from locust import HttpUser
class QuickstartUser(HttpUser):
def on_start(self):
pass
def on_stop(self):
pass
@task(1)
def post_api(self):
self.client.post("/api/post", {
"param1": 1,
"param2": 2
})
@task(2)
def get_api(self):
self.client.get("/api/get?param1=1")
如上述代码,在 QuickstartUser 类中,
on_start 方法 表示在进行接口测试前运行的 函数,一般用来进行数据的初始化操作,或者登陆操作。
on_stop 方法 表示在接口测试运行后调用的函数,可用来调用系统登出函数。
这两个函数都是在文件运行时自动调用的。
用 task 装饰器 装饰的函数都是进行接口测试的函数,一般自己在其中写入需要压测的接口, task 后面的 数字表示权重,如上,post_api 和 get_api 调用的次数比例就为 1:2。
根据接口的不同方法,使用 self.client.get 或者 self.client.post。
在 locustfil.py 文件所在文件夹下运行命令:
locust -f locustfile.py -H http://ip+port
# ip + port 为待测接口的 地址和端口
会启动一个程序,默认端口为 8089,登陆该 ip + 8089,可以看到类似如下页面:
输入两个参数,第一个参数为 创建的虚拟用户的总数量,第二个参数意义为 每秒钟产生用户的数量,会随着时间数量达到第一个参数的值。
点击 start swarming 按钮会慢慢增加虚拟出的用户数,直到和 第一个参数的数量持平,随后会自动进入数据检测页面,会有接口的统计数据表,包括访问次数,失败次数,访问时间等,还有时时变化的曲线图。
2、登陆后测试
有些接口需要登陆后才能访问,所以在访问接口前可以调用 on_start() 方法来进行接口的登陆操作,以下是示例:
class QuickstartUser(HttpUser):
def on_start(self):
self.client.post("/api/login", {
"username": "test",
"password": "123"
})
这样,在接口访问开始前会自动调用 on_start 方法,进行登陆操作。
3、GET 和 POST 方法的自动调用
如果我们需要测试一系列接口,这些接口请求数据被写入一个 json 文件,且接口请求方法可能是 GET,也可能是 POST,需要根据在文件中读取的数据的不同来进行不同方法的调用。
假设 json 数据的组织结构是:
# API DATA
[
{'method': 'get', 'param': {'param1': 1, 'param2': 2}},
{'method': 'post', 'param': {'param1': 1, 'param2': 2}}
]
这样在进行操作的时候可以根据不同的 method 进行不同的操作:
from urllib.parse import urlencode
class QuickstartUser(HttpUser):
def request_api(self):
"""
GET SINGLE API DATA BY RANDOM
return api_info
"""
method = api_info["method"]
if method == "get":
self.request_get(api_info)
elif method == "post":
self.request_post(api_info)
def request_get(self, api_info):
api = api_info.get("api")
param = json.loads(api_info.get("param", {}))
if param:
api += "?" + urlencode(param)
self.client.get(api)
def request_post(self, api_info):
api = api_info.get("api")
param = api_info.get("param")
self.client.post(api, param)