本文写作时,使用当时最新版本的0.14.5,现在已更新到2.x,可能有误,请谨慎参考。


乌鸦用的Python3.8.2 locust0.14.51.

1.安装locustio

pip install locustio

Supported Python VersionsLocust is supported on Python 3.6, 3.7 and 3.8.

如果使用在线安装有问题,可以修改pip源为国内镜像或离线安装

pip install locustio

安装成功以后可以查看帮助

locust -h


乌鸦:python3.8竟然还要C++大于14(参考: https://blog.csdn.net/vkingnew/article/details/89857774 https://wiki.python.org/moin/WindowsCompilers

2.Quick start

from locust import Locust, task, TaskSet, constant

class MyTaskSet(TaskSet):
    @task
    def task1(self):
        print('this is task1..........')

class MyLocust(Locust):
    task_set = MyTaskSet
    wait_time = constant(3)

定义了两个类,第一个MyTaskSet继承了TaskSet,并且使用@task声明了一个任务,类似jmeter的sampler
第二个类MyLocust继承了Locust,其中必须重写两个父类的属性,task_set和wait_timetask_set被赋值了一个TaskSet子类的实例,wait_time可以是locust提供的几种时间策略(constant、between),也可以自己实现wait_time

执行

locust -f locust_file.py   乌鸦:如果提示http://*:8089,使用 --web-host=127.0.0.1 即可

然后在浏览器中访问http://ip:8089 输入用户数和时间即可。
另外,乌鸦调试脚本更倾向使用命令模式

locust -f locust_file.py --no-web -c 10 -r 1 -t 5 

NUM CLIENTS 虚拟用户数
-r Hatch rate 每秒产生客户端的速率
-t Run Time 运行的时间

3.详细介绍

每一个Locust脚本,都需要至少包含一个Locust的子类。
如果一个文件中包含多个Locust的子类,运行时需要显示指定需要运行的子类,否则会随机选择一个子类运行

locust -f locust_file.py WebUserLocust MobileUserLocust

Locust的属性,子类中必须要继承的属性
task_set:【必须】需要执行的任务
wait_time:【必须】等待时间,(between(m,n)随机返回m和n之间的数字;constant(3)返回指定的时间)
等待时间为5到15秒之间

class MyTaskSet(TaskSet):
    @task
    def my_task(self):
        print("executing my_task")

class User(Locust):
    task_set = MyTaskSet
    wait_time = between(5, 15)

也可以在Locust的子类中声明wait_time方法

class MyLocust(Locust):

task_set = MyTaskSet
last_wait_time = 0

def wait_time(self):
    self.last_wait_time += 1
    return self.last_wait_time

weight:比重

class WebUserLocust(Locust):
    weight = 3
    ...
class MobileUserLocust(Locust):
    weight = 1
    ...

执行多个Locust子类的时候,第一个和第二个的执行比例为3:1

locust -f locust_file.py WebUserLocust MobileUserLocust

使用@task可以指定权重,task2和task1执行的比例为2:1。一般建议使用@task

class MyTask(TaskSet):
    @task(3)
    def task1(self):
        pass

    @task(6)
    def task2(self):
        pass

一般,都会创建一个TaskSet的子类,来存放众多的测试任务。除了TaskSet,还有TaskSequence。
TaskSet的子类,在运行时,会从多个task中随机选择一个来运行。而TaskSequence的子类,在运行时,会按task的顺序来执行(乌鸦:在当前实例中,所有的task按顺序执行)

Locust 有setup、teardown,一般用于全局初始化、资源申请等操作
TaskSet 有setup、on_start、on_stop、teardown
执行顺序为

1. Locust setup (once)  
2. TaskSet setup (once)
3. TaskSet on_start (once per locust)  乌鸦:每个实例执行一次
4. TaskSet tasks…
5. TaskSet on_stop (once per locust)  乌鸦:每个实例执行一次
6. TaskSet teardown (once)
7. Locust teardown (once)

注:每个虚拟用户都是一个Locust的实例

jmeter用的好好的,突然下定决定折腾一把locust,之前看了gatling,scala的语法实在难以下咽,趁着python还没忘干净,尝试一把。毕竟locust和gatling都是号称能发起百万级别请求的测试工具。

参考 https://docs.locust.io/en/0.14.5/writing-a-locustfile.html

PS:看官方文档注意版本,之前看了最新的latest,跟目前的版本(0.14.5)有些许差别,切换了文档版本号才没问题。看了github,感觉快要发布新版本了。。。

在latest的文档中介绍,不一定需要继承TaskSet的子类,声明任务使用@task,直接写在Locust子类中即可。