Load testing provides the application development team assurance that an application will perform as expected — at least up to a designated load value. Too many organizations don’t properly emphasize load testing.
Developers might run spot checks or adopt high-performance coding practices, but when unexpected customer load locks up a server, the business — and its customers — tend to be caught off guard. It is embarrassing when too much load causes an application to fail.
So, let’s discuss where Python fits in load testing best practices and how you can better prepare your applications for real-world conditions.
Why load testing matters
A type of performance testing, load testing stresses an application to determine at what level loads harm that app’s performance or functionality.
Let’s say a software development business is ready to launch a new website that enables users to sign up to have their prescriptions and medications tracked daily. The application sends out daily messages for patients to take their medication at specified times and relays information back to the patient’s medical record and provider.
With a load test, a tester loads the server to simulate 1,000 to 1 million users concurrently signing up, logging in and entering medical data. When the application has around 1% of users consuming server resources, it should work as expected and perform well. The tester then adds more users, who now consume 50% or more of the server resources, and continues until the server fails or the application locks up. As a tester tests the load, they also measure and track load times and data-retrieval speeds. In other words, the application and server performance are documented at various user load levels.
Effective load testing helps to identify problems with systems, including the following:
- Performance bottlenecks.
- Scalability.
- Application stability.
- Maximum user load capacity.
- Failover points.
- Problems with data retrieval rates.
Understanding how an application performs at capacity is an essential way to create a useful application that delivers a positive customer experience. Load testing provides a way to test and improve system capacity and performance. It also establishes at what point the capacity must be load-balanced onto another server so the application does not crash or fail.
With Python, you have built-in features for load testing; plus, it is the coding language behind one of the most popular and effective load testing tools.
Tools for load testing using Python
Load testing tools enable development teams to measure and analyze various loads against a system and application.
Tools provide the ability to measure and analyze key items, such as throughput rates for supporting peak loads; system resource utilization levels; hardware performance; load-balancer function and performance; concurrency performance; application defects visible under load levels; and application design flaws.
Effective load testing identifies system lags, inefficient page loads and crashes with more precision than when defects are reported from other manual or automated testing.
Use load testing to determine a failover point where either a load balancer kicks in or the extra user load is offloaded to another server rather than crashing or failing.
Writing load tests with Locust
Locust and JMeter are the most popular load testing tools, but there are many options.
Locust enables load testers and developers to simulate user load on an application. It uses Python code to test and then presents the load testing results in a dashboard.
The benefits of using Locust as a load testing tool include the following:
- Test-as-code functionality.
- User-friendly, web-based UI.
- Result analysis through dashboards, visual charts and testing reports.
- Ongoing performance tracking.
- Support for repeatable testing using multiple test script executions.
- Open source accessibility.
- Ease of use for Python developers.
- System and platform agnosticism.
Let’s see a simple example of how to write a Locust load test:
- Import HttpUser, task, time and classes.
- Create class = AuthenticateUser that takes an argument of the HttpUser class.
- Create a variable called timer that adds 10 seconds between every executed task.
- Define the function = authenticate_task that encapsulates the registration and login process.
- Implement a method = on_start that executes at the start of the test file.
import time
from locust import HttpUser, task, between
class AuthenticateUser(HttpUser):
timer = between(1, 10)
@task
def authenticate_task(self):
self.client.get("/login")
self.client.get("/register")
def on_start(self):
self.client.post("/register",json={"username":"testuser",
"email":[email protected]",
"password":"password"})
The popular Apache JMeter tool was designed specifically for load testing, but it is based on Java rather than Python. Its open source desktop application is fully customizable using Java and tests various load types. JMeter supports application performance testing and web services, Lightweight Directory Access Protocol, database and shell scripts. It has record-and-playback functions for easy, quick test script creation, and it enjoys strong developer community support.
Best practices for Python load testing
Load testing is complicated, at least at the start. To be done effectively, load testing requires you to follow some best practices. This ensures the quality and maintainability of tests and the accuracy of results. Load testing follows a set of best practices to help ensure high-quality testing and accurate results.
Load testing best practices include the following:
- Create an isolated test environment specifically for load testing.
- Don’t risk testing on production; mimic production on a separate server.
- Use scrubbed test data that simulates production data.
- Ensure the infrastructure of the load test system mimics production.
- Identify scenarios for testing based on priority and risk.
- Include testing all relevant endpoints.
- Include database retrieval times.
- Include key application functionality.
- Develop test scripts.
- Design tests that break the application rather than simply proving the application works as designed.
- Look for opportunities to make even small performance gains.
- Execute test scripts.
- Track test results for historical reference.
- Keep test suites updated along with the application code.
- Analyze test reports and results.
- Look for areas that can be improved, not only defects or failures.
- Document failover and load-balancer capacity points.
- Know and understand the application’s limits, and take steps to prevent failures.
- Optimize application performance with defect correction if necessary.
- Fix design flaws or system issues as effectively as possible.
- Measure performance metrics that matter:
- Response time.
- Wait time.
- Error rates.
- Requests per second.
- Passed transactions.
- Failed transactions.
- CPU utilization.
- Concurrent user performance.
Whether it is done with Python or by some other method, load testing improves application responsiveness and creates a plan for failover or load balancing. Python is a powerful language that’s useful for load testing directly or within a tool.
An application’s success and ability to generate positive customer experiences may well depend on how well it can handle load.
Amy Reichert is a 20-plus-year professional QA tester and a QA lead, specializing in test development, execution and management techniques. Her experience comes from a variety of sources, including ERP systems, architectural design, e-commerce and healthcare software.