Tuesday, February 10, 2009

SoapUI - Property Expansion

While profiling one of my web services I was looking for an effective tool for load testing my web service. Initially thought of JMeter, but due to my happy experience with SoapUI in the past I decided to use SoapUI.

My request xml had multiple fields however couple of fields I had to send the same data. This wouldn't have been a problem during unit testing, but while load testing this service the value of these fields should be unique per test request. So my problem was say If I am sending 50 requests then in each request the value of these fields though common should be unique. Example request would be as below...
<soapenv:Envelope xmlns:soapenv = "http://schemas.xmlsoap.org/soap/envelope/" xmlns:web = "http://www.xyz.com/webservices/">
<soapenv:Header/>
<soapenv:Body>
<web:MigrateOrdersRequest>
<web:Header>...</web:Header>
<web:Credentials>...<web:Credentials>
<web:Order>
...
<web:OrderNumber>PO10001</web:OrderNumber>
...
<web:OrderLines>
<web:OrderLine>
...
<web:SerialNumber>PO10001</web:SerialNumber>
...
</web:orderLine>
<web:OrderLine>...</web:OrderLine>
</web:OrderLines>
</web:Order>
<web:MigrateOrdersRequest>
</soapenv:Body>
</soapenv:Envelope>

Here I have to pass both PO number and Serial Number unique and same. I initially looked for groovy script, but didn't work out for me. The other feature which really impressed me was Property Expansion which really did it. The property expansion will evaluate the property for you in the soap request may be it is from implicit objects, properties or any random math expression.

The solution initially looked tough was very very simple in the end. I just created a new TestCase in my soapUI testSuite with just one test step which was the soap request. And I created a load test step in the same test case (visibly load test will have only one test step). I used simple strategy with limit as 5 seconds and Test Delay of 5000 milliseconds and giving as many threads as required to mimic the scenario where 'n' (say 50) test requests hit the server. With other strategies where Test Delay was lesser than limit, the counter was not actually unique as the same thread after Test Delay was creating a new request. The modified request is as below.
<soapenv:Envelope xmlns:soapenv = "http://schemas.xmlsoap.org/soap/envelope/" xmlns:web = "http://www.xyz.com/webservices/">
<soapenv:Header/>
<soapenv:Body>
<web:MigrateOrdersRequest>
<web:Header>...</web:Header>
<web:Credentials>...<web:Credentials>
<web:Order>
...
<web:OrderNumber>PO1000${=context.getProperty("ThreadIndex")}${=context.getProperty("RunCount")}</web:OrderNumber>
...
<web:OrderLines>
<web:OrderLine>
...
<web:SerialNumber>PO1000${=context.getProperty("ThreadIndex")}${=context.getProperty("RunCount")}</web:SerialNumber>
...
</web:orderLine>
<web:OrderLine>...</web:OrderLine>
</web:OrderLines>
</web:Order>
<web:MigrateOrdersRequest>
</soapenv:Body>
</soapenv:Envelope>

Here after every load test the PO1000 needs to be modified to give next set of unique numbers. The catch here is that ${=<expression>}was actually evaluating to a value by soapUI at runtime. This expression can be any expression with the objects available in the context like properties, implicits etc.

2 comments:

Denys Nikolayenko said...

You saved my day! Thanks !

Anonymous said...

Hi,

Thanks for sharing the knowledge. I was struggling to assign a uniqueid to soap request and HTTP header. Your notes helped me to fix the issue. Thanks a lot. Keep doing good work.

Krishna

Learning programming

    Programming is an interesting world where you apply your skills to build a software program that comes into life when it is run on a com...