locust学习教程(3)- 编写locust脚本

news2024/11/25 11:57:20

前言

一句话总结:并发的用户执行了第一类测试任务、第二类测试任务,设置所有类的测试前置、测试后置,设置每一类测试任务的测试前置,测试后置。


1、概念

1.1、一个完整的脚本示例

from locust import task, HttpUser, constant_pacing
from locust import between, constant, tag
from locust import events
from locust.runners import MasterRunner
import csv
import time
import json
from json import JSONDecodeError
from loguru import logger


@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    if not isinstance(environment.runner, MasterRunner):
        print("Beginning test setup")
    else:
        print("Started test from Master node")


@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
    if not isinstance(environment.runner, MasterRunner):
        print("Cleaning up test data")
    else:
        print("Stopped test from Master node")


# 请求完成后,触发监听器:定义了输出响应的相关内容,这个可以放到locufile文件里面
@events.request.add_listener
def my_request_handler(request_type, name, response_time, response_length, response,
                       context, exception, start_time, url, **kwargs):
    if exception:
        print(f"Request to {name} failed with exception {exception}")
    else:
        print(f"request_type : {request_type}")
        print(f"response_time : {response_time}")
        print(f"response_length : {response_length}")
        print(f"context : {context}")
        print(f"start_time : {start_time}")
        print(f"url : {url}")
        print(f"Successfully made a request to: {name}")
        print(f"The response : {response.text}")


class User1(HttpUser):
    weight = 1  # user1类被执行的概率是25%,user2类被执行的概率是4分之3
    host = "https://xxx.com"  # 要加载的url的前缀
    wait_time = between(2, 5)  # 每个用户结束,等待2-5秒
    # wait_time = constant(3)  # 每个用户操作完成后,等待3秒
    # wait_time = constant_pacing(10)  # 强制只等待10秒,优先级大于@task标记方法自定义的的sleep(20)
    # wait_time = constant_throughput(0.1)  # pacing的反例,这个还是等待10秒,1/值(0.1) = 10

    def on_start(self):
        """
        每个user启动前调用on_start方法
        这是获取用户特定测试数据的好地方。每个用户执行一次
        如果不希望记录请求,可以将self.client.<method>替换为request请求
        """
        headers = {"Content-Type": "application/json"}
        self.client.headers = headers  # 这里设置的headers将给分发给每个任务的headers,避免重复去写。
        time.sleep(1)

    @tag("smoke", "tag2")  # 执行被smoke标记的任务:--tags smoke,执行没有被tag2标记的:--exclude-tags tag2/--exclude-tags tag2 smoke
    @task(1)  # 执行脚本时,只会运行被task标记的方法作为一个测试点,其他方法都是辅助任务的
    def test_login1(self):
        # 读取csv中的用户名、密码
        file = open("../data/user/userdata_1000.csv", "r")
        table = csv.reader(file)
        for i in table:
            # 参数化登录的入参
            data = json.dumps({"account": "18741341234"})
        	headers = {"Content-Type": "application/json"}
            r = self.client.post("/api/login", data=data, headers=headers)
            # self.client继承了request.session,所以不用传cookie,传登录,直接请求即可
            with r as response:  # 断言响应的内容
                try:
                    if response.status_code != 200:
                        logger.info("Did not get expected value in greeting")
                except JSONDecodeError:
                    response.failure("Response could not be decoded as JSON")  # 如果是json格式问题,抛出自己定义的异常
                except KeyError:
                    response.failure("Response did not contain expected key 'greeting'")  # 执行失败,抛出异常

    @tag("smoke1")
    @tag("smoke")
    @task(3)  # 有4分之3的几率执行下面这个任务
    def test_login2(self):
        data = json.dumps({"account": "18741341234"})
        headers = {"Content-Type": "application/json"}
        response = self.client.post("/api/login", data=data, headers=headers)
        # locust自带标准断言
        with response as res:
            try:
                if res.status_code != 200:
                    res.failure("脚本返回的code不是200")
            except JSONDecodeError:
                res.failure("Response could not be decoded as JSON")
        time.sleep(1)
        # self.environment.runner.quit()  # to stop the runner from a task method

    def on_stop(self):
        """
        每个user运行结束后调用on_start方法
        清理测试数据等:
        (1)调用接口清理测试数据、(2)数据库清理测试数据
        """
        data = json.dumps({"account": "18741341234"})
        headers = {"Content-Type": "application/json"}
        self.client.post("/api/login", data=data, headers=headers)
        time.sleep(1)

    # tasks = {test_login1: 3, test_login2: 1}  # 任务权重的第二种选择:执行1的概率是2的3倍
    # tasks = [test_login1, test_login2]  # 任务权重的第三种选择:随机执行列表里面的任务


