In my current role as application performance specialist I see a lot of different frameworks that are used to develop applications faster, to make a more reactive frontend application or just a framework that is the latest and greatest from a development point of view.
One of these frameworks is Google Web Toolkit. Frameworks like this are a good thing for development… but for performance testing they might be a problem.
For performance testing the best practice is to use a proxy server recording all traffic between a browser and the application. In most cases this is just plain http with html or xml as a protocol. So it is easy to replay the recorded test and parameterize it with different values.
In most cases I use JMeter with a few good plugins like the plugins on Google code.
First you set your browser to a proxy which you define in JMeter. JMeter will record the requests you do.
After that you can fire the recorded requests to the application. Of course you first have to add proper test data so each session has different data.
While recording my first GWT applications I found out that GWT uses its own proprietary protocol wrapped in a sort of JSON. This gives at least 3 challenges if you use JMeter for record and playback.
In the following 4 paragraphs I will give an overview of GWT and tell you three of the tricks I used to be able to record and playback scripts for GWT applications. In my next blog I will also explain an alternative approach to test frameworks like GWT.
GWT overview
GWT is a framework in which you can code an application that will be precompiled to javascript and a services part (java). The javascript part will be used for a single page view in a browser.
This way you have a high responsive application because you don’t have to reload pages over and over again. GWT also has a lot of controls you can use without taking care about the communication between your control an your service. All the javascript and communication code will be generated by the precompile step.
3 Tricks to use JMeter for load testing GWT
GWT session context
GWT uses a session for each unique user.
Here you see a sample request coming from the GWT generated javascript frontend:
7|0|4|https://myserver:9080/myurl/|ABE2C0B156012B8657E5E26645105F43| org.class.MyClass|FieldName|1|2|3|4|0| |
One of the first things you might see is the sort of hash code (ABE2C0B156012B8657E5E26645105F43) this code can be found in one of the first html pages with the .nocache file extension which is fetched before. This is a sort of session context. You need it for each unique session.
Object id obfuscation/ compression
If you are requesting an object by id via GWT in the frontend, GWT will obfuscate/ compress it. To be able to get predefined records you have to deobfuscate/ decompress it. In the sample below I am requesting a record with id 318 (E$). What you see in the communication is E$.
//OK[7,1,[“java.lang.Integer/3438268394”],0,7,E$] |
It took me quite some time to find out how to map the GWT obfuscated/ compressed id’s to the id’s which where used in the application.
Finally I was able to created a function to compress/ encrypt an id like GWT does it.
String chars = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_”; long id = 318; String out = “”; while(id > 0){ long charpos = id % 64; id /= 64; out = chars.charAt((int)charpos) + out; } System.out.println(“GWT id: ” + out); |
GWT specific JSON
The next problem I found was that if you have a list of objects the field length is not equal for all objects in the list. In the later part of a request you see some id’s. In this list the field length for each object is also set together with a reference of the value used in some of the other records that came before.
Here you see an example JSON response from GWT.
//OK[35,8,34,27,5,’CvA’, 4,26,3,8,33,27,5,’CvB’, 4,0,3,8,7,6,5,’Cvh’, 4,0,3,30,2,2559,1,[“com.search.searchResult/3409195600″,”java.util.ArrayList/4159755760”, “com.data.client.message.MyMessageSummary/3311733355″,”java.lang.Long/4227064769”, “type.type1“,”My Object type 1.”,”08-10-2012 10:06″,”55863485″, “04-10-2012 11:27″, ” type.type2“,”My Object type 54″,”04-10-2012 11:28″, “05-10-2012 11:27”, |
This response represents a list of 4 records. The first 4 lines give some information about the object id and the amount of data for that record which will differ from the records before.
Record | Date | Type |
345 | 08-10-2012 10:06 | type.type1 |
346 | 04-10-2012 11:27 | type.type2 |
347 | 04-10-2012 11:28 | type.type1 |
348 | 05-10-2012 11:27 | type.type2 |
As you can see the type.type1 and type.type2 data will only be seen two times in the JSON data.
This while it is used 4 times. GWT uses some type of pointers between the records to point to data which is used before.
Different way of testing
This was the point I decided we needed a different way to test GWT applications.
In the GWT manuals there is a description to create special hooks in the backend code to test the individual backend services individual. This is something I can not use, different teams make the applications and making extra hooks will mean an application change and different code for production and testing. This is not the best way to test for scalability and performance in my opinion.
Function testers use Selenium a lot for functional testing. After a while I found a method to use Selenium in combination with JMeter to do performance testing. I will write a blog to describe this method later.