Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SequentialTaskSet improvements #1579

Merged
merged 1 commit into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 13 additions & 20 deletions docs/writing-a-locustfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -388,39 +388,32 @@ within a nested TaskSet, locust will execute that task even if the TaskSet isn't
SequentialTaskSet class
=======================

:py:class:`SequentialTaskSet <locust.SequentialTaskSet>` is a TaskSet but its
tasks will be executed in the order that they are declared. Weights are ignored for tasks on a
SequentialTaskSet class. It is possible to nest SequentialTaskSets within a TaskSet and vice versa.
:py:class:`SequentialTaskSet <locust.SequentialTaskSet>` is a TaskSet whose tasks will be executed
in the order that they are declared. It is possible to nest SequentialTaskSets
within a TaskSet and vice versa.

For example, the following code will request URLs /1-/4 in order, and then repeat.

.. code-block:: python

def function_task(taskset):
pass
taskset.client.get("/3")

class SequenceOfTasks(SequentialTaskSet):
@task
def first_task(self):
pass
self.client.get("/1")
self.client.get("/2")

# you can still use the tasks property to specify a list of tasks
tasks = [function_task]

@task
def second_task(self):
pass

@task
def third_task(self):
pass

In the above example, the tasks are executed in the order of declaration:

1. ``first_task``
2. ``function_task``
3. ``second_task``
4. ``third_task``

and then it will start over at ``first_task`` again.
def last_task(self):
self.client.get("/4")

Note that you dont need SequentialTaskSets to just do some requests in order. It is often easier to
just do a whole user flow in a single task.

.. _on-start-on-stop:

Expand Down
2 changes: 2 additions & 0 deletions examples/browse_docs_sequence_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def index_page(self):
pq = PyQuery(r.content)
link_elements = pq(".toctree-wrapper a.internal")
self.toc_urls = [l.attrib["href"] for l in link_elements]
# it is fine to do multiple requests in a single task, you dont need SequentialTaskSet for that
self.client.get("/favicon.ico")

@task
def load_page(self, url=None):
Expand Down
4 changes: 3 additions & 1 deletion locust/user/sequential_taskset.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
from locust.exception import LocustError
from .task import TaskSet, TaskSetMeta

Expand Down Expand Up @@ -28,7 +29,8 @@ def __new__(mcs, classname, bases, class_dict):

if "locust_task_weight" in dir(value):
# method decorated with @task
new_tasks.append(value)
for _ in range(value.locust_task_weight):
new_tasks.append(value)

class_dict["tasks"] = new_tasks
return type.__new__(mcs, classname, bases, class_dict)
Expand Down
4 changes: 2 additions & 2 deletions locust/user/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,14 @@ def get_tasks_from_base_classes(bases, class_dict):
for task in tasks:
if isinstance(task, tuple):
task, count = task
for i in range(count):
for _ in range(count):
new_tasks.append(task)
else:
new_tasks.append(task)

for item in class_dict.values():
if "locust_task_weight" in dir(item):
for i in range(0, item.locust_task_weight):
for i in range(item.locust_task_weight):
new_tasks.append(item)

return new_tasks
Expand Down