Drupal 8 Load Testing with Locust
Load-testing is an essential best practice for Drupal 8 development. Quantifying how much traffic a site can sustain is critical information both during development and prior to launch.
The reasons for doing so are significant and wide-ranging:
- Determine hosting needs
- Identify under-performing code
- Test the efficiency of candidate contributed modules
- Quantify how performance is impacted as content grows
- Document pre-launch performance to facilitate future troubleshooting
Locust as a Load-testing Solution
Locust is a web-based, open-source tool. It was created to be easy-to-use via its user interface, while also being customizable via Python test scripts. For example, it allows for the ability to simulate multiple users concurrently submitting a Drupal webform multiple times. It can also run distributed tests with instances running on multiple machines.
Installing Locust
python3 -m pip install locustio
Install the "Beautiful Soup" python library to facilitate user login
python3 -m pip install bs4
Example Test Script
from locust import HttpLocust, TaskSet, between
from bs4 import BeautifulSoup
def index(self):
self.client.get("/")
def about(self):
self.client.get("/about")
def drupalLogin(self):
# Get form build ID to pass back to Drupal on login.
response = self.client.get("/user")
content = BeautifulSoup(response.content)
build_id = content.body.find('input', {'name': 'form_build_id'})['value']
self.client.post("/user/login", {
"name": "testusername",
"pass": "testpassword",
"form_id": "user_login_form",
"form_build_id": build_id,
"op": "Log in"
})
def drupalLogout(self):
self.client.get("/user/logout")
class UserBehavior(TaskSet):
tasks = {index: 1, about: 1}
def on_start(self):
drupalLogin(self);
def on_stop(self):
drupalLogout(self)
class WebsiteUser(HttpLocust):
task_set = UserBehavior
wait_time = between(5.0, 9.0)
In this example, 5 users log in to Drupal and then each user accesses either the front page or the / about page every 5-9 seconds. The "Hatch rate" of 1 adds an additional use each second until a total of 5 concurrent users are actively running the script. This helps to simulate a more natural increase in traffic. Finally, all users log out of Drupal when testing ends.
Running a Test
locust -f ./locust_test.py
Here is the UI form for initializing the test:
Here is a screenshot of the data table this test produced:
Here are PNG graph images generated by Locust during this test:
Tests can also be run without the UI. This is useful for automation or for running tests in a remote environment:
locust -f ./locust_test.py --no-web -c 5 -r 1 -H https://target.domain
This approach has successfully been tested in a CentOS 7 environment.
Load-Testing in the Development Cycle
Since tests are fairly straightforward to write and run, it is feasible to perform load-testing throughout the development process.
Early in the development phase, tests could be more simple and generic. For example, visiting the front page, logging in, and logging out. These initial tests could be site-agnostic for reuse across multiple projects. Then, more site-specific tests can be added as the project takes shape,.
An approach for this might include load-testing directions within pull requests or, potentially, automation could kick off tests following a PR merge so a snapshot of performance is captured with each code change.
Next Steps
Locust is a simple yet flexible open-source tool for quantifying performance throughout the development cycle. Interested in load-testing or test-driven development for your Drupal 8 site? Contact us today.
Resources
Other Insights & Resources you may like
Get our newsletter
Get weekly Drupal and AI technology advancement news, pro tips, ideas, insights, and more.