一、Locust介绍
1、Locust简介
Locust(蝗虫)是一个开源的性能测试工具,主要思想就是模拟一群用户访问你的系统
2、特点
(1)在代码中定义用户行为
不需要安装笨重的软件,只是简单的Python代码
(2)分布式和可扩展
Locust支持在多台机器上的运行负载测试,因此可用于模拟数百万用户的请求
(3)经过验证和战斗测试
Locust被用于许多真实的项目中
(4)Locust有一个整洁的HTML+JS的用户界面,实时显示相关测试细节
由于用户界面是基于网络的,它是跨平台的和容易扩展
二、Locust技术架构
安装命令:
pip install locust
安装成功验证:
locust --version # 查看安装的版本 locust -h # 查看使用帮助
注意:python的版本最好在3.7以上
架构组成:
1、Python编写的测试用例方案
2、使用request发送HTTP请求
3、使用协程,低成本的实现更多并发
4、支持分布式
5、使用Flask提供WebIUI
6、有第三方的插件,可以进行扩展
三、locust测试用例的写法
def test_login_smalleel():
paramsPro = {"username": config.get_user_info("usernamePro"),
"password": login_md5(config.get_user_info("usernamePro"), config.get_user_info("passwordPro"))}
url = ApiUtil(1, "ApiCommon").get_url("LOGIN")
responsePro = requests.post(url=url, data=paramsPro).json()
assert responsePro["code"] == 200
将其转为locust的性能测用例,经过几个步骤:
1、创建locust.HttpUser子类
2、为用例加上@locust.task
3、使用self.client发送请求
4、指定wait_time属性
import locust
from common.util.apiUtil.apiUtil import ApiUtil
from common.util.configUtil.configUtil import ConfigUtil
from common.util.md5Util.stringTomd5 import login_md5
from common.util.requestUtil.requestUtil import RequestsUtil
requestUtil = RequestsUtil()
config = ConfigUtil()
class MyUser(locust.HttpUser): # 1、创建locust.HttpUser子类
wait_time = locust.between(1, 2) # 2、每个tast间隔1~2s
@locust.task
def test_login_smalleel(self):
paramsPro = {"username": config.get_user_info("usernamePro"),
"password": login_md5(config.get_user_info("usernamePro"), config.get_user_info("passwordPro"))}
url = ApiUtil(1, "ApiCommon").get_url("LOGIN")
responsePro = self.client.post(url=url, data=paramsPro).json()
print(responsePro)
assert responsePro["code"] == 200
if __name__ == '__main__':
my = MyUser()
my.test_login_smalleel()
四、Locust执行多任务模板
import random
from locust import TaskSequence, HttpLocust, task, seq_task, between
# 定义一个任务类,这个类名称自己随便定义,类继承TaskSequence 或 TaskSet类,所以要从locust中,引入TaskeSequence或TaskSet
# 当类里面的任务请求有先后顺序时,继承TaskSequence类, 没有先后顺序,可以使用继承TaskSet类
class MyTaskCase(TaskSequence):
# 初始化方法,相当于 setup
def on_start(self):
pass
# @task python中的装饰器,告诉下面的方法是一个任务,任务就可以是一个接口请求,
# 这个装饰器和下面的方法被复制多次,改动一下,就能写出多个接口
# 装饰器后面带上(数字)代表在所有任务中,执行比例
# 要用这个装饰器,需要头部引入 从locust中,引入 task
@task
@seq_task(1) # 装饰器,定义有执行顺序的任务,扩展中的数字,从小到大,代表先后执行顺序
def regist_(self):
url = '/erp/regist'
self.headers = {"Content-Type": "application/json"}
self.user = "locust_" + str(random.randint(10000, 100000))
self.pwd = '1234567890'
data = {"name": self.user, "pwd": self.pwd} # post请求的 请求体
# 使用self.client发起请求,请求的方法根据接口实际选,
# catch_response 值为True 允许为失败 , name 设置任务标签名称 -----可选参数
rsp = self.client.post(url, json=data, headers=self.headers, catch_response=True, name='api_regist')
if rsp.status_code == 200:
rsp.success()
else:
rsp.failure('regist_ 接口失败!')
@task # 装饰器,说明下面是一个任务
@seq_task(2) # 顺序任务装饰器,说明下面的任务,第二个执行
def login_(self):
url = '/erp/loginIn'
data = {"name": self.user, "pwd": self.pwd}
rsp = self.client.post(url, json=data, headers=self.headers,
catch_response=True) # 使用self.client发起请求,请求的方法 选择post
self.token = rsp.json()['token']
if rsp.status_code == 200 and rsp.json()['code'] == "200":
rsp.success()
else:
rsp.failure('login_ 接口失败!')
@task # 装饰器,说明下面是一个任务
@seq_task(3) # 顺序任务装饰器,说明下面的任务,第三个执行
def getuser_(self):
url = '/erp/user'
headers = {"Token": self.token}
rsp = self.client.get(url, headers=headers, catch_response=True) # 使用self.client发起请求,请求的方法 选择 get
if rsp.status_code == 200:
rsp.success()
else:
rsp.failure('getuser_ 接口失败!')
# 结束方法, 相当于teardown
def on_stop(self):
pass
# 定义一个运行类 继承HttpLocust类, 所以要从locust中引入 HttpLocust类
class UserRun(HttpLocust):
task_set = MyTaskCase # 定义固定的 task_set 指定前面的任务类名称
wait_time = between(0.1, 3) # 设置运行过程中间隔时间 需要从locust中 引入 between
'''
运行:
在终端中输入:locust -f 被执行的locust文件.py --host=http://被测服务器域名或ip端口地址
也可以不指定host
命令执行成功,会提示服务端口,如:*:8089
此时,则可通过浏览器访问机器ip:8089,看到任务测试页面
'''
五、Locust执行压测
4.1 通过WebUI执行
优点:简单+绘制图表(直观)
py文件没有问题的话,将可以通过浏览器访问 http://localhost:8089 访问locust服务.
locust -f .\z_demo\demo1.py
启动:http://localhost:8089/
第1个"Number of total users to simulate" 填写的是 总共将运行的用户数;
第2个 "Hatch rate"每秒加载的用户数;
第3个 "Host",被测接口的域名或ip端口地址(带http://),
Start swarming , 启动
如图
4.2 通过命令行执行
-
指定运行时的ip和端口
locust -f 被执行的文件.py --web-host 127.0.0.1 -P 8389
此时,浏览器访问 http://localhost:8089 时,页面中,已经自动带入了 Host值
-
无图形界面(无头模式)模式
无头模式,即无图形界面模式,不能通过浏览器访问页面来设置性能测试场景,只能通过命令中带参数来设置。参考命令如下:
locust -f 被执行的文件.py --no-web -c 30 -r 2 -t 2m --host=http://ip:8080 --csv=结果报告文件前缀
# --no-web 指名用无图形界面模式
# -c 指定运行的最大用户数,对应图形界面中的 Number of total users to simulate
# -r 指定每秒生成用户数,对应图形界面中的 Hatch rate
# -t 指定总共运行时长,因在无图形界面中,没有停止按钮,需要有这个参数才能到时间就停止,不然会一直运行下去,直到终端ctrl+c强行停止
# --host 指定被测服务器域名或ip端口地址
# --csv 指定输出结果到csv文件的前缀
这样,就会按照设置的参数,运行,到达运行时长自动停止,同时把测试结果写到配置的文件前缀的 '_stats.csv' 和 '_stats_history.csv' 文件中.
-
分布式运行
locust 除了上面两种常用的模式外,还有一种叫分布式,就是用主控机器,控制助攻机,一起执行测试。
Ⅰ.主控机器master和助攻机器slave,同一台机器
启动主控进程,在终端中执行:
locust -f 被执行的文件.py --master
启动助攻进程,在终端中执行:
locust -f 被执行的文件.py --slave
注意:
Ⅰ 助攻进程可以启动多个,在多个终端中执行启动助攻进程,就能启动多个。
Ⅱ 主控机master和助攻机slave,启动顺序没有要求,
Ⅲ 启动主控机master后,检测到有助攻机进程,就会显示 'Client reported as ready. Currently N** clients ready to swarm.' N指代数量
Ⅳ 分布式支持图形界面、无图形界面,相比而言,图形界面用的较多,因为能轻松控制所有助攻机slave一起执行;分布式执行无图像界面命令,建议先启动助攻机slave,然后再在启动主控机master时,指定命令,不然,助攻机器将可能不同时执行。
Ⅴ 分布式在执行时,设置的total users、Hatch rate,将平均分配到各个助攻机slave中执行。
Ⅵ 建议一台机器slave个数,不要超过cpu核数数量。
Ⅱ. 主控机器master和助攻机器slave,不是同一台机器
启动主控机器主进程master,在终端中执行:
locust -f 被执行的文件.py --master
locust -f 被执行的文件.py --master
locust -f 被执行的文件.py --slave --master-host=主控机器ip --master-port=5557
-
注意:
-
启动助攻机器进程时,--master-host指定主控机器master的ip地址,如果不带master-port则用默认的5557端口,如果主控机器指定了端口,则这个要对应修改
-
其他,与在同一台机器上一样