Locust的使用

作者: 萝卜枣 | 来源:发表于2021-10-18 10:01 被阅读0次

    转自 (https://www.cnblogs.com/qingchengzi/p/9505548.html

    启动:

    终端中--->进入到代码目录: locust -f xxxoo.py --host=xxxxx.com

    • -f 指定性能测试脚本文件
    • -host 被测试应用的URL地址【如果不填写,读取继承(HttpLocust)类中定义的host】
    • 通过浏览器访问:http://localhost:8089(Locust启动网络监控器,默认为端口号为:8089)

    Number of users to simulate 设置虚拟用户数
    Hatch rate(users spawned/second)每秒产生(启动)的虚拟用户数
    点击Start swarming 按钮,开始运行性能测试。

    no-web模式运行启动

     终端中-->进入代码目录:>> locust -f xxoo.py  --no-web -c10  -r2 -t 1m
    
    启动参数:
    
        --no-web   表示不使用web界面运行测试。  -c 设置虚拟用户数 。  -r 设置每秒启动虚拟用户数  。 -t  设置运行时间.。
    
    no-web模式运行将测试结果保存到当前.py目录中:locust -f xxoo.py --csv=起一个名字 
    

    例如:

          locust -f test3.py --csv=foobar --no-web -c2 -t10s
    

    分布式压测:

          主从机中必须运行相同的测试代码(把主机中代码复制一份到多个从机中),主机负责收集测试数据,从机进行施压测试;
    
          在主机终端中-->进入代码目录:>> locust -f xxxoo.py --master
    
          从机中终端中-->进入代码目录:>> locust -f  xxxoo.py --slave --master-host=主机ip 
    
          分布式压测no-web模式保存结果到主机中当前运行.py的目录中:>>locust -f test2.py  --csv=foobartt --no-web -c2 -t10s --master
    

    locust --help 查看帮助信息

    概述:
    Locust寓意蝗虫,蝗虫过境,寸草不生;而Locust工具生成并发请求就和一大群蝗虫一般,向我们的被测系统发起攻击,以此测试系统在高并发压力下是否能正常运转。

    Locust测试框架中,采用python进行开发,对常见的http(s)协议的系统,Locust采用request库作为客户端,在发请求时和request库使用方法一样。

    在模拟并发时,Locust采用协程、非阻塞IO来实现网络层的并发请求,因此单台压力机也能产生数千并发请求,再加上对分布式运行的支持,Locust能在使用较少压力机的前提下支持极高的并发数测试。

    实例脚本

    from locust import HttpLocust, TaskSet, task
    
    class WebsiteTasks(TaskSet):
      def on_start(self):   #进行初始化的工作,每个Locust用户开始做的第一件事
          payload = {
              "username": "test_user",
              "password": "123456",
          }
          header = {
              "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
          }
          self.client.post("/login",data=payload,headers=header)#self.client属性使用Python request库的所有方法,调用和使用方法和requests完全一致;
    
      @task(5)    #通过@task()装饰的方法为一个事务,方法的参数用于指定该行为的执行权重,参数越大每次被虚拟用户执行的概率越高,默认为1
      def index(self):
          self.client.get("/")
    
      @task(1)
      def about(self):
          self.client.get("/about/")
    
    class WebsiteUser(HttpLocust):
      host     = "https://github.com/" #被测系统的host,在终端中启动locust时没有指定--host参数时才会用到
      task_set = WebsiteTasks          #TaskSet类,该类定义用户任务信息,必填。这里就是:WebsiteTasks类名,因为该类继承TaskSet;
      min_wait = 5000  #每个用户执行两个任务间隔时间的上下限(毫秒),具体数值在上下限中随机取值,若不指定默认间隔时间固定为1秒
      max_wait = 15000
    
    

    伪代码中对https://github.com/网站的测试场景,先模拟用户登录系统,然后随机访问首页/和/about/,请求比例5:1,并且在测试过程中,两次请求的间隔时间1-5秒的随机值;
    on_start方法,在正式执行测试前执行一次,主要用于完成一些初始化的工作,例如登录操作;

    WebsiteTasks类中如何去调用 WebsiteUser(HttpLocust)类中定义的字段和方法呢?

    通过在WebsiteTasks类中self.locust.xxoo xxoo就是我们在WebsiteUser类中定义的字段或方法;

    伪代码:

    from locust import HttpLocust, TaskSet, task
    import hashlib
    import queue
     
    class WebsiteTasks(TaskSet):
     
        @task(5)
        def index(self):
            data = self.locust.user_data_queue  #获取WebsiteUser里面定义的ser_data_queue队列
            md5_data=self.locust.md5_encryption() #获取WebsiteUser里面定义的md5_encryption()方法
            self.client.get("/")
     
    class WebsiteUser(HttpLocust):
        host     = "https://github.com/"
        task_set = WebsiteTasks
        min_wait = 5000
        max_wait = 15000
        user_data_queue = queue.Queue()
     
        def md5_encryption(self,star):
             '''md5加密方法'''
             obj    = hashlib.md5()
             obj.update(bytes(star,encoding="utf-8"))
             result = obj.hexdigest()
             return result
    

    伪代码中测试场景如何表达?

    代码主要包含两个类:

    WebsiteUser继承(HttpLocust,而HttpLocust继承自Locust)
    WebsiteTasks继承(TaskSet)
    在Locust测试脚本中,所有业务测试场景都是在Locust和TaskSet两个类的继承子类中进行描述;

    简单说:Locust类就类似一群蝗虫,而每只蝗虫就是一个类的实例。TaskSet类就类似蝗虫的大脑,控制蝗虫的具体行为,即实际业务场景测试对应的任务集;

    在Locust类中,静态字段client即客户端的请求方法,这里的client字段没有绑定客户端请求方法,因此在使用Locust时,需要先继承Locust类class HttpLocust(Locust),然后在self.client = HttpSession(base_url=self.host)绑定客户端请求方法;

    对于常见的HTTP(s)协议,Locust已经实现了HttpLocust类,其self.client=HttpSession(base_url=self.host),而HttpSession继承自requests.Session。因此在测试HTTP(s)的Locust脚本中,可以通过client属性来使用Python requests库的所 有方法,调用方式与 reqeusts完全一致。另外,由于requests.Session的使用,client的方法调用之间就自动具有了状态记忆功能。常见的场景就是,在登录系统后可以维持登录状态的Session,从而后续HTTP请求操作都能带上登录状态;

    Locust类中,除了client属性,还有几个属性需要关注:

    task_set ---> 指向一个TaskSet类,TaskSet类定义了用户的任务信息,该静态字段为必填;
    max_wait/min_wait ---> 每个用户执行两个任务间隔的上下限(毫秒),具体数值在上下限中随机取值,若不指定则默认间隔时间为1秒;
    host --->被测试系统的host,当在终端中启动locust时没有指定--host参数时才会用到;
    weight--->同时运行多个Locust类时,用于控制不同类型的任务执行权重;
    Locust流程,测试开始后,每个虚拟用户(Locust实例)运行逻辑都会遵守如下规律:

    先执行WebsiteTasks中的on_start(只执行一次),作为初始化;
    从WebsiteTasks中随机挑选(如果定义了任务间的权重关系,那么就按照权重关系随机挑选)一个任务执行;
    根据Locust类中min_wait和max_wait定义的间隔时间范围(如果TaskSet类中也定义了min_wait或者max_wait,以TaskSet中的优先),在时间范围中随机取一个值,休眠等待;
    重复2~3步骤,直到测试任务终止;
    TaskSet类实现了虚拟用户所执行任务的调度算法,包括规划任务执行顺序(schedule_task)、挑选下一个任务(execute_next_task)、执行任务(execute_task)、休眠等待(wait)、中断控制(interrupt)等待。在此基础上,就可以在TaskSet子类中采用非常简洁的方式来描述虚拟用户的业务测试场景,对虚拟用户的所有行为进行组织和描述,并可以对不同任务的权重进行配置。
    @task
    通过@task()装饰的方法为一个事务。方法的参数用于指定该行为的执行权重。参数越大每次被虚拟用户执行的概率越高。如果不设置默认为1。
    TaskSet子类中定义任务信息时,采取两种方式:@task装饰器和tasks属性。
    采用@task装饰器定义任务信息时:

    from locust import TaskSet, task
    
    class UserBehavior(TaskSet):
        @task(1)
        def test_job1(self):
            self.client.get('/test1')
    
        @task(3)
        def test_job2(self):
            self.client.get('/test2')
    
    

    采用tasks属性定义任务信息时

    from locust import TaskSet
    
    def test_job1(obj):
        obj.client.get('/test1')
    
    def test_job2(obj):
        obj.client.get('/test2')
    
    class UserBehavior(TaskSet):
        tasks = {test_job1:1, test_job2:3}
        # tasks = [(test_job1,1), (test_job1,3)] # 两种方式等价
    
    

    上面两种定义任务信息方式中,均设置了权重属性,即执行test_job2的频率是test_job1的两倍。

    若不指定,默认比例为1:1。

    关联:
    在某些请求中,需要携带之前response中提取的参数,常见场景就是session_id。Python中可用通过re正则匹配,对于返回的html页面,可用采用lxml库来定位获取需要的参数;

    from locust import HttpLocust, TaskSet, task
    from lxml import etree
    
    class WebsiteTasks(TaskSet):
    
        def get_session(self,html): #关联例子
            tages = etree.HTML(html)
            return tages.xpath("//div[@class='btnbox']/input[@name='session']/@value")[0]
    
        def on_start(self):
            html = self.client.get('/index')
            session = self.get_session(html.text)
            payload = {
                "username": "test_user",
                "password": "123456",
                'session' : session
            }
            header = {
                "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
            }
            self.client.post("/login",data=payload,headers=header)
    
        @task(5)
        def index(self):
            self.client.get("/")
            assert response['ErrorCode']==0   #断言
    
        @task(1)
        def about(self):
            self.client.get("/about/")
    
    class WebsiteUser(HttpLocust):
        host     = "https://github.com/"
        task_set = WebsiteTasks
        min_wait = 5000
        max_wait = 15000
    

    相关文章

      网友评论

        本文标题:Locust的使用

        本文链接:https://www.haomeiwen.com/subject/wmnlnltx.html