Skip to content

Commit

Permalink
Merge pull request #1118 from locustio/wait_time
Browse files Browse the repository at this point in the history
New API for specifying wait time
  • Loading branch information
heyman authored Nov 13, 2019
2 parents c16dc71 + bb3ae02 commit 795b5a1
Show file tree
Hide file tree
Showing 27 changed files with 427 additions and 108 deletions.
14 changes: 10 additions & 4 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ Locust class
============

.. autoclass:: locust.core.Locust
:members: min_wait, max_wait, wait_function, task_set, weight
:members: wait_time, task_set, weight

HttpLocust class
================

.. autoclass:: locust.core.HttpLocust
:members: min_wait, max_wait, wait_function, task_set, client
:members: wait_time, task_set, client


TaskSet class
=============

.. autoclass:: locust.core.TaskSet
:members: locust, parent, min_wait, max_wait, wait_function, client, tasks, interrupt, schedule_task
:members: locust, parent, wait_time, client, tasks, interrupt, schedule_task

task decorator
==============
Expand All @@ -31,13 +31,19 @@ TaskSequence class
==================

.. autoclass:: locust.core.TaskSequence
:members: locust, parent, min_wait, max_wait, wait_function, client, tasks, interrupt, schedule_task
:members: locust, parent, wait_time, client, tasks, interrupt, schedule_task

seq_task decorator
==================

.. autofunction:: locust.core.seq_task

Built in wait_time functions
============================

.. automodule:: locust.wait_time
:members: between, constant, constant_pacing

HttpSession class
=================

Expand Down
5 changes: 2 additions & 3 deletions docs/increase-performance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ How to use FastHttpLocust

Subclass FastHttpLocust instead of HttpLocust::

from locust import TaskSet, task
from locust import TaskSet, task, between
from locust.contrib.fasthttp import FastHttpLocust
class MyTaskSet(TaskSet):
Expand All @@ -34,8 +34,7 @@ Subclass FastHttpLocust instead of HttpLocust::
class MyLocust(FastHttpLocust):
task_set = MyTaskSet
min_wait = 1000
max_wait = 60000
wait_time = between(1, 60)


.. note::
Expand Down
20 changes: 9 additions & 11 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Below is a quick little example of a simple **locustfile.py**:

.. code-block:: python
from locust import HttpLocust, TaskSet
from locust import HttpLocust, TaskSet, between
def login(l):
l.client.post("/login", {"username":"ellen_key", "password":"education"})
Expand All @@ -35,8 +35,7 @@ Below is a quick little example of a simple **locustfile.py**:
class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 5000
max_wait = 9000
wait_time = between(5.0, 9.0)
Here we define a number of Locust tasks, which are normal Python callables that take one argument
Expand All @@ -60,7 +59,7 @@ Another way we could declare tasks, which is usually more convenient, is to use

