locust学习教程(8) - event 事件

目录

1、对请求的测试前置、后置处理

2、在web界面添加新内容

3、监听测试的失败率或阀值

4、汇总总结

更多干货


1、对请求的测试前置、后置处理

  请求有一个上下文参数,通过数据有关的请求(之类的用户名,标签等)。它可以通过覆盖 User.context() 方法直接在对请求方法的调用中或在用户级别设置。

class MyUser(HttpUser):
    def context(self):
        return {"username": self.username}

    @task
    def t(self):
        self.username = "foo"
        self.client.post("/login", json={"username": self.username})

    @events.request.add_listener
    def on_request(context, **kwargs):
        print(context["username"])

2、在web界面添加新内容

  Locust 使用 Flask 为 Web UI 提供服务,因此很容易将 Web 端点添加到 Web UI。通过侦听init事件,我们可以检索对 Flask 应用程序实例的引用,并使用它来设置新路由:

from locust import events

@events.init.add_listener
def on_locust_init(environment, **kw):
    @environment.web_ui.app.route("/added_page")
    def my_added_page():
        return "Another page"

访问网址:http://localhost:8089/ added_pa​​ge

3、监听测试的失败率或阀值

from locust import events
from locust.runners import STATE_STOPPING, STATE_STOPPED, STATE_CLEANUP, WorkerRunner

def checker(environment):
    while not environment.runner.state in [STATE_STOPPING, STATE_STOPPED, STATE_CLEANUP]:
        time.sleep(1)
        if environment.runner.stats.total.fail_ratio > 0.2:
            print(f"fail ratio was {environment.runner.stats.total.fail_ratio}, quitting")
            environment.runner.quit()
            return


@events.init.add_listener
def on_locust_init(environment, **_kwargs):
    # only run this on master & standalone
    if not isinstance(environment.runner, WorkerRunner):
        gevent.spawn(checker, environment)

4、汇总总结

import datetime
import json
import logging
import time
import gevent
import requests
from locust import task, HttpUser, between
from locust import events
from locust.runners import MasterRunner
from locust.runners import STATE_STOPPING, STATE_STOPPED, STATE_CLEANUP, WorkerRunner


# 这里主要是 event hooks 的示例,用于各种测试监听,测试前置、后置、每个任务请求后的处理等等。


def timestring():
    """
    解析locustfile,比其他任何事情都要早
    :return:
    """
    now = datetime.datetime.now()
    return datetime.datetime.strftime(now, "%m:%S.%f")[:-5]


global_test_data = requests.post("https://postman-echo.com/post",
                                 data="global_test_data_" + timestring(),).json()["data"]
test_run_specific_data = None


def checker(environment):
    """
    定义了失败率判断的函数,主要用于 @events.init.add_listener 进行监听
    :param environment:
    :return:
    """
    while not environment.runner.state in [STATE_STOPPING, STATE_STOPPED, STATE_CLEANUP]:
        time.sleep(1)
        if environment.runner.stats.total.fail_ratio > 0.2:
            print(f"fail ratio was {environment.runner.stats.total.fail_ratio}, quitting")
            environment.runner.quit()
            return


@events.init.add_listener
def on_locust_init(environment, **_kwargs):
    """
    监控测试的失败率并在超过某个阈值时(0.2)停止运行
    :param environment:
    :param _kwargs:
    :return:
    """
    # only run this on master & standalone
    if not isinstance(environment.runner, WorkerRunner):
        gevent.spawn(checker, environment)


@events.init.add_listener
def on_locust_init(environment, **kw):
    """
    添加web界面,可以直接访问:http://localhost:8089/added_page,用于自定义拓展web界面
    源码有拓展的示例
    """
    @environment.web_ui.app.route("/added_page")
    def my_added_page():
        return "Another page"


@events.init.add_listener
def _(environment, **_kwargs):
    """
    初始化蝗虫,发生在解析蝗虫文件之后但测试开始之前,比如增加额外的web界面
    """
    print("2. Initializing locust, happens after parsing the locustfile but before test start")


@events.quitting.add_listener
def _(environment, **_kwargs):
    print("locust is shutting down")


@events.quitting.add_listener
def _(environment, **kw):
    """
    如果满足以下任何条件,则将退出代码设置为非零:
    超过 1% 的请求失败
    平均响应时间大于 200 ms
    响应时间的第 95 个百分位数大于 800 毫秒
    """
    if environment.stats.total.fail_ratio > 0.01:
        logging.error("Test failed due to failure ratio > 1%")
        environment.process_exit_code = 1
    elif environment.stats.total.avg_response_time > 200:
        logging.error("Test failed due to average response time ratio > 200 ms")
        environment.process_exit_code = 1
    elif environment.stats.total.get_response_time_percentile(0.95) > 800:
        logging.error("Test failed due to 95th percentile response time > 800 ms")
        environment.process_exit_code = 1
    else:
        environment.process_exit_code = 0


@events.test_start.add_listener
def _(environment, **_kwargs):
    """
    在headless运行中仅发生一次,但在web ui运行中可能发生多次
    在分布式运行中,主机通常不需要任何测试数据
    :param environment:
    :param _kwargs:
    :return:
    """
    global test_run_specific_data
    print("3. Starting test run")
    if not isinstance(environment.runner, MasterRunner):
        test_run_specific_data = requests.post(
            "https://postman-echo.com/post",
            data="test-run-specific_" + timestring(),
        ).json()["data"]


@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    """
    在分布式模式下运行 locust 时,在运行测试之前在工作节点上进行一些设置可能会很有用。
    可以通过检查节点的类型来检查以确保您没有在主节点上运行runner
    :param environment:
    :param kwargs:
    :return:
    """
    if not isinstance(environment.runner, MasterRunner):
        print("Beginning test setup")
    else:
        print("Started test from Master node")


@events.test_stop.add_listener
def _(environment, **_kwargs):
    print("stopping test run")


@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
    """
    监听测试执行,执行结束后,自动清楚数据
    :param environment:
    :param kwargs:
    :return:
    """
    if not isinstance(environment.runner, MasterRunner):
        print("Cleaning up test data")
    else:
        print("Stopped test from Master node")


@events.request.add_listener
def my_request_handler(request_type, name, response_time, response_length, response,
                       context, exception, start_time, url, **kwargs):
    """
    对所有的类添加监听器:每个类的任务执行完成后,定义了输出响应的相关内容,这个可以放到locufile文件里面
    """
    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 UserBehavior1(HttpUser):
    """
    登录
    """
    host = "https://yyy.com"
    wait_time = between(2, 5)  # 每个任务执行后等待2-5秒

    @task  # Locust 创建一个 greenlet(微线程),一个微线程可以跑很多协程
    def test_login(self):
        data = json.dumps({
            "user1": "tfjiao",
        })
        self.username = "xxx"
        headers = {"Content-Type": "application/json"}
        r = self.client.post("/api/login", data=data, headers=headers)

    def context(self):
        """
        :return: context 用于请求的监听,自定义输出内容
        """
        return {"username": self.username}

    # request context
    # 给userbehaver1类设置了请求的监听,触发什么时候,执行什么操作,这里执行打印操作
    @events.request.add_listener
    def on_request(context, **kwargs):
        if context:
            print(context["username"])

更多干货


 

完整版文档下载方式:

这些资料,对于从事【软件测试】等相关工作的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享。

在评论区和我互动交流或者私❤我【软件测试学习】领取即可,拿走不谢。


如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “✍️评论” “收藏” 一键三连哦!

你可能感兴趣的:(性能测试,软件测试,压力测试,软件测试,性能测试,locust,程序人生)