【问题标题】:Assign Locust task sets programmatically以编程方式分配 Locust 任务集
【发布时间】:2021-09-28 01:44:18
【问题描述】:

我正在尝试根据通过 UI 传递的主机值动态分配蝗虫任务。在这个例子中,如果 host 作为“hello”传入,测试应该运行 hello 任务,否则它应该运行 world 任务。

from locust import HttpUser, TaskSet, task, events

class RandomTask1(TaskSet):
  @task(1)
  def soemthing(self):
    print("Hello!")

class RandomTask2(TaskSet):
  @task(1)
  def soemthing(self):
    print("World!")

class LoadTestUser(HttpUser):
  def on_start(self):
    host_config = self.host
    if host_config == "hello":
      tasks = {RandomTask1:1}
    else:
      tasks = {RandomTask2:1}

下面的示例不起作用,我收到以下错误

Exception: No tasks defined on LoadTestUser. use the @task decorator or set the tasks property of the User (or mark it as abstract = True if you only intend to subclass it)

知道如何实现这样的目标吗?我已经为示例简化了这一点,但出于所有意图和目的,我们假设 locust 实例已经在运行并且无法停止或重新启动,并且需要动态分配任务。

编辑:

试过这样做:

class LoadTestUser(HttpUser):
    def on_start(self):
        if self.host == "hello":
            self.tasks = {HelloTask: 1}
        else:
            self.tasks = {WorldTask: 1}

    @task
    def nothing(self):
        pass

class HelloTask(TaskSet):
    @task
    def something(self):
        print("Hello")

class WorldTask(TaskSet):
    @task
    def something(self):
        print("World")

现在我看到以下错误:

Traceback (most recent call last):
  File "/Users/user/project/venv/lib/python3.8/site-packages/locust/user/task.py", line 285, in run
    self.schedule_task(self.get_next_task())
  File "/Users/user/project/venv/lib/python3.8/site-packages/locust/user/task.py", line 420, in get_next_task
    return random.choice(self.user.tasks)
  File "/Users/user/opt/anaconda3/lib/python3.8/random.py", line 291, in choice
    return seq[i]
KeyError: 0

【问题讨论】:

    标签: python performance-testing locust


    【解决方案1】:

    创建一个任务并将逻辑放入该任务中以使其运行。

    class LoadTestUser(HttpUser):
    
        def something1(self):
            print("Hello!")
    
        def something2(self):
            print("World!")
    
        @task
        def task_logic(self):
            if self.host == "hello":
                self.something1()
            else:
                self.something2()
    

    但是,您可以直接解决遇到的错误。即使您打算使用任务集覆盖或更改任务,您也需要在类中定义任务。有一个示例 in the documentation 但只需使用 pass 添加一个任务,这样它就不会做任何事情,那么您的覆盖应该可以工作。

    class LoadTestUser(HttpUser):
    
        def on_start(self):
            host_config = self.host
            if host_config == "hello":
                self.tasks = {RandomTask1:1}
            else:
                self.tasks = {RandomTask2:1}
    
        @task
        def nothing(self):
            pass
    

    编辑:应该工作,但看起来在当前版本的 Locust 中可能存在一个错误,它只在 Locust 首次启动时接受任务字典,然后只接受一个列表.在修复之前,其他答案中的示例有效。

    【讨论】:

    • 这将很难管理,因为我有很多任务和很多主机要处理。每种主机类型本质上都需要有自己的任务集,我想动态加载该任务集。
    • 如果没有更多信息,我想我不会理解。即使您有很多任务和主机要处理,这也是有效的。根据您提供的示例,这本质上是相同的,但更简单,您无需担心复杂性。但可能还有另一种方式。我可以编辑我的答案以添加另一个选项。
    • 你说得对,这适用于很多任务和主机,但如果我希望不同主机的任务权重不同,你有什么建议?
    • 可以处理自己的加权逻辑。你如何做这将取决于你想要什么,但它通常并不像起初看起来那么困难。通常只是另一个如果有随机数选择。如果您需要 2 个任务之间的 10:1 加权,如果 0 和 10 之间的随机为 0,则执行 1 任务,否则执行 10 任务。
    • 我尝试了你在第二个代码 sn-p 中的建议,看起来覆盖没有发生。我认为任务集需要在类加载时分配,而不是在跑步者是初学者时分配。此外,对于第一个 sn-p,请考虑这种情况:如果我有 2 个任务:task1 和 task2。对于 host1,我想要 1:1 的权重,如果它是 host2,我希望任务权重为 1:5。我该怎么做呢?
    【解决方案2】:
    import sys
    from locust import HttpUser, TaskSet, task, events
    
    class LoadTestUser(HttpUser):
        def locust_class(self, name):
            module = sys.modules[__name__]
            return getattr(module, f"{name.capitalize()}Task")
    
        def get_weighted_tasks(self, task_list):
            new_tasks = []
            for item in task_list:
                if "locust_task_weight" in dir(item):
                    for i in range(item.locust_task_weight):
                        new_tasks.append(item)
            return new_tasks
    
        def get_locust_tasks(self, cls):
            tasks = []
            for maybe_task in cls.__dict__.values():
                if hasattr(maybe_task, "locust_task_weight"):
                    tasks.append(maybe_task)
            return tasks
    
        def on_start(self):
            task_cls = self.locust_class(self.host)
            task_list = self.get_locust_tasks(task_cls)
            self.tasks = self.get_weighted_tasks(task_list)
    
        @task(1)
        def nothing(self):
            pass
    
    
    class HelloTask(TaskSet):
        @task(1)
        def something(self):
            print("Hello")
    
        @task(100)
        def something_else(self):
            print("hello")
    
    
    class WorldTask(TaskSet):
        @task(1)
        def something(self):
            print("World")
    
        @task(10)
        def something_else(self):
            print("world")
    

    【讨论】:

      猜你喜欢
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 2012-02-07
      • 2021-02-17
      • 2018-08-18
      • 2011-07-22
      相关资源
      最近更新 更多