Locust
Locust claims to be:
an easy to use, scriptable and scalable performance testing tool.
and to be more specific:
You define the behaviour of your users in regular Python code, instead of using a clunky UI or domain specific language
and the features include:
- Write user test scenarios in plain old Python
- Distributed & Scalable - supports hundreds of thousands of users
- Web-based UI
- Can test any system
- Hackable
Fact check
Test drive environment
OS | Windows 10 Home 21H1 19043.1081 |
---|
python | 3.9.6; MSC v.1929 64 bit (AMD64) | pip | 21.1.3 |
Package dependencies (after pip install)
python -m pip install locust==1.6.0
python -m pip list
gives:
Package Version
------------- ---------
certifi 2021.5.30
cffi 1.14.6
chardet 4.0.0
click 8.0.1
colorama 0.4.4
ConfigArgParse 1.5.1
Flask 1.1.2
Flask-BasicAuth 0.2.0
Flask-Cors 3.0.10
gevent 21.1.2
geventhttpclient 1.4.4
greenlet 1.1.0
idna 2.10
itsdangerous 2.0.1
Jinja2 3.0.1
locust 1.6.0
MarkupSafe 2.0.1
msgpack 1.0.2
pip 21.1.3
psutil 5.8.0
pycparser 2.20
pywin32 301
pyzmq 22.1.0
requests 2.25.1
setuptools 57.1.0
six 1.16.0
urllib3 1.26.6
Werkzeug 2.0.1
wheel 0.36.2
zope.event 4.5.0
zope.interface 5.4.0
Test drive
Setup target web application (flask):
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home() -> str:
return "<p>Hellow world!</p>"
@app.route("/<int:number>")
def lucky_number(number: int) -> str:
return f"<p>Your lucky number is {number}!</p>"
and:
python -m flask run
Then the terminal shows:
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Setup test runner:
import random
from typing import Callable
from locust import HttpUser, between, task
class FlaskAppUser(HttpUser):
wait_time: Callable = between(min_wait=1, max_wait=3)
def on_start(self) -> None:
return super().on_start()
@task(weight=3)
def go_home(self) -> None:
self.client.get("/")
@task(weight=1)
def go_lucky_number(self) -> None:
for _ in range(10):
self.client.get(f"/{random.randint(100, 999)}")
and:
python -m locust -f runner.py
Then the terminal shows:
[2021-07-12 ******] DESKTOP-******/INFO/locust.main: Starting web interface at http://0.0.0.0:8089 (accepting connections from all network interfaces)
[2021-07-12 ******] DESKTOP-******/INFO/locust.main: Starting Locust 1.6.0
Run the test:
Go to http://localhost:8089/ in the browser and the locust page is shown, fill in the desired parameter as well as the host of the target flask app: Click Start swarming button in the page and the test starts to run, and the statistics are populated in real time: The Charts tab shows graphs:
At any time, click the STOP botton on top-right corner to stop the current run. The terminal in which the runner runs shows like:
[2021-07-12 ******] DESKTOP-******/INFO/locust.runners: Spawning 10 users at the rate 10 users/s (0 users already running)...
[2021-07-12 ******] DESKTOP-******/INFO/locust.runners: All users spawned: FlaskAppUser: 10 (10 total running)
[2021-07-12 ******] DESKTOP-******/INFO/locust.runners: Stopping 10 users
[2021-07-12 ******] DESKTOP-******/INFO/locust.runners: 10 Users have been stopped, 0 still running
|