class User2(HttpUser):
    """
    登录
    """
    weight = 4
    last_wait_time = 0
    host = "https://xxx.com"
    wait_time = constant(1)

    def on_start(self):
        data = json.dumps({"account": "18741341234"})
        headers = {"Content-Type": "application/json"}
        self.user_specific_testdata = self.client.post("/api/login", data=data, headers=headers)
        time.sleep(1)
        self.tfjiao = "jiaotengfei"  # 在on start方法中定义了self.tfjiao属性,所以下面可直接调用

    @tag("tag2")
    @task
    def test_login3(self):
        print(self.tfjiao)
        self.last_wait_time += 1  #
        data = json.dumps({"account": "18741341234"})
        headers = {"Content-Type": "application/json"}
        response = self.client.post("/api/login", data=data, headers=headers)
        assert response.status_code == 200

    @tag("smoke")
    @task
    def test_login4(self):
        self.last_wait_time += 1  #
        data = json.dumps({"account": "18741341234"})
        headers = {"Content-Type": "application/json"}
        r = self.client.post("/api/login", data=data, headers=headers)

    def on_stop(self):
        data = json.dumps({"account": "18741341234"})
        headers = {"Content-Type": "application/json"}
        self.client.post("/api/login", data=data, headers=headers)
        time.sleep(1)

1.2、基础内容

from locust import task, HttpUser, constant_pacing from locust import between, constant, tag from locust import events from locust.runners import MasterRunner

  • 在这里locust 文件只是一个普通的 Python 模块,它可以从其他文件或包中导入代码。
  • 在这里,我们为将要模拟的用户定义了一个类。它继承自 HttpUser,为每个用户提供一个client属性,HttpUser继承了HttpSession,client属性可用于发出 HTTP 请求。当测试开始时,locust 会为模拟的每个用户创建一个这个类的实例,每个用户都将开始在他们自己的gevent 线程中运行。HttpSession继承了request.session,HttpSession 增加的主要是将请求结果上报到 Locust(成功/失败、响应时间、响应长度、名称),它具有request库的所有功能,包括抛出的异常内容。
  • wait_time = between(1, 5) :父类定义了一个wait_time,让模拟用户在每个任务执行后等待 1 到 5 秒
  • @task 装饰器locustd的核心。对于每个正在运行的用户,Locust 创建一个 greenlet(微线程),它将调用这些方法。我们通过用 装饰两个方法来声明两个任务@task,其中一个被赋予了更高的执行概率。locust只会监控被@task标记的方法的测试数据,因此可以定义自己的内部辅助方法。

2、HttpUser类

  一个继承了HttpUser的类代表一个用户(脚本执行,web界面可以让你自由设置用户的数目)。它继承自User 类,有以下通用属性:

2.1、等待时间:wait_time

  1. wait_time = between(2, 5) # 每个用户执行结束,等待2-5秒
  2. wait_time = constant(3) # 每个用户执行结束,固定等待3秒
  3. wait_time = constant_pacing(10) # 每个用户执行结束,强制等待10秒,优先级大于@task标记方法自定义的的 time.sleep(20)
  4. wait_time = constant_throughput(0.1) # pacing的反例,这个还是等待10秒,1/值(0.1) = 10

