Locust (二)接口压力测试

文中示例代码使用的 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个用户

六、查看测试结果

猜你喜欢

转载自blog.csdn.net/kk_gods/article/details/111672037