Dieses Blog durchsuchen

Sonntag, 13. November 2022

Doing a JSF Login with the load testing tool Locust

Locust (locust.io) is an open source load testing tool which allows you to write load tests in Python. This is a nice approach because you can leverage the full possibilities of this nice programming language and are not restricted to complicated and overloaded UIs to configure your tests. (you probably have an idea about which tool I am referring to)

The starting point of each load test is a so called locust-file which contains the code that is executed in order to run the test. Locust can be used to test all kind of technology but is per default optimized for http-based systems like REST services or web-UIs.

Doing REST calls and simple GET-requests is easy and they are pretty much self-explanatory:

class WebTest(HttpUser):
    def index_page(self):
    def login_page(self):

In this example two simple get request is issued to the web sites "index.html" and "login.html". The task annotations define an action that a user is doing repeatedly.

When you have to support frameworks like JSF the challenges increase. For example when doing a JSF login with locust (python) you  have to keep two things in mind:

  1. JSF uses a JSESSIONID which is set to a cookie and identifies the session of a user on the server. Therefore the client needs to save the JSESSIONID after login in order to make sure the session is not lost between the requests.
  2. JSF uses a view state to keep track of the JSF component tree on the server side. The view state ID has to be sent to the server otherwise an exception is thrown.
Fortunately the first requirement is not a problem because locust's HttpUser keeps track of the session automatically by using cookies in the background. The View State ID on the other hand is something that needs to be sent to the server manually. In order to do so the first step is to call the pages that includes the login form with the view state is. 
The login procedure can be defined in the on_start method of the test class, which is executed only once before the tasks are performed:

  def on_start(self):
      response = client.get('/')
Afterwards the view state ID can be extracted from the response. Here is an example on how this is done with the "BeautifulSoup" library:

    bs = BeautifulSoup(response.content, features="html.parser")
    viewstate = bs.find("input", {"name": "javax.faces.ViewState"}).attrs['value']

Finally the login can be executed:

 data = {"loginForm": "loginForm",
     "user": "my_user",
     "password": "test123",
     "javax.faces.ViewState": viewstate,}
 response = client.post('/', data=data)

If you ask yourself which parameters you need to send in the post request for a successful login it can be helpful to take a look at the requests performed using the developer tools (i.e. from Chrome browser) to see the actual request done when using a web browser.