I recently had to load test web services for the smart client application we have developed. I wanted to be able to go through quick cycles (test, evaluate, adjust) without having to wait for a few days for a load test slot in our LoadRunner lab, so I offered to use Visual Studio team system to perform the tests. I already had experience with Microsoft’s previous load test tool – Application Center Test. I was pleased with VSTS’ version of a load test tool. Not quite as powerful as LoadRunner, but much more accessible in ease of use.
Anyway, I used VSTS successfully to load test web services and satisfy the following requirements:
- Randomly pick data from a set for a given test.
- Invoke the web services using HTTP POSTs (i.e. without having to create a client)
- Use a configuration file to store the SOAP envelopes needed to make the web service calls.
Picking data randomly
When using VSTS tests, the test methods are decorated with the [TestMethod] attribute. The [DataSource] attribute can also be used on the test method to indicate that the test is data-driven. Caution: the test is executed as many times as there are rows in the data source. That may be OK when performing unit tests, but it is not OK for a load test. So how do you get around this? Well, I got my data source to return only one row picked randomly. Using SQL Server 2005 Express, I defined views that would select one row of data using the following construct: “SELECT TOP(1) columnName1 AS alias1, columnName2 AS alias2, …. , columnNameN as aliasN FROM tableName ORDER BY NEWID();”
You might wonder why I am using an aliases on the column names. The reason why I did this was to decouple the column names in the tables from the element names in the SOAP envelopes. When the data source provides the row of data, I have a utility running through the column names of the DataRow object and substituting the data in the SOAP envelope based on the name of the columns found in the DataRow provided through the [DataSource] attribute. This simple convention makes it very easy to parameterize the SOAP sent to the service. Because the load test client should be as efficient as possible, I use a simple string parsing algorithm to perform the substitutions.
Invoke the web services using HTTP POSTs
I created a static class that uses an HttpWebRequest object to create the POST. The result is returned into an HttpWebResponse object by simply doing this:
using ( HttpWebResponse response = (HttpWebResponse)request.GetResponse())
If the web server responds with error response codes (e.g. HTTP 401, HTTP 500), VSTS detects that and reports on the errors. This is much better than Application Center Test where I was left to parse through the responses to make sure I did not get an error back.
Use a configuration file to store the SOAP envelopes needed to make the web service calls.
For this, my team member created an XML file that is loaded into an XmlDocument from which XmlNodes are selected and stored into an object that holds the SOAPAction to perform, the SOAP envelope to send the service, and the Url to use. Yes, I know, this is very ASMX-centric, and will likely need to change with WCF, but we were not developing a framework either. We needed a point solution to get going quickly.
Leave a comment if you have any questions or comments.