2.2、权重:weight

  weight = 2 用来设置用户类的权重,权重也就是每个用户类被执行的概率,也就是上面的user1和user2两类用户被执行的概率,2个类默认被执行的概率是一样的,如下设置,user2被执行的概率是user1的4倍。

2.3、host

  host 要加载的主机的 URL 前缀(即“ google.com ”)。可以理解为base url,后面发送的请求只要想写变化的部分,url固定的内容都被提到了 host 属性里面。

2.4、on_start \ on_stop

User1类在执行被@task标记的方法前会调用 on_start 方法,on_stop 是执行完@task 后调用。 用于自定义测试数据的准备、清理等。

2.5、环境属性

  environment对用户正在运行的用户的引用。使用它与环境或其runner包含的环境进行交互。例如,从任务方法中停止跑步者: self.environment.runner.quit() ,如果在独立的 locust 实例上运行,这将停止整个运行。如果在工作节点上运行,它将停止该特定节点。

2.6、验证响应

  如果 HTTP 响应代码正常(<400),则认为请求成功,但对响应进行一些额外验证通常很有用。 可以使用catch_response参数、with语句和对response.failure()的调用将请求标记为失败

with self.client.get("/", catch_response=True) as response:
    if response.text != "Success":
        response.failure("Got wrong response")
    elif response.elapsed.total_seconds() > 0.5:
        response.failure("Request took too long")

  我常用的3种断言:

            # 第一种
            assert response.status_code == 200
            
            # 第二种:locust自带标准断言
            with response as res:
                try:
                    if res.status_code != 200:
                        res.failure("脚本返回的code不是200")
                except JSONDecodeError:
                    res.failure("Response could not be decoded as JSON")
            # 第三种:
            # res = response.json()['code']
            # if res == 200:
            #     result = f"{title} - 用例执行成功"
            #     file2.write(result + "\n")
            #     logger.info("成功搜索title: " + title)
            # else:
            #     result = f"{title} - 用例执行失败"
            #     file2.write(result + "\n")

3、任务

  当10并发开始时,将为并发的每个用户创建一个User1类(继承HttpUser)的实例,并且他们将开始在自己的gevent中运行。当这些用户运行时,他们选择要执行的任务,执行完成后,等待一会,继续选择一个新任务,如此持续。这些任务是普通的 Python 可调用程序,如果我们对网站进行负载测试,它们可以执行,如“加载起始页”、“搜索某些产品”、“出价”等操作。

3.1、给用户添加任务:@task

  给用户添加任务就是添加装饰器 @task , 它接受权重的设置,如下test_login2方法的执行概率是test_login1的三倍,

 

3.2、给用户添加任务:tasks

  给用户添加任务的第二个方法是设置tasks属性。以下是2种设置方法:

  • 使用字典来设置权重: tasks = {test_login1: 3, test_login2: 1} # 执行1的概率是2的3倍
  • 源码调用 random.choice() 从列表中随机选择任务: tasks = [test_login1, test_login2]

  在内部,上面的 dict 实际上将扩展为一个列表(并且tasks属性被更新),类似于: [my_task, my_task, my_task, another_task]

from locust import User, constant

def my_task(user):
    pass

class MyUser(User):
    tasks = [my_task]
    wait_time = constant(1)

 

3.3、标记任务:@tag

  通过使用@tag装饰器标记任务,可以使用--tags--exclude-tags参数对在测试期间执行的任务进行自由选择,比如冒烟用例。示例:

from locust import User, constant, task, tag

class MyUser(User):
    wait_time = constant(1)

    @tag('tag1')
    @task
    def task1(self):
        pass

    @tag('tag1', 'tag2')
    @task
    def task2(self):
        pass

    @tag('tag3')
    @task
    def task3(self):
        pass

    @task
    def task4(self):
        pass

  执行示例:locust -f per_01_test.py --tags smoke tag2

4、事件 @event

  如果你想运行一些设置代码作为测试的一部分,通常把它放在 locustfile.py 里面就足够了,但有时需要在运行中的特定时间做一些事情。为了这个需求,Locust 提供了事件钩子。

