Coderead: Locust
- Github
-
Load testing tool written in Python
- Simple makefile
- Uses vagrant to create a local vm for testing
- Uses flask for a web admin ui
- TIL flask has extensions for cors, basicauth!
- eg Extension naming convention flask-basicauth
- locust/web.py has the flask webapp
- Very nicely factored
- Not an SPA. Templating language used (jinja2?) with server side rendering (SSR). I guess you can still build apps this way! It saves a bunch of complexity setting up build tools for an asset pipeline if the framework you’re using doesn’t give you that for free which flask does not I guess
- Bumped into type hinting today again. It’s been awhile since I’ve read python code so it took a few minutes to get myself oriented :)
- Interesting that code docs appear after symbols … :/
class WebUI:
"""
Sets up and runs a Flask web app that can start and stop load tests using the
:attr:`environment.runner <locust.env.Environment.runner>` as well as show the load test statistics
in :attr:`environment.stats <locust.env.Environment.stats>`
"""
app: Optional[Flask] = None
"""
Reference to the :class:`flask.Flask` app. Can be used to add additional web routes and customize
the Flask app in other various ways. Example::
from flask import request
@web_ui.app.route("/my_custom_route")
def my_custom_route():
return "your IP is: %s" % request.remote_addr
"""
greenlet: Optional[gevent.Greenlet] = None
"""
Greenlet of the running web server
"""
...
- Here’s the task decorator where we describe load test user scripts
def task(weight: TaskT | int = 1) -> TaskT | Callable[[TaskT], TaskT]:
"""
Used as a convenience decorator to be able to declare tasks for a User or a TaskSet
inline in the class. Example::
class ForumPage(TaskSet):
@task(100)
def read_thread(self):
pass
@task(7)
def create_thread(self):
pass
@task(25)
class ForumThread(TaskSet):
@task
def get_author(self):
pass
@task
def get_created(self):
pass
"""
def decorator_func(func):
if func.__name__ in ["on_stop", "on_start"]:
logging.warning(
"You have tagged your on_stop/start function with @task. This will make the method get called both as a task AND on stop/start."
) # this is usually not what the user intended
if func.__name__ == "run":
raise Exception(
"User.run() is a method used internally by Locust, and you must not override it or register it as a task"
)
func.locust_task_weight = weight
return func
"""
Check if task was used without parentheses (not called), like this::
@task
def my_task()
pass
"""
if callable(weight):
func = weight
weight = 1
return decorator_func(func)
else:
return decorator_func