.. code-block:: python
from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between
class UserBehavior(TaskSet):
def on_start(self):
Expand All @@ -87,14 +86,13 @@ Another way we could declare tasks, which is usually more convenient, is to use
class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 5000
max_wait = 9000
wait_time = between(5, 9)
The :py:class:`Locust <locust.core.Locust>` class (as well as :py:class:`HttpLocust <locust.core.HttpLocust>`
since it's a subclass) also allows one to specify minimum and maximum wait time in milliseconds—per simulated
user—between the execution of tasks (*min_wait* and *max_wait*) as well as other user behaviours.
By default the time is randomly chosen uniformly between *min_wait* and *max_wait*, but any user-defined
time distributions can be used by setting *wait_function* to any arbitrary function.
since it's a subclass) also allows one to specify the wait time between the execution of tasks
(:code:`wait_time = between(5, 9)`) as well as other user behaviours.
With the between function the time is randomly chosen uniformly between the specified min and max values,
but any user-defined time distributions can be used by setting *wait_time* to any arbitrary function.
For example, for an exponentially distributed wait time with average of 1 second:

.. code-block:: python
Expand All @@ -103,7 +101,7 @@ For example, for an exponentially distributed wait time with average of 1 second
class WebsiteUser(HttpLocust):
task_set = UserBehaviour
wait_function = lambda self: random.expovariate(1)*1000
wait_time = lambda self: random.expovariate(1)*1000
Start Locust
Expand Down
59 changes: 39 additions & 20 deletions docs/writing-a-locustfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,58 @@ A locust class represents one user (or a swarming locust if you will). Locust wi
instance of the locust class for each user that is being simulated. There are a few attributes that
a locust class should typically define.

The :py:attr:`task_set <locust.core.Locust.task_set>` attribute
---------------------------------------------------------------
The *task_set* attribute
------------------------

The :py:attr:`task_set <locust.core.Locust.task_set>` attribute should point to a
:py:class:`TaskSet <locust.core.TaskSet>` class which defines the behaviour of the user and
is described in more detail below.

The *min_wait* and *max_wait* attributes
----------------------------------------
The *wait_time* attribute
-------------------------

In addition to the *task_set* attribute, one should also declare a
:py:attr:`wait_time <locust.core.Locust.wait_time>` method. It's used to determine
for how long a simulated user will wait between executing tasks. Locust comes with a few built in
functions that return a few common wait_time methods.

In addition to the task_set attribute, one usually wants to declare the *min_wait* and *max_wait*
attributes. These are the minimum and maximum time respectively, in milliseconds, that a simulated user will wait
between executing each task. *min_wait* and *max_wait* default to 1000, and therefore a locust will
always wait 1 second between each task if *min_wait* and *max_wait* are not declared.
The most common one is :py:attr:`between <locust.wait_time.between>`. It's used to make the simulated
users wait a random time between a min and max value after each task execution. Other built in
wait time functions are :py:attr:`constant <locust.wait_time.constant>` and
:py:attr:`constant_pacing <locust.wait_time.constant_pacing>`.

With the following locustfile, each user would wait between 5 and 15 seconds between tasks:

.. code-block:: python
from locust import Locust, TaskSet, task
from locust import Locust, TaskSet, task, between
class MyTaskSet(TaskSet):
@task
def my_task(self):
print("executing my_task")
class User(Locust):
task_set = MyTaskSet
wait_time = between(5, 15)
The wait_time method should return a number of seconds (or fraction of a second) and can also
be declared on a TaskSet class, in which case it will only be used for that TaskSet.

It's also possible to declare your own wait_time method directly on a Locust or TaskSet class. The
following locust class would start sleeping for one second and then one, two, three, etc.

.. code-block:: python
class MyLocust(Locust):
task_set = MyTaskSet
min_wait = 5000
max_wait = 15000
last_wait_time = 0
def wait_time(self):
self.last_wait_time += 1
return self.last_wait_time
The *min_wait* and *max_wait* attributes can also be overridden in a TaskSet class.
The *weight* attribute
----------------------
Expand Down Expand Up @@ -94,9 +114,9 @@ and—if we were load-testing an auction website—could do stuff like "loading

When a load test is started, each instance of the spawned Locust classes will start executing their
TaskSet. What happens then is that each TaskSet will pick one of its tasks and call it. It will then
wait a number of milliseconds, chosen at random between the Locust class' *min_wait* and *max_wait* attributes
(unless min_wait/max_wait have been defined directly under the TaskSet, in which case it will use
its own values instead). Then it will again pick a new task to be called, wait again, and so on.
wait a number of seconds, specified by the Locust class' *wait_time* method (unless a *wait_time*
method has been declared directly on the TaskSet, in which case it will use its own method instead).
Then it will again pick a new task to be called, wait again, and so on.