4.1、test_start \ test_stop

  如果您需要在负载测试开始或停止时运行一些代码,您应该使用 test_start和test_stop 事件。您可以在 locustfile 的模块级别为这些事件设置侦听器:

from locust import events

@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    print("A new test is starting")

@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
    print("A new test is ending")

4.2、init

  该init事件在每个 Locust 进程开始时触发。在分布式模式中特别有用,其中每个工作进程(而不是每个用户)都需要进行一些初始化。:

from locust import events
from locust.runners import MasterRunner

@events.init.add_listener
def on_locust_init(environment, **kwargs):
    if isinstance(environment.runner, MasterRunner):
        print("I'm on master node")
    else:
        print("I'm on a worker or standalone node")

4.3、其他

  其他参考产品文档

5、项目框架

三部分:common、locustfiles、testdata,locustfiles里面分项目、项目里面分单接口测试脚本、业务流程测试脚本


-事必有法,然后有成- 最后祝大家早日达到测试的天花板! 



 以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以留言【777】直接拿走就好了

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/666944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ASEMI代理光宝光耦LTV-50L的工作原理及应用领域

编辑-Z 本文将对光耦LTV-50L进行详细的介绍&#xff0c;包括其工作原理、性能特点、应用领域以及注意事项。通过阅读本文&#xff0c;您将对光耦LTV-50L有更深入的了解&#xff0c;以便在实际应用中更好地发挥其作用。 1、光耦LTV-50L的工作原理 光耦LTV-50L是一种光电器件&a…

uni-table 表格的封装

文章目录 项目场景&#xff1a;实现效果创建表格组件文件页面中使用实现方法 项目场景&#xff1a; 在实际的应用场景中&#xff0c;表格是一个非常常见的需求&#xff0c;如果每一个的表格都自己去手写的话非常的浪费时间&#xff0c;并且当中的代码冗余量非常大&#xff0c;…

Python--元组

Python--元组 <font colorblue>一、创建元组<font colorblue>二、访问元组元素<font colorblue>三、元组的增、删、查、改<font colorblue>1、添加元素<font colorblue>2、删除元素<font colorblue>3、查找元素<font colorblue>4、修…

甄品进化 | 燕小千智能助手,用AIGC撬动企业知识宝藏

背景&#xff1a;2022年AIGC&#xff08;AI-Generated Content,人工智能生成内容&#xff09;这个新概念横空出世&#xff0c;不仅被消费者追捧&#xff0c;而且备受投资界的关注&#xff0c;更是被技术和产业界竞相追逐。2022年12月&#xff0c;OpenAI的大型语言生成模型ChatG…

Android 60问60答 (一篇复习整个Android)

Android 60问60答 &#xff08;一篇复习整个Android&#xff09; 有哪些移动端平台&#xff1f; 厂商开发平台&#xff1a; los 黑莓&#xff08;blackBerry&#xff09; 第三方私有平台&#xff1a;第三方开发供移动设备厂商使用 WindowsMobile 免费开源平台&#xff1…

微信小程序克隆到运行

1.git克隆 2.安装依赖 npm i 如果遇到卡在node lib/install.js 一直不进行 重新运行安装&#xff1a;(https://www.python100.com/html/3716RLP8FZM2.html) npm install --ignore-scripts理解npm install --ignore-scripts 3.安装完运行 npm run serve如果报错&#xff1a; …

基于改进多目标粒子群算法的配电网储能选址定容——附Matlab代码

目录 摘要&#xff1a; 主要内容&#xff1a; 程序思路&#xff1a; 储能选址定容优化模型&#xff1a; &#xff08;1&#xff09;节点电压波动&#xff1a; &#xff08;2&#xff09;负荷波动&#xff1a; &#xff08;3&#xff09;储能系统容量&#xff1a; 改进的…

2023年最好用的办公AI工具,让你工作效率提升10倍!

