From 4bc0f177b863823c02d5511a8dfd9910284180da Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Fri, 18 May 2018 14:05:10 +0200 Subject: [PATCH] docs: Syntax highlight code and commands --- docs/installation.rst | 20 +++++--- docs/quickstart.rst | 61 ++++++++++++++--------- docs/retrieving-stats.rst | 22 ++++++--- docs/running-locust-without-web-ui.rst | 14 ++++-- docs/writing-a-locustfile.rst | 68 +++++++++++++++++++------- 5 files changed, 124 insertions(+), 61 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index e79e579878..6d7fa33b43 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -3,7 +3,7 @@ Installation Locust is available on PyPI and can be installed through pip or easy_install -:: +.. code-block:: console pip install locustio @@ -11,9 +11,11 @@ Locust is available on PyPI and can be installed through pip or easy_install When Locust is installed, a **locust** command should be available in your shell (if you're not using virtualenv—which you should—make sure your python script directory is on your path). -To see available options, run:: +To see available options, run: - locust --help +.. code-block:: console + + $ locust --help Supported Python Versions @@ -33,9 +35,11 @@ the pre built binary packages for pyzmq, gevent and greenlet. You can find an unofficial collection of pre built python packages for windows here: `http://www.lfd.uci.edu/~gohlke/pythonlibs/ `_ -When you've downloaded a pre-built ``.whl`` file, you can install it with:: +When you've downloaded a pre-built ``.whl`` file, you can install it with: + +.. code-block:: console - pip install name-of-file.whl + $ pip install name-of-file.whl Once you've done that you should be able to just ``pip install locustio``. @@ -52,9 +56,11 @@ Installing Locust on OS X The following is currently the shortest path to installing gevent on OS X using Homebrew. #. Install `Homebrew `_. -#. Install libev (dependency for gevent):: +#. Install libev (dependency for gevent): + + .. code-block:: console - brew install libev + brew install libev #. Then follow the above instructions. diff --git a/docs/quickstart.rst b/docs/quickstart.rst index fabeb19604..b6d8dddca0 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -5,31 +5,34 @@ Quick start Example locustfile.py ===================== -Below is a quick little example of a simple **locustfile.py**:: +Below is a quick little example of a simple **locustfile.py**: + + +.. code-block:: python from locust import HttpLocust, TaskSet - + def login(l): l.client.post("/login", {"username":"ellen_key", "password":"education"}) - + def logout(l): l.client.post("/logout", {"username":"ellen_key", "password":"education"}) - + def index(l): l.client.get("/") - + def profile(l): l.client.get("/profile") - + class UserBehavior(TaskSet): tasks = {index: 2, profile: 1} - + def on_start(self): login(self) - + def on_stop(self): logout(self) - + class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 @@ -49,15 +52,17 @@ The :py:class:`HttpLocust ` class inherits from the :py:class:`HttpSession ` that can be used to make HTTP requests. Another way we could declare tasks, which is usually more convenient, is to use the -``@task`` decorator. The following code is equivalent to the above:: +``@task`` decorator. The following code is equivalent to the above: + +.. code-block:: python from locust import HttpLocust, TaskSet, task - + class UserBehavior(TaskSet): def on_start(self): """ on_start is called when a Locust start before any task is scheduled """ self.login() - + def on_stop(self): """ on_stop is called when the TaskSet is stopping """ self.logout() @@ -88,6 +93,8 @@ By default the time is randomly chosen uniformly between *min_wait* and *max_wai time distributions can be used by setting *wait_function* to any arbitrary function. For example, for an exponentially distributed wait time with average of 1 second: +.. code-block:: python + import random class WebsiteUser(HttpLocust): @@ -99,29 +106,39 @@ Start Locust ============ To run Locust with the above Locust file, if it was named *locustfile.py* and located in the current working -directory, we could run:: +directory, we could run: - locust --host=http://example.com +.. code-block:: console + + $ locust --host=http://example.com If the Locust file is located under a subdirectory and/or named different than *locustfile.py*, specify -it using ``-f``:: +it using ``-f``: + +.. code-block:: console - locust -f locust_files/my_locust_file.py --host=http://example.com + $ locust -f locust_files/my_locust_file.py --host=http://example.com To run Locust distributed across multiple processes we would start a master process by specifying -``--master``:: +``--master``: - locust -f locust_files/my_locust_file.py --master --host=http://example.com +.. code-block:: console -and then we would start an arbitrary number of slave processes:: + $ locust -f locust_files/my_locust_file.py --master --host=http://example.com - locust -f locust_files/my_locust_file.py --slave --host=http://example.com +and then we would start an arbitrary number of slave processes: + +.. code-block:: console + + $ locust -f locust_files/my_locust_file.py --slave --host=http://example.com If we want to run Locust distributed on multiple machines we would also have to specify the master host when starting the slaves (this is not needed when running Locust distributed on a single machine, since the master -host defaults to 127.0.0.1):: +host defaults to 127.0.0.1): + +.. code-block:: console - locust -f locust_files/my_locust_file.py --slave --master-host=192.168.0.100 --host=http://example.com + $ locust -f locust_files/my_locust_file.py --slave --master-host=192.168.0.100 --host=http://example.com .. note:: diff --git a/docs/retrieving-stats.rst b/docs/retrieving-stats.rst index d9de9465bf..7c6d49de02 100644 --- a/docs/retrieving-stats.rst +++ b/docs/retrieving-stats.rst @@ -7,31 +7,37 @@ You may wish to consume your Locust results via a CSV file. In this case, there First, when running Locust with the web UI, you can retrieve CSV files under the Download Data tab. Secondly, you can run Locust with a flag which will periodically save two CSV files. This is particularly useful -if you plan on running Locust in an automated way with the ``--no-web`` flag:: - - locust -f examples/basic.py --csv=example --no-web -t10m +if you plan on running Locust in an automated way with the ``--no-web`` flag: +.. code-block:: console + $ locust -f examples/basic.py --csv=example --no-web -t10m The files will be named ``example_distribution.csv`` and ``example_requests.csv`` (when using ``--csv=example``) and mirror Locust's built in stat pages. -You can also customize how frequently this is written if you desire faster (or slower) writing:: +You can also customize how frequently this is written if you desire faster (or slower) writing: + +.. code-block:: python import locust.stats locust.stats.CSV_STATS_INTERVAL_SEC = 5 # default is 2 seconds -This data will write two files with ``_distribution.csv`` and ``_requests.csv`` added to the name you give:: +This data will write two files with ``_distribution.csv`` and ``_requests.csv`` added to the name you give: - $cat example_distribution.csv +.. code-block:: console + + $ cat example_distribution.csv "Name","# requests","50%","66%","75%","80%","90%","95%","98%","99%","100%" "GET /",31,4,4,4,4,4,4,4,4,4 "/does_not_exist",0,"N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A" "GET /stats/requests",38,3,4,4,4,4,5,5,5,5 "None Total",69,3,4,4,4,4,4,5,5,5 -and:: +and: + +.. code-block:: console - $cat example_requests.csv + $ cat example_requests.csv "Method","Name","# requests","# failures","Median response time","Average response time","Min response time","Max response time","Average Content Size","Requests/s" "GET","/",51,0,4,3,2,6,12274,0.89 "GET","/does_not_exist",0,56,0,0,0,0,0,0.00 diff --git a/docs/running-locust-without-web-ui.rst b/docs/running-locust-without-web-ui.rst index d9155858e5..3b83963545 100644 --- a/docs/running-locust-without-web-ui.rst +++ b/docs/running-locust-without-web-ui.rst @@ -5,10 +5,12 @@ Running Locust without the web UI ================================= You can run locust without the web UI - for example if you want to run it in some automated flow, -like a CI server - by using the ``--no-web`` flag together with ``-c`` and ``-r``:: +like a CI server - by using the ``--no-web`` flag together with ``-c`` and ``-r``: + +.. code-block:: console + + $ locust -f locust_files/my_locust_file.py --no-web -c 1000 -r 100 - locust -f locust_files/my_locust_file.py --no-web -c 1000 -r 100 - ``-c`` specifies the number of Locust users to spawn, and ``-r`` specifies the hatch rate (number of users to spawn per second). @@ -20,9 +22,11 @@ Setting a time limit for the test This is a new feature in v0.9. For 0.8 use ``-n`` to specify the number of requests -If you want to specify the run time for a test, you can do that with ``--run-time`` or ``-t``:: +If you want to specify the run time for a test, you can do that with ``--run-time`` or ``-t``: + +.. code-block:: console - locust -f --no-web -c 1000 -r 100 --run-time 1h30m + $ locust -f --no-web -c 1000 -r 100 --run-time 1h30m Locust will shutdown once the time is up. diff --git a/docs/writing-a-locustfile.rst b/docs/writing-a-locustfile.rst index 823b90aedb..de7099d670 100644 --- a/docs/writing-a-locustfile.rst +++ b/docs/writing-a-locustfile.rst @@ -27,7 +27,9 @@ attributes. These are the minimum and maximum time respectively, in milliseconds 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. -With the following locustfile, each user would wait between 5 and 15 seconds between tasks:: +With the following locustfile, each user would wait between 5 and 15 seconds between tasks: + +.. code-block:: python from locust import Locust, TaskSet, task @@ -46,20 +48,24 @@ The *min_wait* and *max_wait* attributes can also be overridden in a TaskSet cla The *weight* attribute ---------------------- -You can run two locusts from the same file like so:: +You can run two locusts from the same file like so: + +.. code-block:: console - locust -f locust_file.py WebUserLocust MobileUserLocust + $ locust -f locust_file.py WebUserLocust MobileUserLocust If you wish to make one of these locusts execute more often you can set a weight attribute on those -classes. Say for example, web users are three times more likely than mobile users:: +classes. Say for example, web users are three times more likely than mobile users: + +.. code-block:: python class WebUserLocust(Locust): weight = 3 - .... + ... class MobileUserLocust(Locust): weight = 1 - .... + ... The *host* attribute @@ -93,7 +99,9 @@ Declaring tasks The typical way of declaring tasks for a TaskSet it to use the :py:meth:`task ` decorator. -Here is an example:: +Here is an example: + +.. code-block:: python from locust import Locust, TaskSet, task @@ -106,7 +114,9 @@ Here is an example:: task_set = MyTaskSet **@task** takes an optional weight argument that can be used to specify the task's execution ratio. In -the following example *task2* will be executed twice as much as *task1*:: +the following example *task2* will be executed twice as much as *task1*: + +.. code-block:: python from locust import Locust, TaskSet, task @@ -136,7 +146,9 @@ just populate the *tasks* attribute). The *tasks* attribute is either a list of python callables, or a ** dict. The tasks are python callables that receive one argument—the TaskSet class instance that is executing -the task. Here is an extremely simple example of a locustfile (this locustfile won't actually load test anything):: +the task. Here is an extremely simple example of a locustfile (this locustfile won't actually load test anything): + +.. code-block:: python from locust import Locust, TaskSet @@ -155,7 +167,7 @@ chosen from the *tasks* attribute. If however, *tasks* is a dict—with callable as values—the task that is to be executed will be chosen at random but with the int as ratio. So with a tasks that looks like this:: - {my_task: 3, another_task:1} + {my_task: 3, another_task: 1} *my_task* would be 3 times more likely to be executed than *another_task*. @@ -187,7 +199,9 @@ we could define TaskSets with the following structure: * About page The way you nest TaskSets is just like when you specify a task using the **tasks** attribute, but -instead of referring to a python function, you refer to another TaskSet:: +instead of referring to a python function, you refer to another TaskSet: + +.. code-block:: python class ForumPage(TaskSet): @task(20) @@ -222,7 +236,9 @@ But by having the interrupt function, we can—together with task weighting—de is that a simulated user leaves the forum. It's also possible to declare a nested TaskSet, inline in a class, using the -:py:meth:`@task ` decorator, just like when declaring normal tasks:: +:py:meth:`@task ` decorator, just like when declaring normal tasks: + +.. code-block:: python class MyTaskSet(TaskSet): @task @@ -294,7 +310,9 @@ class exists. When using this class, each instance gets a When inheriting from the HttpLocust class, we can use its client attribute to make HTTP requests against the server. Here is an example of a locust file that can be used to load test a site -with two URLs; **/** and **/about/**:: +with two URLs; **/** and **/about/**: + +.. code-block:: python from locust import HttpLocust, TaskSet, task @@ -338,13 +356,17 @@ tasks. Here's a simple example that makes a GET request to the */about* path (in this case we assume *self* is an instance of a :py:class:`TaskSet ` or :py:class:`HttpLocust ` -class:: +class: + +.. code-block:: python response = self.client.get("/about") print("Response status code:", response.status_code) print("Response content:", response.text) -And here's an example making a POST request:: +And here's an example making a POST request: + +.. code-block:: python response = self.client.post("/login", {"username":"testuser", "password":"secret"}) @@ -366,7 +388,9 @@ return *200 OK* even though an error occurred—there's a need for manually cont locust should consider a request as a success or a failure. One can mark requests as failed, even when the response code is OK, by using the -*catch_response* argument and a with statement:: +*catch_response* argument and a with statement: + +.. code-block:: python with client.get("/", catch_response=True) as response: if response.content != b"Success": @@ -374,7 +398,9 @@ One can mark requests as failed, even when the response code is OK, by using the Just as one can mark requests with OK response codes as failures, one can also use **catch_response** argument together with a *with* statement to make requests that resulted in an HTTP error code still -be reported as a success in the statistics:: +be reported as a success in the statistics: + +.. code-block:: python with client.get("/does_not_exist/", catch_response=True) as response: if response.status_code == 404: @@ -389,7 +415,9 @@ Often it makes sense to group these URLs together in Locust's statistics. This c by passing a *name* argument to the :py:class:`HttpSession's ` different request methods. -Example:: +Example: + +.. code-block:: python # Statistics for these requests will be grouped under: /blog/?id=[id] for i in range(10): @@ -447,7 +475,9 @@ working directory) importable. * ``ecommerce.py`` -With the above project structure, your locust files can import common libraries using:: +With the above project structure, your locust files can import common libraries using: + +.. code-block:: python sys.path.append(os.getcwd()) import common.auth