diff --git a/README.md b/README.md index eae0422c05..cb447e2980 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Even though Locust primarily works with web sites/services, it can be used to te ## Hackable -Locust is small and very flexible and we intend to keep it that way. If you want to [send reporting data to that database & graphing system you like](https://github.com/SvenskaSpel/locust-plugins/blob/master/locust_plugins/listeners.py), wrap calls to a REST API to handle the particulars of your system or run a [totally custom load pattern](https://docs.locust.io/en/latest/generating-custom-load-shape.html#generating-custom-load-shape), there is nothing stopping you! +Locust is small and very flexible and we intend to keep it that way. If you want to [send reporting data to that database & graphing system you like](https://github.com/SvenskaSpel/locust-plugins/blob/master/locust_plugins/listeners.py), wrap calls to a REST API to handle the particulars of your system or run a [totally custom load pattern](https://docs.locust.io/en/latest/custom-load-shape.html#custom-load-shape), there is nothing stopping you! ## Links diff --git a/docs/conf.py b/docs/conf.py index 14d1208837..27aa7e810e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -79,7 +79,13 @@ def save_locust_env_variables(): # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx_search.extension"] +extensions = [ + "sphinx-prompt", + "sphinx_substitution_extensions", + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx_search.extension", +] # autoclass options # autoclass_content = "both" @@ -169,3 +175,7 @@ def save_locust_env_variables(): # The name of the Pygments (syntax highlighting) style to use. # pygments_style = 'trac' + +rst_prolog = f""" +.. |version| replace:: {__version__} +""" diff --git a/docs/configuration.rst b/docs/configuration.rst index 2ba6bf1aa6..d04e40252d 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -66,7 +66,7 @@ Example: Configuration values are read (overridden) in the following order: - .. code-block:: + .. code-block:: console ~/locust.conf -> ./locust.conf -> (file specified using --conf) -> env vars -> cmd args diff --git a/docs/generating-custom-load-shape.rst b/docs/custom-load-shape.rst similarity index 94% rename from docs/generating-custom-load-shape.rst rename to docs/custom-load-shape.rst index a4ba760e73..696ecca56c 100644 --- a/docs/generating-custom-load-shape.rst +++ b/docs/custom-load-shape.rst @@ -1,8 +1,8 @@ -.. _generating-custom-load-shape: +.. _custom-load-shape: -============================== -Generating a custom load shape -============================== +================== +Custom load shapes +================== Sometimes a completely custom shaped load test is required that cannot be achieved by simply setting or changing the user count and spawn rate. For example, you might want to generate a load spike or ramp up and down at custom times. By using a `LoadTestShape` class you have full control over the user count and spawn rate at all times. diff --git a/docs/developing-locust-itself.rst b/docs/developing-locust.rst similarity index 63% rename from docs/developing-locust-itself.rst rename to docs/developing-locust.rst index 28c398c03e..7124adc0f4 100644 --- a/docs/developing-locust-itself.rst +++ b/docs/developing-locust.rst @@ -1,19 +1,34 @@ -======================================= -Developing Locust itself -======================================= +.. _developing-locust: -Here's useful information on making changes to Locust. +================= +Developing Locust +================= +You want to contribute to Locust? Great! Here is a list of `open bugs/feature requests `_. + +Install Locust for development +============================== + +Fork Locust on `Github `_ and then run + +.. code-block:: console + + $ git clone git://github.com//locust.git # clone the repo + $ pip3 install -e locust/ # install in editable mode + +Now the ``locust`` command will run *your* code with no need for reinstalling after making changes. + +Before you open a pull request, make sure the tests work. And if you are adding a feature, make sure it is documented. Running tests ============= -To be able to run Locust's test on different Python versions we use `tox `_. +To be able to run Locust's test on different Python versions we use `tox `_. You can install tox by running: .. code-block:: console - pip install tox + pip3 install tox Then you can run the tests by just invoking tox in the Locust project root directory: @@ -30,7 +45,7 @@ the following command in the Locust project's root directory: .. code-block:: console - pip install -r docs/requirements.txt + pip3 install -r docs/requirements.txt Then you can build the documentation locally using: diff --git a/docs/images/number_of_users.png b/docs/images/number_of_users.png new file mode 100644 index 0000000000..290a8bcf5c Binary files /dev/null and b/docs/images/number_of_users.png differ diff --git a/docs/images/response_times.png b/docs/images/response_times.png new file mode 100644 index 0000000000..7d480fb6e3 Binary files /dev/null and b/docs/images/response_times.png differ diff --git a/docs/images/total_requests_per_second.png b/docs/images/total_requests_per_second.png new file mode 100644 index 0000000000..22da4bd20f Binary files /dev/null and b/docs/images/total_requests_per_second.png differ diff --git a/docs/images/webui-running-charts.png b/docs/images/webui-running-charts.png deleted file mode 100644 index eb25729916..0000000000 Binary files a/docs/images/webui-running-charts.png and /dev/null differ diff --git a/docs/images/webui-running-statistics.png b/docs/images/webui-running-statistics.png index c53fef2f99..619727209c 100644 Binary files a/docs/images/webui-running-statistics.png and b/docs/images/webui-running-statistics.png differ diff --git a/docs/images/webui-splash-screenshot.png b/docs/images/webui-splash-screenshot.png index f5d74f85af..76c74c4c98 100644 Binary files a/docs/images/webui-splash-screenshot.png and b/docs/images/webui-splash-screenshot.png differ diff --git a/docs/index.rst b/docs/index.rst index bbab1c8556..622562bf65 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -40,8 +40,7 @@ Running your Locust tests configuration running-locust-distributed running-locust-docker - running-locust-without-web-ui - increase-performance + running-without-web-ui Other functionalities @@ -50,9 +49,10 @@ Other functionalities .. toctree :: :maxdepth: 2 - generating-custom-load-shape + custom-load-shape retrieving-stats testing-other-systems + increase-performance extending-locust logging use-as-lib @@ -64,7 +64,7 @@ Further reading / knowledgebase .. toctree :: :maxdepth: 1 - developing-locust-itself + developing-locust further-reading diff --git a/docs/installation.rst b/docs/installation.rst index 63c502b809..7c4963ec31 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -3,21 +3,23 @@ Installation ============ -`Install Python `_ 3.6 or later. +`Install Python `_ 3.6 or later, if you dont already have it. -Install Locust using pip. +Install Locust: .. code-block:: console $ pip3 install locust -Validate your installation and show the Locust version number: +Validate your installation. If this doesnt work, `check the wiki `_ for some possible solutions. .. code-block:: console + :substitutions: $ locust -V + locust |version| -If everything worked, move on to :ref:`quickstart`. If it did not, check out `the wiki `_ for some solutions. +Great! Now we're ready to create our first test: :ref:`quickstart` Bleeding edge version --------------------- @@ -25,4 +27,9 @@ If you need some feature or fix not yet part of a release: .. code-block:: console - $ pip3 install -e git://github.com/locustio/locust.git@master#egg=locust \ No newline at end of file + $ pip3 install -e git://github.com/locustio/locust.git@master#egg=locust + +Install for development +----------------------- + +If you want to modify Locust or contribute to the project, see :ref:`developing-locust`. diff --git a/docs/quickstart.rst b/docs/quickstart.rst index c224be7573..57abca71ec 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -1,158 +1,84 @@ .. _quickstart: -============= -Quick start -============= +=============== +Getting started +=============== -In Locust you define your user behaviour in Python code. You then use the ``locust`` command and (optionally) -its web interface to spawn and simulate a number of those users while gathering request statistics. - -Example locustfile.py -===================== +A Locust test is essentially a Python program. This makes it very flexible and particularly good at implementing complex user flows. But it can do simple tests as well, so lets start with that: .. code-block:: python - import time - from locust import HttpUser, task, between - - class QuickstartUser(HttpUser): - wait_time = between(1, 2.5) + from locust import HttpUser, task + class HelloWorldUser(HttpUser): @task def hello_world(self): self.client.get("/hello") self.client.get("/world") - - @task(3) - def view_items(self): - for item_id in range(10): - self.client.get(f"/item?id={item_id}", name="/item") - time.sleep(1) - - def on_start(self): - self.client.post("/login", json={"username":"foo", "password":"bar"}) - - -.. rubric:: Let's break it down - -.. code-block:: python - - import time - from locust import HttpUser, task, between - -A locust file is just a normal Python module, it can import code from other files or packages. - -.. code-block:: python - - class QuickstartUser(HttpUser): - -Here we define a class for the users that we will be simulating. It inherits from -:py:class:`HttpUser ` which gives each user a ``client`` attribute, -which is an instance of :py:class:`HttpSession `, that -can be used to make HTTP requests to the target system that we want to load test. When a test starts, -locust will create an instance of this class for every user that it simulates, and each of these -users will start running within their own green gevent thread. - -.. code-block:: python - - wait_time = between(1, 2.5) - -Our class defines a ``wait_time`` that will make the simulated users wait between 1 and 2.5 seconds after each task (see below) -is executed. For more info see :ref:`wait-time`. - -.. code-block:: python - - @task - def hello_world(self): - ... - -Methods decorated with ``@task`` are the core of your locust file. For every running user, -Locust creates a greenlet (micro-thread), that will call those methods. -.. code-block:: python - - @task - def hello_world(self): - self.client.get("/hello") - self.client.get("/world") - - @task(3) - def view_items(self): - ... - -We've declared two tasks by decorating two methods with ``@task``, one of which has been given a higher weight (3). -When our ``QuickstartUser`` runs it'll pick one of the declared tasks - in this case either ``hello_world`` or -``view_items`` - and execute it. Tasks are picked at random, but you can give them different weighting. The above -configuration will make Locust three times more likely to pick ``view_items`` than ``hello_world``. When a task has -finished executing, the User will then sleep during it's wait time (in this case between 1 and 2.5 seconds). -After it's wait time it'll pick a new task and keep repeating that. - -Note that only methods decorated with ``@task`` will be picked, so you can define your own internal helper methods any way you like. - -.. code-block:: python +This user will make HTTP requests to ``/hello``, and then ``/world``, again and again. For a full explanation and a more realistic example see :ref:`writing-a-locustfile`. - self.client.get("/hello") +Put the code in a file named *locustfile.py* in your current directory and run ``locust``: -The ``self.client`` attribute makes it possible to make HTTP calls that will be logged by Locust. For information on how -to make other kinds of requests, validate the response, etc, see -`Using the HTTP Client `_. - -.. code-block:: python - :emphasize-lines: 4,4 - - @task(3) - def view_items(self): - for item_id in range(10) - self.client.get(f"/item?id={item_id}", name="/item") - time.sleep(1) - -In the ``view_items`` task we load 10 different URLs by using a variable query parameter. -In order to not get 10 separate entries in Locust's statistics - since the stats is grouped on the URL - we use -the :ref:`name parameter ` to group all those requests under an entry named ``"/item"`` instead. - -.. code-block:: python - - def on_start(self): - self.client.post("/login", json={"username":"foo", "password":"bar"}) - -Additionally we've declared an `on_start` method. A method with this name will be called for each simulated -user when they start. For more info see :ref:`on-start-on-stop`. +.. code-block:: console + :substitutions: + $ locust + [2021-07-24 09:58:46,215] .../INFO/locust.main: Starting web interface at http://*:8089 + [2021-07-24 09:58:46,285] .../INFO/locust.main: Starting Locust |version| -Start Locust -============ +Locust's web interface +============================== -Put the above code in a file named *locustfile.py* in your current directory and run: +Once you've started Locust, open up a browser and point it to http://localhost:8089. You will be greeted with something like this: -.. code-block:: console +.. image:: images/webui-splash-screenshot.png +| - $ locust +Point the test to your own web server and try it out! +The following screenshots show what it might look like when running this test targeting 40 concurrent users with a ramp up speed of 0.5 users/s, pointed it to a server that responds to ``/hello`` and ``/world``. -If your Locust file is located somewhere else, you can specify it using ``-f`` +.. image:: images/webui-running-statistics.png -.. code-block:: console +You can also view the results as charts: - $ locust -f locust_files/my_locust_file.py +.. image:: images/total_requests_per_second.png +.. image:: images/response_times.png +.. image:: images/number_of_users.png .. note:: - To see all available options type: ``locust --help`` or check :ref:`configuration` - -Locust's web interface -============================== + Intepreting perfomance test results is quite complex (and mostly out of scope for this manual), but if your graphs start looking like this, the most likely reason is that your target service/system cannot handle the load you are hitting it with (it is overloaded or "saturated") -Once you've started Locust using one of the above command lines, you should open up a browser -and point it to http://127.0.0.1:8089. Then you should be greeted with something like this: + The clearest sign of this is that when we get to around 9 users, response times start increasing so fast that the requests per second-curve flattens out, even though new users are still being added. -.. image:: images/webui-splash-screenshot.png + If you're having trouble generating enough load to saturate your system, or need some pointers on how to start digging into a server side problem have a look at the `Locust FAQ `_ -Fill out the form and try it out! (but note that if you don't change your locust file to match your actual target system you'll mostly get error responses) -.. image:: images/webui-running-statistics.png +Direct command line usage / headless +==================================== -.. image:: images/webui-running-charts.png +Using the Locust web UI is entirely optional. You can supply the load parameters on command line and get reports on the results in text form: +.. code-block:: console + :substitutions: + + $ locust --headless --users 10 --spawn-rate 1 -H http://your-server.com + [2021-07-24 10:41:10,947] .../INFO/locust.main: No run time limit set, use CTRL+C to interrupt. + [2021-07-24 10:41:10,947] .../INFO/locust.main: Starting Locust |version| + [2021-07-24 10:41:10,949] .../INFO/locust.runners: Ramping to 10 users using a 1.00 spawn rate + Name # reqs # fails | Avg Min Max Median | req/s failures/s + ---------------------------------------------------------------------------------------------- + GET /hello 1 0(0.00%) | 115 115 115 115 | 0.00 0.00 + GET /world 1 0(0.00%) | 119 119 119 119 | 0.00 0.00 + ---------------------------------------------------------------------------------------------- + Aggregated 2 0(0.00%) | 117 115 119 117 | 0.00 0.00 + (...) + [2021-07-24 10:44:42,484] .../INFO/locust.runners: All users spawned: {"HelloWorldUser": 10} (10 total users) + (...) + +See :ref:`running-without-web-ui` for more details. More options ============ @@ -161,14 +87,11 @@ To run Locust distributed across multiple Python processes or machines, you can with the ``--master`` command line parameter, and then any number of Locust worker processes using the ``--worker`` command line parameter. See :ref:`running-locust-distributed` for more info. -To start tests directly, without using the web interface, use ``--headless``. - Parameters can also be set through :ref:`environment variables `, or in a :ref:`config file `. -To add/remove users during a headless run press w or W (1, 10) to spawn users and s or S to stop(1, 10). +To see all available options type: ``locust --help`` or check :ref:`configuration`. -How to write a *real* locust file? -"""""""""""""""""""""""""""""""""" +|  -The above example was just a small introduction, see :ref:`writing-a-locustfile` for more info. +Now, lets have a more in-depth look at locustfiles and what they can do: :ref:`writing-a-locustfile` \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt index 86c9b850d0..8449aec079 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,4 @@ sphinx==3.0.4 sphinx-rtd-theme==0.4.3 -e git+https://github.com/readthedocs/readthedocs-sphinx-search#egg=readthedocs-sphinx-search +Sphinx-Substitution-Extensions==2020.9.30.0 diff --git a/docs/running-locust-distributed.rst b/docs/running-locust-distributed.rst index 502aa15447..8e67bce089 100644 --- a/docs/running-locust-distributed.rst +++ b/docs/running-locust-distributed.rst @@ -1,7 +1,7 @@ .. _running-locust-distributed: =========================== -Running Locust distributed +Distributed load generation =========================== Once a single machine isn't enough to simulate the number of users that you need, Locust supports @@ -144,12 +144,6 @@ Running Locust distributed without the web UI See :ref:`running-locust-distributed-without-web-ui` -Generating a custom load shape using a `LoadTestShape` class -============================================================ - -See :ref:`generating-custom-load-shape` - - Increase Locust's performance ============================= diff --git a/docs/running-locust-docker.rst b/docs/running-locust-docker.rst index 11143e81ce..49b3a7f883 100644 --- a/docs/running-locust-docker.rst +++ b/docs/running-locust-docker.rst @@ -1,12 +1,12 @@ .. _running-locust-docker: -================================= -Running Locust with Docker -================================= +================= +Running in Docker +================= -The official Docker image is currently found at `locustio/locust `_. +The official Docker image is at `locustio/locust `_. -The docker image can be used like this (assuming that the ``locustfile.py`` exists in the current working directory):: +Use it like this (assuming that the ``locustfile.py`` exists in the current working directory):: docker run -p 8089:8089 -v $PWD:/mnt/locust locustio/locust -f /mnt/locust/locustfile.py @@ -37,8 +37,8 @@ official Locust docker image as a base image:: Running a distributed load test on Kubernetes ============================================= -The easiest way to run Locust on Kubernetes is to use a Helm chart. A Helm chart will package all settings and kubernetes resources together into an easy to manage way. +The easiest way to run Locust on Kubernetes is to use a `Helm chart `_ -Currently the most up to date Helm chart is here: `github.com/deliveryhero/helm-charts `_ +There is a good helm chart here: `github.com/deliveryhero/helm-charts `_ -Note: this Helm chart is not maintained or supported directly by Locust maintainers. +Note: this Helm chart is a separate project, and not supported by Locust maintainers. diff --git a/docs/running-locust-without-web-ui.rst b/docs/running-without-web-ui.rst similarity index 93% rename from docs/running-locust-without-web-ui.rst rename to docs/running-without-web-ui.rst index e2e2179bc3..9ba587913b 100644 --- a/docs/running-locust-without-web-ui.rst +++ b/docs/running-without-web-ui.rst @@ -1,7 +1,7 @@ -.. _running-locust-without-web-ui: +.. _running-without-web-ui: ================================= -Running Locust without the web UI +Running without the web UI ================================= You can run locust without the web UI - for example if you want to run it in some automated flow, @@ -14,6 +14,7 @@ like a CI server - by using the ``--headless`` flag together with ``-u`` and ``- ``-u`` specifies the number of Users to spawn, and ``-r`` specifies the spawn rate (number of users to start per second). +While the test is running you can change the user count manually, even after ramp up has finished. Pressing w to add 1 user or W to add 10. Press s to remove 1 or S to remove 10. Setting a time limit for the test --------------------------------- diff --git a/docs/use-as-lib.rst b/docs/use-as-lib.rst index 5feb574ed7..b7d8897f7a 100644 --- a/docs/use-as-lib.rst +++ b/docs/use-as-lib.rst @@ -4,9 +4,9 @@ Using Locust as a library ========================== -It's possible to use Locust as a library, instead of running Locust using the ``locust`` command. +It is possible to start a load test from your own Python code, instead of running Locust using the ``locust`` command. -To run Locust as a library you need to create an :py:class:`Environment ` instance: +Start by creating an :py:class:`Environment ` instance: .. code-block:: python @@ -26,6 +26,10 @@ The :py:class:`Environment ` instance's env.runner.start(5000, spawn_rate=20) env.runner.greenlet.join() +.. note:: + + Do not attempt to create a master runner and worker(s) in the same Python process. It does not work, and even if it did, it would not give you better performance than running a single LocalRunner. Every worker *must* run in its own process, there is no way around that. + We could also use the :py:class:`Environment ` instance's :py:meth:`create_web_ui ` method to start a Web UI that can be used to view the stats, and to control the runner (e.g. start and stop load tests): @@ -36,7 +40,6 @@ to view the stats, and to control the runner (e.g. start and stop load tests): env.create_web_ui() env.web_ui.greenlet.join() - Full example ============ diff --git a/docs/what-is-locust.rst b/docs/what-is-locust.rst index 71cb5cd413..0a8b21a813 100644 --- a/docs/what-is-locust.rst +++ b/docs/what-is-locust.rst @@ -42,7 +42,7 @@ Features * **Hackable** - Locust is small and very flexible and we intend to keep it that way. If you want to `send reporting data to that database & graphing system you like `_, wrap calls to a REST API to handle the particulars of your system or run a :ref:`totally custom load pattern `, there is nothing stopping you! + Locust is small and very flexible and we intend to keep it that way. If you want to `send reporting data to that database & graphing system you like `_, wrap calls to a REST API to handle the particulars of your system or run a :ref:`totally custom load pattern `, there is nothing stopping you! Name & background ================= diff --git a/docs/writing-a-locustfile.rst b/docs/writing-a-locustfile.rst index e1b8a3db6a..a52fc95d99 100644 --- a/docs/writing-a-locustfile.rst +++ b/docs/writing-a-locustfile.rst @@ -4,7 +4,116 @@ Writing a locustfile ====================== -A locustfile is a normal python file. The only requirement is that it declares at least one class that inherits from the class :py:class:`User `. +Now, lets look at a more complete/realistic example of what your tests might look like: + +.. code-block:: python + + import time + from locust import HttpUser, task, between + + class QuickstartUser(HttpUser): + wait_time = between(1, 5) + + @task + def hello_world(self): + self.client.get("/hello") + self.client.get("/world") + + @task(3) + def view_items(self): + for item_id in range(10): + self.client.get(f"/item?id={item_id}", name="/item") + time.sleep(1) + + def on_start(self): + self.client.post("/login", json={"username":"foo", "password":"bar"}) + + +.. rubric:: Let's break it down + +.. code-block:: python + + import time + from locust import HttpUser, task, between + +A locust file is just a normal Python module, it can import code from other files or packages. + +.. code-block:: python + + class QuickstartUser(HttpUser): + +Here we define a class for the users that we will be simulating. It inherits from +:py:class:`HttpUser ` which gives each user a ``client`` attribute, +which is an instance of :py:class:`HttpSession `, that +can be used to make HTTP requests to the target system that we want to load test. When a test starts, +locust will create an instance of this class for every user that it simulates, and each of these +users will start running within their own green gevent thread. + +For a file to be a valid locustfile it must contain at least one class inheriting from :py:class:`User `. + +.. code-block:: python + + wait_time = between(1, 5) + +Our class defines a ``wait_time`` that will make the simulated users wait between 1 and 5 seconds after each task (see below) +is executed. For more info see :ref:`wait-time`. + +.. code-block:: python + + @task + def hello_world(self): + ... + +Methods decorated with ``@task`` are the core of your locust file. For every running user, +Locust creates a greenlet (micro-thread), that will call those methods. + +.. code-block:: python + + @task + def hello_world(self): + self.client.get("/hello") + self.client.get("/world") + + @task(3) + def view_items(self): + ... + +We've declared two tasks by decorating two methods with ``@task``, one of which has been given a higher weight (3). +When our ``QuickstartUser`` runs it'll pick one of the declared tasks - in this case either ``hello_world`` or +``view_items`` - and execute it. Tasks are picked at random, but you can give them different weighting. The above +configuration will make Locust three times more likely to pick ``view_items`` than ``hello_world``. When a task has +finished executing, the User will then sleep during it's wait time (in this case between 1 and 5 seconds). +After it's wait time it'll pick a new task and keep repeating that. + +Note that only methods decorated with ``@task`` will be picked, so you can define your own internal helper methods any way you like. + +.. code-block:: python + + self.client.get("/hello") + +The ``self.client`` attribute makes it possible to make HTTP calls that will be logged by Locust. For information on how +to make other kinds of requests, validate the response, etc, see +`Using the HTTP Client `_. + +.. code-block:: python + + @task(3) + def view_items(self): + for item_id in range(10) + self.client.get(f"/item?id={item_id}", name="/item") + time.sleep(1) + +In the ``view_items`` task we load 10 different URLs by using a variable query parameter. +In order to not get 10 separate entries in Locust's statistics - since the stats is grouped on the URL - we use +the :ref:`name parameter ` to group all those requests under an entry named ``"/item"`` instead. + +.. code-block:: python + + def on_start(self): + self.client.post("/login", json={"username":"foo", "password":"bar"}) + +Additionally we've declared an `on_start` method. A method with this name will be called for each simulated +user when they start. For more info see :ref:`on-start-on-stop`. User class ========== @@ -20,7 +129,7 @@ wait_time attribute A User's :py:attr:`wait_time ` method is an optional attribute used to determine how long a simulated user should wait between executing tasks. If no :py:attr:`wait_time ` -is specified, a new task will be executed as soon as one finishes. +is specified, the next task will be executed as soon as one finishes. There are three built in wait time functions: @@ -28,8 +137,6 @@ There are three built in wait time functions: * :py:attr:`between ` for a random time between a min and max value -* :py:attr:`constant_pacing ` for an adaptive time that ensures the task runs (at most) once every X seconds - For example, to make each user wait between 0.5 and 10 seconds between every task execution: .. code-block:: python @@ -43,6 +150,10 @@ For example, to make each user wait between 0.5 and 10 seconds between every tas wait_time = between(0.5, 10) +* :py:attr:`constant_pacing ` for an adaptive time that ensures the task runs (at most) once every X seconds + +This is very useful if you want to target a specific throughput. For example, if you want Locust to run 500 task iterations per second at peak load, you could use `wait_time = constant_pacing(10)` and a user count of 5000. If the time for each iteration exceeds 10 seconds then you'll get lower throughput. Note that as wait time is applied *after* task execution, if you have a high spawn rate/ramp up you may slightly exceed your target during rampup. + It's also possible to declare your own wait_time method directly on your class. For example, the following User class would sleep for one second, then two, then three, etc. @@ -58,7 +169,6 @@ For example, the following User class would sleep for one second, then two, then ... - weight attribute ---------------- diff --git a/locust/main.py b/locust/main.py index 2aff5689bb..01fea3dd94 100644 --- a/locust/main.py +++ b/locust/main.py @@ -136,7 +136,7 @@ def main(): if options.step_time or options.step_load or options.step_users or options.step_clients: sys.stderr.write( - "The step load feature was removed in Locust 1.3. You can achieve similar results using a LoadTestShape class. See https://docs.locust.io/en/stable/generating-custom-load-shape.html\n" + "The step load feature was removed in Locust 1.3. You can achieve similar results using a LoadTestShape class. See https://docs.locust.io/en/stable/custom-load-shape.html\n" ) sys.exit(1) diff --git a/locust/templates/index.html b/locust/templates/index.html index f1750a5e2b..0fd2a4b0f0 100644 --- a/locust/templates/index.html +++ b/locust/templates/index.html @@ -59,17 +59,17 @@

Start new load test

{% if is_shape %} - +

- +

{% else %} - -
- -
+ +
+ +
{% endif %} {% endif %} -
+
@@ -92,15 +92,15 @@

Start new load test

Edit running load test

{% if is_shape %} - +
- +
{% else %} - -
- -
+ +
+ +
{% endif %} {% if is_shape %} diff --git a/locust/test/test_web.py b/locust/test/test_web.py index 6f4f87f14c..a8864377d4 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -94,8 +94,8 @@ def test_index_with_spawn_options(self): self.assertEqual(html_to_option[html_name][1], start_value) self.assertEqual(html_to_option[html_name][1], edit_value) else: - self.assertEqual("", start_value) - self.assertEqual("", edit_value) + self.assertEqual("1", start_value, msg=f"start value was {start_value} for {html_name}") + self.assertEqual("1", edit_value, msg=f"edit value was {edit_value} for {html_name}") def test_stats_no_data(self): self.assertEqual(200, requests.get("http://127.0.0.1:%i/stats/requests" % self.web_port).status_code)