2023年是AI工具大爆发的一年&#xff0c;在效率办公领域&#xff0c;同样涌现出了很多优秀的AI办公工具&#xff0c;小编亲测了几款&#xff0c;都是宝藏好用的App&#xff0c;以下排名不分先后&#xff0c;一起来看看吧&#xff01; AI办公工具哪个好 GitMindNotion AI酷表C…

智能优化算法之黏菌优化算法(SMA),附matlab代码

黏菌算法是2020年提出的一种智能优化算反&#xff0c;主要模拟的是自然界中多头绒泡菌在不同食物浓度下的觅食行为以及状态变化。黏菌主要分泌酶来消化食物&#xff0c;黏菌的前端延伸成扇形&#xff0c;后端由相互连接的静脉网络包围。环境中不同浓度的食物影响着黏菌静脉网络…

C语言数据在内存中存储---整型提升练习

前言&#xff1a;学习了C语言中的整型提升&#xff0c;总是感觉听的时候很明白&#xff0c;但当自己做题的时候&#xff0c;又总是遗漏了哪一步。自己的感悟&#xff1a;整型提升步骤以及原理都一样&#xff0c;就是把步骤记清楚一步一步的来就行。因此通过下面的一道题来每日复…

【正点原子STM32连载】第三十七章 485实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html# 第三…

【Java.SE】数组的定义与使用

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a;Java.SE&#xff0c;本专栏主要讲解运算符&#xff0c;程序逻辑控制&#xff0c;方法的使用&…

【机器学习】十大算法之一 “随机森林”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

Error in `taosdump‘: malloc(): memory corruption: 0x0

在使用taostools的taosdump导出数据时&#xff0c;遇到如下问题&#xff1a; 解决步骤如下&#xff1a; 先看导出目录下的内存是否足够&#xff0c;不够的话&#xff0c;换其他目录导出如果在内存充足的情况下&#xff0c;出现上述问题那么可能是taostools版本不对&#xff0…

Agilent8564EC频谱分析仪

安捷伦8564EC频谱分析仪13145876435 8564EC 是安捷伦的 40 GHz 频谱分析仪。频谱分析仪测量已知和未知信号的频谱功率。频谱分析仪收集信息&#xff0c;例如输入信号与其频率相比的幅度。作为频率分析仪&#xff0c;频谱分析仪的主要用途是记录和分析电输入信号以及其他信号的频…

OWASP之CSRF跨站请求伪造

CSRF&#xff08;Cross-site request forgery&#xff09;跨站请求伪造 文章目录 一、CSRF定义二、CSRF危害三、CSRF漏洞构成1.漏洞风险存在2.用户登录受信任网站A&#xff0c;并在本地生成Cookie3.攻击者伪装数据操作请求的恶意链接或者页面4.诱使未登出用户主动访问或登录恶…

新式茶饮头部品牌「古茗茶饮」联手企企通,打造采购数字化新思路

导读 企企通在采购与供应链领域积累了丰富的项目开发经验&#xff0c;是国内一站式采购数字化管理平台领军企业之一&#xff0c;其售前、商务、项目人员都是这个赛道最专业的。该平台的建设可以自动化处理采购链路多个节点重复性任务&#xff0c;帮助我们提高采购效率&#xf…

向日葵× 实在RPA擦出AI的火花,贝锐与实在智能官宣战略合作

6月19日&#xff0c;实在智能&#xff08;Intelligence Indeed&#xff09;与贝锐&#xff08;Oray&#xff09;正式宣布达成战略合作。实在智能作为国内AI准独角兽企业和超级自动化平台提供商&#xff0c;与国内领先的SaaS远程连接解决方案提供商贝锐的实力“牵手”&#xff0…

基于Python的电影票房爬取与可视化系统的设计与实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

2023年blender渲染显卡推荐

Blender是完全免费的、开源的&#xff0c;而且非常灵活。为了让 Blender 运行良好&#xff0c;有必要找到最好的 GPU。对于希望优化其 3D 建模和渲染体验的 Blender 专业人士和爱好者来说&#xff0c;找到最好的 GPU 是当务之急。GPU 不仅在渲染方面起着至关重要的作用&#xf…