locust性能测试脚本编写分享

locust是一个相对容易上手的一个分布式用户负载测试工具,支持Web UI实时监控以及无头模式运行。
安装也非常简单,需要先确定自己的python在3.6以上版本,然后再安装Locust,执行安装命令pip install locust即可。

如何编写locust的python脚本?下面是locust的一些类和属性的介绍

1. HttpUser 类是用于模拟 HTTP 请求的基本用户行为类,首先需要定义一个继承自 HttpUser 的类,并在其中定义用户的操作,其中的一些属性参数

client 属性,类似于requests中请求方式支持以下几种方式
  • client.get(url, **kwargs):发送 GET 请求。
  • client.post(url, data=None, json=None, **kwargs):发送 POST 请求。
  • client.put(url, data=None, **kwargs):发送 PUT 请求。
  • client.delete(url, **kwargs):发送 DELETE 请求。
  • client.head(url, **kwargs):发送 HEAD 请求。
  • client.options(url, **kwargs):发送 OPTIONS 请求

拿我们常用的post请求举例子

from locust import HttpUser, task

class MyUser(HttpUser):

    @task
    def login(self):
        self.client.post("/login", {"username": "test", "password": "test"})

除了基本的请求方法之外,client 还支持传递额外的参数,如 headers、params 等。

1.2 wait_time 属性 
    wait_time 属性用于设置虚拟用户在执行完一次任务后等待的时间。这可以通过 between(min_wait, max_wait) 方法来设置一个随机的等待时间范围,如 wait_time = between(5, 15)  
1.3 host 属性
      HttpUser 类默认使用 host 属性来发送请求。如果未指定 host,则需要在每个请求中明确指定 URL.host属性,一般在HttpUser 类中设置 host 属性
示例:class MyTest(HttpUser):
             host = "http://127.0.0.00:10001"

2 .TaskSet 类是一个容器类,用于定义一组任务,并且可以指定这些任务的执行频率。TaskSet 允许任务以随机顺序执行,并且可以为每个任务指定权重,权重较高的任务将更频繁地被执行
示例

from locust import task, TaskSet


class XnTest(TaskSet):
    @task(4)
    def more_page(self):
        self.client.get("/one")
    
    @task(1)
    def litle_page(self):
        self.client.get("/two")

@task(4) 和 @task(1):分别为两个任务指定了权重,就是@task(4)的more_page执行大概占比80%,@task(1)的litle_page占比为20%

3 .SequentialTaskSet 类与 TaskSet 类相似,但它的任务将按照定义的顺序依次执行,而不是随机执行。这意味着任务将按照你在脚本中定义的顺序依次执行,而不会被打乱

from locust import task, SequentialTaskSet


class UserTest(SequentialTaskSet):
    @task
    def index_page(self):
        self.client.get("/")
    
    @task
    def profile_page(self):
        self.client.get("/profile")

@task:定义了两个任务,它们将按照定义的顺序依次执行

4.  一个简单的SequentialTaskSet 类与 TaskSet类,HttpUser类一起结合使用

from locust import task, between,TaskSet, SequentialTaskSet,HttpUser


class LoginSequence(SequentialTaskSet):
    @task
    def login(self):
        self.client.post("/login", {"username": "test", "password": "test"})
    
    @task
    def logout(self):
        self.client.get("/logout")


class UserBer(TaskSet):
    tasks = {LoginSequence: 2}  # 指定顺序执行的任务
    
    @task(4)
    def index_page(self):
        self.client.get("/one")
    
    @task(1)
    def profile_page(self):
        self.client.get("/two")

class MyWebUser(HttpUser):
    wait_time = between(5, 15)
    host = "http:/xxxxxxxx.com"
    tasks = [UserBer]

通过 TaskSet 和 SequentialTaskSet 类结合使用,我们可以简单定义模拟较为真实的用户行为,具体还是要看业务场景灵活使用

5. on_start和on_stop
就是每个用户实列化前会执行一次,oe_stop则是实例化后销毁一次,可以模拟用户的登录登出场景。

6. 对于多接口测试,在每个方法上加上task装饰器即可,task装饰器上可添加权重参数,把之前所用到的组合起来,并且加上with断言更贴近我们实际的测试场景。

from locust import HttpUser, task, between,TaskSet


class MyUser(TaskSet):


    def on_start(self):
        cs_url = "/login/xxxx/xxxx/xxx"  # 替换为你的地址
        # 模拟用户登录并获取 token
        data_zero = {"username": "testuser", "password": "testpassword"}
        response = self.client.post(cs_url, data=data_zero)
        token = response.json()["token"]
        self.token = token

    @task(4)
    def test_one(self):
        url_one = "/xxxx/xxxx/xxxx/xxx"
        data_one = {
            "token": self.token,  # 调用on_start中获取的token
            "type": 1,
            "size": "1",
            "id": 12
        }
        with self.client.get(url_one, data=data_one, catch_response=True) as response:
            if response.status_code == 200:
                restext = {"name":"test_name", "id": 2}
                textlist = response.json()["data"]
                if restext in textlist:
                    response.success()
                else:
                    response.failure("购物车返回的数据不正确")
            else:
                response.failure("请求失败状态码不正确,实际为".format(response.status_code))



    @task(1)  # 权重占比为1
    def test_two(self):
        cs_url = "/xxxx/xxxx/xxxx/xxx"
        cs_data = {"token": self.token,
                   "id": 14,
                   "size": 1
                   }

        with self.client.get(cs_url, data=cs_data,catch_response=True) as response:
            if response.status_code == 200:
                restext_1 = {"name": "test_name", "id": 2}
                textlist_1 = response.json()["data"]
                if restext_1 in textlist_1:
                    response.success()
                else:
                    response.failure("返回的数据不正确")
            else:
                response.failure("请求失败状态码不正确,实际为".format(response.status_code))

class OP_login(HttpUser):
    tasks = [MyUser]
    host = "http://localhost:1001"
    wait_time = between(1, 3)

在locust中我们一般用with进行自定义断言,with 语句结合 catch_response=True 参数可以用来获取和自定义请求的响应。这允许我们在请求失败时手动标记为成功或失败,并且可以添加自定义的失败原因,这让我们更好的去控制测试结果。

7. 在实际场景中不同时间段,客户用户数是不同的,为了更贴近实际的场景,可以这样去编写

from locust import HttpUser, task, between ,LoadTestShape


class MyWebUser(HttpUser):
    wait_time = between(5, 15)
    host = "http://example.com"

    @task
    def index_page(self):
        self.client.get("/")

    @task
    def profile_page(self):
        self.client.get("/profile")

class TestShape(LoadTestShape):
    """
    自定义负载测试,模拟网站流量不同时间的流量。
    """

    max_users = 500  # 最大用户数
    start_rate = 50  # 每秒启动的用户数

    def tick(self, run_time):
        if run_time < 60:  # 前 1 分钟内逐渐增加用户数
            return (round(run_time * (self.max_users / 60)), self.start_rate)

        elif run_time < 120:  # 接下来的 1 分钟内保持最大用户数
            return (self.max_users, self.spawn_rate)

        elif run_time < 180:  # 接下来的 1 分钟内逐渐减少用户数
            return (round((180 - run_time) * (self.max_users / 60)), self.start_rate)

        else:  # 3 分钟后停止测试
            return None

根据自己的实际情况来编写脚本结合使用,合理编写贴近自己场景的测试脚本,以上只是本人的一些分享,如有错误的地方欢迎指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值