Locust最佳实践之脚本分析(二)

脚本分析

单接口脚本

image.png

一个测试类对象中添加多个测试任务(方法),通过@task  标识该方法是否为测试类,@task(N) 配置测试任务在整个测试对象Live中的权重。

提供on_start(self),on_stop(self) 方法设置自定义任务开始和结束,每个用户仅执行一次。

写在前面:

脚本中的url 坚决的不要带上环境地址,只允许写path 路径,举例:

错误:https:/baidu.com/apollo/public/getLargeClass?p=w&

正确:/apollo/public/businessLive/getLargeClasst?p=w&

坑点原因说明:在执行测试时,task任务中指定的host 无法覆盖 请求url 中的host !!!!!

多任务脚本(单接口测试):

from locust import HttpUser, task, TaskSet

from api.gettoken import  login_b_withToken


class Live(TaskSet):# 

    def on_start(self): #每个User初始化一次
        print("~~~~~start~~~~~")
       self.token = "c2a2d7a6aea3456a8ae5ea42034eeb21" 
    
    @task(2) #设置该方法是否为执行任务,(2)标识 该任务在该类任务中的权重 1:2:3 ,可以理解为种子数相对比例
    def getInteractionClassLiveList(self):
        # client 方法 
        self.client.post(
            f"/public/getInteraction?p=w&v=v5.4.8&userType=B&token={self.token}",
            json={
                "current": 1,
                "size": 10,
                "courseName": "sss"
            })
    
    @task(3)
    def getLargeClassLiveList(self):
        self.client.post(
            f"/public/getInteraction2?p=w&v=v5.4.8&userType=B&token={self.token}",
            json={
                "current": 1,
                "size": 10,
            })

    def on_stop(self): # 默认会执行
        print("~~~~~stop~~~~~")

class User(HttpUser):
    tasks = [Live] # tasks指定的任务类对象设置,把该类任务放入统一list中
    host = "https://baidu.com" #被测主机地址
    min_wait = 1000 
    max_wait = 5000

单任务多接口脚本(串行链路):

适合1v1链路测试

class show_test(TaskSet):

    @task
    def createShow(self):
        data = {"title": "英语启蒙陪伴营", 
                "deadline": 1615734000256,
                "startTime": 1614506365256,
                "activityType": "312",
                "templateId": "312"}

        show = self.client.post("/sho", json=data)
        print(show.json())
        activityId = show.json()['result']
        
        # 发布
        json = {"activityId": activityId}
        res = self.client.post(
            "/public/business?p=w&",
            json=json)
        print(res.text)

class User(HttpUser):
    tasks = [show_test] # tasks指定的任务类对象设置,把该类任务放入统一list中
    host = "https://baidu.com" #被测主机地址
    min_wait = 1000 
    max_wait = 5000

特别得HttpUser类

它在HttpUser 类中,源码说明:This class creates a *client* attribute on instantiation which is an HTTP client with support for keeping a user session between requests.

翻译:这个类在实例化时创建一个*client*属性,它是一个HTTP客户机,支持在请求之间保持用户会话。

client 是一个HttpSession 类型

client: HttpSession = None
"""
Instance of HttpSession that is created upon instantiation of Locust.
The client supports cookies, and therefore keeps the session between HTTP requests.
"""

翻译:在实例化时创建的HttpSession的实例蝗虫客户端支持cookies,因此在HTTP请求之间保持会话。

理解:在任务执行开始之前,首先会实例化一个HttpUser 对象,这个对象中有一个属性交client ,这个属性是一个HttpSession 的类型。

再来看看HttpSession,class HttpSession(requests.Session): 它继承了requests 的Session 类,并且重写了父类的requets 方法,重写方法中去处理了一些相应结果数据和请求数据,源码如下:

response = self._send_request_safe_mode(method, url, **kwargs)

        # record the consumed time
        request_meta["response_time"] = (time.monotonic() - request_meta["start_time"]) * 1000

        request_meta["name"] = name or (response.history and response.history[0] or response).request.path_url

        # get the length of the content, but if the argument stream is set to True, we take
        # the size from the content-length header, in order to not trigger fetching of the body
        if kwargs.get("stream", False):
            request_meta["content_size"] = int(response.headers.get("content-length") or 0)
        else:
            request_meta["content_size"] = len(response.content or b"")

        if catch_response:
            response.locust_request_meta = request_meta
            return ResponseContextManager(
                response, request_success=self.request_success, request_failure=self.request_failure
            )
        else:
            if name:
                # Since we use the Exception message when grouping failures, in order to not get
                # multiple failure entries for different URLs for the same name argument, we need
                # to temporarily override the response.url attribute
                orig_url = response.url
                response.url = name
            try:
                response.raise_for_status()
            except RequestException as e:
                self.request_failure.fire(
                    request_type=request_meta["method"],
                    name=request_meta["name"],
                    response_time=request_meta["response_time"],
                    response_length=request_meta["content_size"],
                    exception=e,
                )
            else:
                self.request_success.fire(
                    request_type=request_meta["method"],
                    name=request_meta["name"],
                    response_time=request_meta["response_time"],
                    response_length=request_meta["content_size"],
                )
            if name:
                response.url = orig_url
            return response

而请求方式是完全沿用父类方法,源码如下:

def _send_request_safe_mode(self, method, url, **kwargs):
        """
        Send an HTTP request, and catch any exception that might occur due to connection problems.

        Safe mode has been removed from requests 1.x.
        """
        try:
            #调用父类request.Session 的请求方法
            return super().request(method, url, **kwargs) 
        except (MissingSchema, InvalidSchema, InvalidURL):
            raise
        except RequestException as e:
            r = LocustResponse()
            r.error = e
            r.status_code = 0  # with this status_code, content returns None
            r.request = Request(method, url).prepare()
            return r

因此这里的请求方式完全符合requests库 的所有规范,不存在更多的学习成本。

测试集合

创建一个task_runner.py 文件

class User(HttpUser):
    tasks = [Server, Live] # 把所有可执行类收录进来,统一执行
    host = "https://baidu.com"

cmd 中进入工程目录:

locust -f tasks_runner.py 

然后打开web页面,设置用户上限和增长数 ,开始执行压测

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值