文中示例代码使用的 locust 版本为 locust 1.1.1
一、导入相关库
from locust import HttpUser, task, between, SequentialTaskSet
import random, json, datetime
from jsonpath import jsonpath
二、声明一些常用变量
ISVALID = (0, 1)
current_date = datetime.date.today().strftime('%Y-%m-%d')
base_url = '''http://***'''
params = {'username': '***', 'password': '***'}
login_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36',
'Content-Type': 'application/json;charset=UTF-8',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
三、创建测试任务类
1、初始化登录
测试任务必须要继承locust的任务类SequentialTaskSet,在不同的版本中写法不一样,详见 Locust 性能测试(一)为什么要用 locust ?为什么 locust 的教程用不了?
class BaseConfig(SequentialTaskSet):
def on_start(self):
# 登录账号,获取token,并将token更新到header中,用来访问后续接口
print('on_start')
import requests
import json
login_url = base_url + '/api/auth/jwt/token'
try:
r = requests.post(url=login_url, json=params, headers=login_headers)
response = json.loads(r.text)
req_token = response['data']['token']
self.org_id = response['data']['user']['orgIdList'][0]
except KeyError:
print('Get Token Failed')
self.req_headers = {
'Authorization': req_token,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36',
'Content-Type': 'application/json;charset=UTF-8',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
on_start 每个用户运行一次,如下,添加三个并发用户,总共运行了三次on_start
2、编写任务
例如:根据需求设计场景为并发100个用户,按照1:2:3分别获取字典、小组、样本
(1)获取样本任务
调用task装饰器,表明这是一个测试任务,并传入参数为3,代表任务权重
@task(3)
def get_relation_color_sample(self):
"""
获取样本
"""
params = {
'orgId': self.org_id,
'isValid': 1,
'colorId': 11
}
# locust 继承了 requests库的全部方法,可以直接使用
with self.client.get('/api/core/coreColorSample/all',
json=params,
headers=self.req_headers,
name='获取样本', # 图表中的任务名称,方便查看
catch_response=True) as resp:
resp_json = json.loads(resp.text)
# 对结果进行断言,并标识
# 取 code 值断言
if int(jsonpath(resp_json, '$.code')[0]) == 200:
resp.success()
else:
# 取 msg 的值
msg_l = jsonpath(resp_json, '$.msg')
resp.failure(msg_l)
# 步骤间等待时间
# 接下来也可以继续编写另一个任务,两个子任务会顺序执行
time.sleep(1)
print('get_relation_color_sample is over')
(2)获取小组任务
设置task权重为2
@task(2)
def get_group(self):
"""
获取小组
"""
params = {
'orgId': self.org_id,
'isValid': 1
}
with self.client.get(
'/api/core/coreGroup/all',
json=params,
headers=self.req_headers,
name='获取小组',
catch_response=True
) as resp:
response = json.loads(resp.text)
# 设置断言
# 如果字符串 “success” 为 True,且 code 为200标记为成功
if response['success'] is True and response['code']==200:
resp.success()
else:
# 否则输出响应报文进一步排查
resp.failure(resp.text)
(3)获取字典任务
task权重设置为1
@task(1)
def get_antibiotic(self):
"""
获取字典
"""
with self.client.get('/api/rtip/lis/antibioticDict/all?orgId={}&del=0&isValid={}'
.format(self.org_id, random.choice(ISVALID)),
headers=self.req_headers,
catch_response=True,
name='获取字典:get_antibiotic') as resp:
print('获取字典:', resp.json())
# 设置断言
# 如果响应时间大于 3 秒标记为响应失败
print(resp.elapsed.total_seconds())
if resp.elapsed.total_seconds() > 3:
resp.failure("Request timed out: >3s")
else:
# 否则不做业务判断直接标记为成功
resp.success()
四、虚拟用户类
必须继承locust用户类,测试任务为http请求,所以继承HttpUser
class WebsiteUser(HttpUser):
tasks = [BaseConfig]
# 设置任务间等待时间 1-2 s
wait_time = between(1, 2)
其他等待时间方法:
(1)constant 类,从上一次响应结束后,等待特定时间(1秒),再发起下一次请求
wait_time = constant(1)
(2)constant_pacing 类,从上一次请求发起后,等待特定时间(1秒),再发起下一次请求,如果上一次请求的响应时间大于指定的时间(3秒),则在响应后立即发起下一次请求
wait_time = constant_pacing(1)
五、运行
pycharm中运行代码
if __name__ == "__main__":
# 在Pycharm中启动
import os
os.system("locust -f base_config.py --host={}".format(base_url))
浏览器中打开 http://localhost:8089/,输入需要运行的用户数和每秒创建用户数,然后点击 start swarming
其他启动locust的方式:
# 命令行单机模式启动 locust.py 可以随意命名
# locust -f locust.py --host=https://test.com
# 命令行分布式模式启动
# locust -f locust.py --host=https://test.com --master
# locust -f locust.py --host=https://test.com --slave --master-host=192.168.1.1
# 非web模式
# locust -f main.py -H http://test.cn --csv=report --no-web -c1000 -r 200 --run-time 60 # 执行60秒,每秒增加200个用户.直到1000个用户
六、查看测试结果