How to Load Test a Website with Authentication
Correctly load testing a website with authentication takes more thought than testing a simple static website, or even an API. When a login is triggered in a web application, more happens behind the scenes than during simpler requests. To load test properly, we need to make sure our test is realistic, and correctly stresses the infrastructure that supports the login process. Let’s review the key concerns when scripting and testing a site with authentication.
Proportional User Load
How many users should the performance of an authentication script support if exercised in isolation?
Generally, since authentication provides a ceiling for your web application’s scalability, it should support as many or more users as you proportionally expect in a real-world scenario to be authenticating. For example, if 5 percent of user-actions are login or logout on your site and you are targeting 1000 users, you should have 50 users simulating login/logout at the same pacing as your other scripts.
Fully Populate Your Database
All queries are fast when the database is empty.
Think of a database like a phone book. Finding a name is easy and fast if there is only one name in the book. If the database backing the web application is fully populated, you’ll get realistic results. If not, you could get a false-positive and your performance test might pass your SLA when it shouldn’t have!
Most load testing tools utilize a databank of some sort to get real working user credentials for the website. These stored credentials need to be vetted, and up to date. For example, if there is a password rotation policy, all users should have recently updated passwords. An application that interrupts the users page-flow for password updates will make working load test scripts fail if users are not able to navigate a webpage.
A Login per User
Utilizing multiple logins is important, but the logins also need to line up with the number of authenticated users your site is expecting. This is important because your logged-in user may use up a certain amount of server-side resources. Perhaps each user session actually holds websocket connection open on the server or some in-memory data when it is in-use. If you use only a few user logins, you won’t be testing if your system can fully handle the resource needs when many users login with different credentials.
If you re-use login credentials, your application will pull from the cache, rather than hit the database. Using a databank provides a way to make sure the application is logging in users the same way it would under real world conditions. If, for example, the database queries are a bottleneck, this ensures you’ll discover that bottleneck. It also ensures the performance measurements are accurate.
There are several reasons to source your login info in a databank. One reason is that the credentials may differ from environment to environment. Is the production and test password and username the same? Hopefully it isn’t! Make sure to consider that your databank needs to be environment-aware.
Concurrency – Everything Everywhere, All at Once
As a thought-experiment, imagine a web application that could *only* authenticate one login at a time because of a poorly implemented lock. It might be able to handle, one at a time, 1000 requests in a minute. If you test without concurrency with a single user-thread, you’ll probably feel pretty good about the performance numbers you see. However, in the real world, when 10 request hit concurrently, the performance will bottleneck. This is bad because you *want* to know this in advance. The way to ensure you find out ahead of time is to make sure you test with the correct number of simultaneous (concurrent) users.
How to Script the Website’s Login?
The most straightforward way to script the website’s authentication is to start your script with a login step and end it with a logout step. By “cleaning up after itself” the script gives a nice, repeatable test.
If your scripting is going to try and only login once, but reuse the session, it may also be helpful to attempt a logout on error, and then re-login in order to prevent the virtual user from getting in a “stuck state.” This really varies by type of tool, though, and whether the script is going to attempt to reuse the session.
There is a caveat to the scripting approach of logging in and out with every run. It can also be a useful test to exercise your login script without logging out–after all, many users won’t. If there’s something in the user session on the server that isn’t being cleaned up, this can be a useful test. That said, this really applies to testing a login component in isolation, and for the moment, we’re mostly considering testing the application as a whole. For more on testing for your website’s login directly, check out our article How to Create a Login Script for Load Testing
Once a user is logged in, it is important to verify response. Some applications have a quirk where they answer with a valid response (200) but the user is not truly logged in. In order to make sure something like this doesn’t happen, when you test, it is important that the response is checked, and that the specific user’s data is verified in the response. By checking the returned data, we can ensure our test isn’t broken, but giving us a false-positive result.