Load Testing with Locust: Everything You Need to Know
Test. Test. 1.2. 1.2
Nope! We are not talking about mic testing but essentially the mantra that every QA engineer and developer follows.
In the world of development and building solutions from scratch, you know you need to conduct different performance testing types to ensure each code change or feature addition. This is to ensure that:
It doesn’t break your system
Actually works
Types of Testing
But which performance testing types should you conduct to suit the dynamic nature of feature releases that a young startup generally operates on?
Let’s start with the basics.
What is Load Testing?
When you work in a startup like Decentro, the project completion rate is uninterrupted over a short period. In such scenarios, running load testing is imperative to check the readiness of these multiple releases. This type of performance testing allows you to determine how your system dealing with sensitive information [especially with the banking and payments domain] will behave during normal and peak load conditions and its breaking point (should it occur below the peak load condition).
Load testing confirms that your system meets your intended performance goals or objectives, frequently identified in a service level agreement (SLA).
Why is Load Testing Important for a player like Decentro?
According to Gartner, the average cost of network downtime for businesses is $5,600 per minute, well over $300,000 per hour. Imagine operating in a domain as sensitive as banking; what would a downtime impact look like for a player like you?
Hence, first, let’s look at the significance of load testing, particularly in the Fintech sector:
Significance of Load Testing
Ensuring system reliability and uptime: Financial systems must be available and responsive at all times to avoid costly downtime or financial losses.
Ensuring transaction processing speed: In fintech, speed is key. Users expect transactions to be processed quickly and accurately.
Detecting and preventing fraud: Load testing can help simulate real-world scenarios that fraudulent actors may use to abuse the system. Load testing can help identify and prevent fraud by simulating large requests.
Ensuring compliance with regulations: Fintech companies must comply with various regulations that mandate security, data privacy, and other requirements. Load testing helps identify vulnerabilities and ensure the system is secure and compliant.
Improving customer experience: Load testing can help identify issues that may affect the customer experience, such as slow page load times, unresponsive pages, or error messages. Load testing can improve customer experience and satisfaction by identifying and resolving these issues.
Now that the relevance and the need for load testing have been established let’s look at the application that can essentially assist developers in their day-to-day testing activities.
Presenting LOCUST.
What is Locust, and why does it being “Pythonic” matter?
When you google “Locust,” you might see two things in the results; one is a bug (grasshoppers). The other is a tool – “The name might resemble a bug, but I don’t allow bugs in your code – Locust.”
Locust is a Python-based load-testing framework that allows you to define user behavior using code and simulate thousands of users performing defined behavior concurrently.
It is “Pythonic” in nature, meaning it follows the Python language’s core principles. One of these principles is “If the implementation is easy to explain, it may be a good idea.” This means that the code should be easy to read, understand, and explain to others.
Let’s look at quick examples:
One of the most common features in web applications today is the Login and logout feature, how the user navigates within the website and what pages he/she is visiting. Now the question arises when the traffic to these pages, let’s say, crosses 300 users in a given time most technologies today can handle this load, but what if we’re to be more than 5000 users at a given time?
Will the website handle the load?
How well will the pages respond to said load now?
These scenarios can be easily tested in locust using the below python script. You can simulate different user activity levels by specifying weights for each task.
from locust import HttpUser, task, constant_pacing | |
from selenium import webdriver | |
from selenium.webdriver.chrome.options import Options | |
from selenium.webdriver.common.by import By | |
from selenium.webdriver.support.ui import WebDriverWait | |
from selenium.webdriver.support import expected_conditions as EC | |
import time | |
class MyUser(HttpUser): | |
#all user will re-initiate operations after 60 sec | |
wait_time = constant_pacing(60) | |
@task | |
def login(self): | |
chrome_options = Options() | |
chrome_options.add_argument("--headless") | |
driver = webdriver.Chrome(options=chrome_options) | |
driver.maximize_window() | |
#add wait time of 10 secs | |
wait = WebDriverWait(driver, 10) | |
# Load the login page | |
start_time = time.time() | |
try: | |
driver.get("https://example.com/login") | |
wait.until(EC.presence_of_element_located((By.XPATH, '//[@id="head"]'))) | |
username = wait.until(EC.presence_of_element_located((By.NAME, "user_id"))) | |
password = wait.until(EC.presence_of_element_located((By.NAME, "password"))) | |
username.send_keys("myuser") | |
password.send_keys("mypassword") | |
driver.find_element(By.XPATH,"//button[contains(text(),'Login')]").click() | |
wait.until(EC.presence_of_element_located((By.XPATH, '//[@id="Home"]'))) | |
self.environment.events.request_success.fire( | |
request_type="login", | |
name="login", | |
response_time=(time.time() - start_time) 1000, | |
response_length=driver.execute_script("return document.body.scrollHeight;"), | |
) | |
except Exception as e: | |
driver.quit() | |
self.environment.events.request_failure.fire( | |
request_type="login", | |
name="login", | |
response_time=(time.time() - start_time) 1000, | |
response_length = 0, | |
exception= str(e) | |
) | |
return | |
# Quit the driver | |
driver.quit() |
view rawlocust-test.py hosted with ❤ by GitHub
Locust uses Python code to define load-testing scenarios; below is code to test database server performance:
import psycopg2 | |
from locust import User, between, task, wait_time | |
class MyUser(User): | |
wait_time = between(5, 15) | |
def init(self, args, kwargs): | |
super().init(args, *kwargs) | |
self.conn = psycopg2.connect( | |
host="localhost", | |
database="mydatabase", | |
user="myuser", | |
password="mypassword" | |
) | |
def on_stop(self): | |
self.conn.close() | |
@task | |
def select_query(self): | |
with self.conn.cursor() as cur: | |
cur.execute("SELECT FROM mytable") | |
rows = cur.fetchall() | |
assert len(rows) > 0 | |
@task | |
def insert_query(self): | |
with self.conn.cursor() as cur: | |
cur.execute("INSERT INTO mytable (col1, col2, col3) VALUES ('value1', 'value2', 'value3')") | |
self.conn.commit() |
view rawlocust-test.py hosted with ❤ by GitHub
Locust Application for the Decentro
We practice what we preach.
We will now delve into our reasons for selecting Locust as our load test tool.
Our personal business use case:
Imagine a financial technology platform that processes transactions for lakhs of people daily, with thousands of transactions happening per second for different transaction types, such as IMPS, NEFT, RTGS, UPI, and card payments. Let’s look at our possible stress points:
Stress Pitstop 1: When a user initiates a payment, the platform performs various security checks, such as verifying the user’s identity and the payment source. Once the security checks are complete, the platform requests the user’s bank to transfer funds from their account to the recipient’s account.
Stress Pitstop 2: The bank then checks whether the payment is authorized and if the user has sufficient funds in their account. If everything is in order, the bank responds to the platform with confirmation that the payment was successful. After receiving confirmation from the bank, the platform updates its database to reflect the completed transaction. It sends a notification to the user within a couple of seconds.
Stress Pitstop 3: At the same time, the platform also receives incoming payments from external users. When an external user makes a payment to someone on the platform, the platform performs a series of security checks to ensure the payment is legitimate and goes to the intended recipient. If everything checks out, the platform updates its database and sends a notification to the payment recipient.
Stress Pitstop 4: In addition to payments, thousands of other users on the platform may also perform actions such as signup, creating accounts, updating beneficiary information, and completing the KYC process. Each action requires strict security checks, external calls, and updates to the platform’s database.
To ensure the system can handle such a high volume of transactions, a load test should be conducted to simulate the load and stress test the system’s performance under extreme conditions.
Conducting a load test can identify and address any performance issues or bottlenecks before the system goes live, ensuring a seamless payment experience for consumers.
What makes Locust a desirable option for your Load Testing?
Benefits of using Locust
Open-source and Python-based: Being open-source and developed in Python, Locust is easy to set up, use, and extend.
Scalable and Distributed: With Locust, you can simulate thousands of concurrent users by distributing the load across multiple worker nodes, making it easy to test your web application’s performance under realistic user activity levels.
Real-time Monitoring and Reporting: Locust’s web interface provides real-time monitoring and reporting.
Supports Multiple Protocols: Apart from HTTP, Locust supports testing protocols like WebSockets and TCP, making it a versatile tool for load testing a wide range of web applications.
Actively Maintained and Supported: With an active community of developers, Locust is well-maintained and supported, with a wealth of online documentation and support available for users.
Other Applications of Locust
Other applications of Locust
Load Testing E-commerce Websites: E-commerce websites need to handle many concurrent users, especially during peak periods like Black Friday or Cyber Monday. Using Locust, you can simulate thousands of virtual users to ensure that your website can handle the expected traffic and perform well under load.
Load Testing Database: Databases are a critical component of many web applications, and they need to be able to handle a large number of queries concurrently.
Load Testing API: APIs are the backbone of modern web applications, and they need to be able to handle a large number of requests concurrently. With Locust, you can simulate traffic from thousands of virtual users and measure your API’s response time and throughput.
Load Testing IoT Devices: The Internet of Things (IoT) is becoming increasingly popular, and IoT devices need to handle many requests from users and other devices. Using Locust, you can simulate traffic from thousands of virtual IoT devices to ensure your system can handle the expected load.
Performance Testing Cloud Services: Cloud services like Amazon Web Services (AWS) and Microsoft Azure provide scalable computing resources but need to handle the expected load. With Locust, you can simulate traffic from thousands of virtual users to test the performance of your cloud services.
In conclusion, Locust is a powerful and versatile tool for load testing that can help organizations ensure their systems’ reliability, performance, and scalability.
By simulating traffic from thousands of virtual users, developers can identify potential bottlenecks, optimize their plans, and provide a seamless user experience.
It’s like having visibility on a problem even before it has potentially affected your system.
UNAGI, in its true sense.
With that, we have come to the end of another immersive read. In our tryst to enable the developer community, we have published other articles, such as JsPDF, KONG, and more.
Feel free to indulge. Also, before we wrap up, leaving quick food for a QA’s inner thought,
Food for a QA’s inner thought
Zen of Python: In the face of ambiguity, refuse the temptation to guess.
This highlights the importance of precision and accuracy in load testing. Load testing can involve a lot of variables and ambiguity, but it’s crucial to resist the temptation to guess or make assumptions when designing and executing load tests. Instead, it’s important to take the time to research and understand the system being tested thoroughly and to design tests that are tailored to its specific requirements.
Please drop us a line on that reflective note if you wish to connect with us at hello@decentro.tech
Subscribe to my newsletter
Read articles from Decentro Tech directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by