Declaring tasks
---------------
Expand All @@ -123,10 +143,10 @@ the following example *task2* will be executed twice as much as *task1*:
.. code-block:: python
from locust import Locust, TaskSet, task
from locust.wait_time import between
class MyTaskSet(TaskSet):
min_wait = 5000
max_wait = 15000
wait_time = between(5, 15)
@task(3)
def task1(self):
Expand Down Expand Up @@ -343,7 +363,7 @@ with two URLs; **/** and **/about/**:

.. code-block:: python
from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between
class MyTaskSet(TaskSet):
@task(2)
Expand All @@ -356,8 +376,7 @@ with two URLs; **/** and **/about/**:
class MyLocust(HttpLocust):
task_set = MyTaskSet
min_wait = 5000
max_wait = 15000
wait_time = between(5, 15)
Using the above Locust class, each simulated user will wait between 5 and 15 seconds
between the requests, and **/** will be requested twice as much as **/about/**.
Expand Down
5 changes: 2 additions & 3 deletions examples/basic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between


def index(l):
Expand All @@ -21,6 +21,5 @@ class WebsiteUser(HttpLocust):
Locust user class that does requests to the locust web server running on localhost
"""
host = "http://127.0.0.1:8089"
min_wait = 2000
max_wait = 5000
wait_time = between(2, 5)
task_set = UserTasks
5 changes: 2 additions & 3 deletions examples/browse_docs_sequence_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# browsing the Locust documentation on https://docs.locust.io/

import random
from locust import HttpLocust, TaskSequence, seq_task, task
from locust import HttpLocust, TaskSequence, seq_task, task, between
from pyquery import PyQuery


Expand Down Expand Up @@ -46,5 +46,4 @@ class AwesomeUser(HttpLocust):
# generally has a quite long waiting time (between
# 20 and 600 seconds), since there's a bunch of text
# on each page
min_wait = 20 * 1000
max_wait = 600 * 1000
wait_time = between(20, 600)
5 changes: 2 additions & 3 deletions examples/browse_docs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# browsing the Locust documentation on https://docs.locust.io/

import random
from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between
from pyquery import PyQuery


Expand Down Expand Up @@ -45,5 +45,4 @@ class AwesomeUser(HttpLocust):
# generally has a quite long waiting time (between
# 20 and 600 seconds), since there's a bunch of text
# on each page
min_wait = 20 * 1000
max_wait = 600 * 1000
wait_time = between(20, 600)
4 changes: 2 additions & 2 deletions examples/custom_wait_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class WebsiteUser(HttpLocust):
host = "http://127.0.0.1:8089"
# Most task inter-arrival times approximate to exponential distributions
# We will model this wait time as exponentially distributed with a mean of 1 second
wait_function = lambda self: random.expovariate(1)*1000 # *1000 to convert to milliseconds
wait_time = lambda self: random.expovariate(1)
task_set = UserTasks

def strictExp(min_wait,max_wait,mu=1):
Expand All @@ -43,7 +43,7 @@ class StrictWebsiteUser(HttpLocust):
Locust user class that makes exponential requests but strictly between two bounds.
"""
host = "http://127.0.0.1:8089"
wait_function = lambda self: strictExp(self.min_wait, self.max_wait)*1000
wait_time = lambda self: strictExp(3, 7)
task_set = UserTasks


Expand Down
5 changes: 2 additions & 3 deletions examples/custom_xmlrpc_client/xmlrpc_locustfile.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import time
import xmlrpclib

from locust import Locust, TaskSet, events, task
from locust import Locust, TaskSet, events, task, between


class XmlRpcClient(xmlrpclib.ServerProxy):
Expand Down Expand Up @@ -41,8 +41,7 @@ def __init__(self, *args, **kwargs):
class ApiUser(XmlRpcLocust):

host = "http://127.0.0.1:8877/"
min_wait = 100
max_wait = 1000
wait_time = between(0.1, 1)

class task_set(TaskSet):
@task(10)
Expand Down
5 changes: 2 additions & 3 deletions examples/dynamice_user_credentials.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# locustfile.py

from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between

USER_CREDENTIALS = [
("user1", "password"),
Expand All @@ -21,5 +21,4 @@ def some_task(self):

class User(HttpLocust):
task_set = UserBehaviour
min_wait = 5000
max_wait = 60000
wait_time = between(5, 60)
5 changes: 2 additions & 3 deletions examples/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
track the sum of the content-length header in all successful HTTP responses
"""

from locust import HttpLocust, TaskSet, events, task, web
from locust import HttpLocust, TaskSet, events, task, web, between


class MyTaskSet(TaskSet):
Expand All @@ -19,8 +19,7 @@ def stats(l):

class WebsiteUser(HttpLocust):
host = "http://127.0.0.1:8089"
min_wait = 2000
max_wait = 5000
between(2, 5)
task_set = MyTaskSet


Expand Down
5 changes: 2 additions & 3 deletions examples/fast_http_locust.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between
from locust.contrib.fasthttp import FastHttpLocust


Expand All @@ -18,7 +18,6 @@ class WebsiteUser(FastHttpLocust):
using the fast HTTP client
"""
host = "http://127.0.0.1:8089"
min_wait = 2000
max_wait = 5000
wait_time = between(2, 5)
task_set = UserTasks

5 changes: 2 additions & 3 deletions examples/multiple_hosts.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

from locust import HttpLocust, TaskSet, task
from locust import HttpLocust, TaskSet, task, between
from locust.clients import HttpSession

class MultipleHostsLocust(HttpLocust):
Expand All @@ -26,6 +26,5 @@ class WebsiteUser(MultipleHostsLocust):
Locust user class that does requests to the locust web server running on localhost
"""
host = "http://127.0.0.1:8089"
min_wait = 2000
max_wait = 5000
wait_time = between(2, 5)
task_set = UserTasks
Loading

0 comments on commit 795b5a1

Please sign in to comment.