Performance Testing SOAP with LoadRunner – Basics

Posted on August 10th 2011 by Joel Deutscher

Simple Object Access Protocol (SOAP)Web services are more commonly becoming the targets of Performance tests. This post aims to provide an introduction to testing SOAP with LoadRunner without using the Web Services VUser type. Why not use the Web Services Vuser? Errors like this

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Xml.XmlException: 'xsi' is an undeclared namespace.

Using the custom web request (as suggested by Wilson Mar, Stuart Moncrieff and many others) bypasses the XML validation steps of LoadRunner, which is a good thing. This is possible because SOAP is just XML over HTTP, so lets take a look.

Understanding SOAP

A typical SOAP message is made up of header and body encapsulated in a SOAP envelope. The SOAP header contains application-specific information (like authentication, payment, etc) about the SOAP message. The header is optional, yet if present, must be the first child element of the Envelope. The SOAP body element contains the actual message.
SOAP EnvelopeAs SOAP uses HTTP as an application protocol, it utilises a request / response model. A SOAP request is sent to the endpoint via a HTTP POST and the returned SOAP message uses the same response codes for HTTP (200 OK, etc). This request is to get the stock price for the ticker symbol HWB (Headwired Bank), with the response returning a price of $460.75 as the last traded price.

SOAP Request

POST /StockQuote HTTP/1.1
Host: headwired.com
Content-Type: text/xml; charset="utf-8"
Content-Length: 1452


    
        
            HWB
        
    

SOAP Response

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: 1298


    
        
            460.75
        
    

SOAP as a Web Service

As a Web Service, the structure of all supported SOAP requests and responses are provided in a WSDL (Web Service Definitions Language). A WSDL provides the following information:

  • The interactions service provided
  • The arguments and results are involved in the interactions
  • The network addresses are used to locate the service
  • The communication protocol that should be used
  • The data formats that messages are represented in

In our example SOAP web have a structure for our request in the SOAP body. We have a GetLastTradePrice tag, with a child tickerSymbol . How can we determine that this is what we need to submit by looking at the WSDL? The following WSDL definition declares what elements should be in GetLastTradePrice input request.


  

This specifies that our input should contain the “ TradePriceRequest” element which is also defined in the WSDL. The definition is for one element “tickerSymbol” that must be a string value.


  
    
      
    
  

The WSDL will also specify the response that we should expect from this request.


  

This specifies that our input should contain the “TradePrice” element which is also defined in the WSDL. The definition is for one element “price” that will contain a float value.


  
    
      
    
  

The WSDL below is a rough example of the stock service that would be used by the example SOAP.


  
    
      
        
          
        
      
      
        
          
        
      
    
  
  
    
  
  
    
  
  
    
      
      
    
  
  
  
        
           
           
           
        
    
    
        My first service
        
           
        
    

SOAP With LoadRunner Custom Requests

SOAP in its most basic form is XML + HTTP. Therefore, we can use the LoadRunner web_custom_request function to manually specify our SOAP message. This method is more verbose than a web_service_call script, yet as it is a web request, there is no XML parsing performed by LoadRunner. This can be very useful if your web_service_call scripts are returning errors.

Scripting a web service is different a web page. Firstly, unless you have a client application, you will not be able to record and replay, instead you will have to recreate the web service calls based on logs, interface specification documents or a WSDL. It is also important to understand how the operations of the web service will be used in production.

Setup

This section discusses the steps to setup your LoadRunner script to commence scripting.

Script Type

A web_custom_request script for SOAP should be created as a “Web (HTTP/HTML)” script. This allows for Internet Protocol Run Time settings to be configured for handling authentication in a more effective way (read: web_set_sockets_option).

Web HTTP Script in LoadRunner

Authentication

The web service you are using may require HTTP level Authentication in order to access the web service operations. This can be performed using a simple web_set_user command in LoadRunner. To avoid a Authentication Error on your first request, the web_set_sockets_option can be configured along with the “Enable Integrated Authentication” run-time setting to avoid this issue.

// Requires "Enable Integrated Authentication" to be set to "yes"
web_set_sockets_option("INITIAL_BASIC_AUTH","1");
// Authenticate
web_set_user("USERNAME","PASSWORD","www.headwired.com:443");

To enable integrated authentication, open “Run-time Settings > Internet Protocol > Preferences > Set Advanced Options” and select yes for “Enable Integrated Authentication”. More information about authentication can be found here.

Enable Integrated Authentication in LoadRunner

There may also be the requirement to login using multiple authentication pairs throughout the test. This is possible through the use of the web_cleanup_cookies function. This function will remove all cookies related to the VUser, including NTLM authentication cookies.

// Clear previous logins
web_cleanup_cookies();

Scripting

Making the Request

In order to use the web_custom_request function for SOAP, we must specify that we will be submitting text/xml. The web_add_header function is used to specify this.

// Set Headers to plain text / xml
web_add_header("Content-Type", "text/xml; charset=utf8"); 

The web_custom_request is pretty straightforward. You specify your URL, Method and Body of the request. The SOAP message, including XML specification and Envelope is placed in the Body section of the request.

web_custom_request("Transaction_Name", 
	"URL=https://www.headwired.com/StockQuote", 
	"Method=POST", "TargetFrame=", "Resource=0", "Referer=", 
	"Body=" 
	
	"Snapshot=t1.inf",
	LAST); 

Verifying the Response

The simplest way to verify the response of a SOAP request is to use the web_reg_find function. This allows the specification of text that must be matched within the response text.

// Ensure the response contains correct text
web_reg_find("Text=GetLastTradePriceResponse",LAST);

To extract data from the response and save it as a parameter, you may also use the web_reg_save_param function. In the example below, the entire XML response, including HTTP headers is saved in the “response” variable.

// Save entire response as a string
web_reg_save_param("response","LB=","RB=",LAST);

Debugging Tips

Perhaps the easiest way to debug a web services script that utilises the web_custom_request function is to enable “Visual test results”. This feature can be enabled via the VuGen General Options, Replay Tab

Visual Test Results

The visual test results will display a report after replaying a script and provide you a script tree view, and allow you to view the XML response from the SOAP server.

Example Script

The following is a LoadRunner script that will send our sample SOAP request to the server. It will ensure that the response contains the term “GetLastTradePriceResponse”. As SOAP uses HTTP, any HTTP level errors (401, 500) will also automatically be failed by LoadRunner.

// Ensure the response contains correct text
web_reg_find("Text=GetLastTradePriceResponse",LAST);

// Set Headers to plain text / xml
web_add_header("Content-Type", "text/xml; charset=ISO-8859-1"); 

// Submit SOAP Request
lr_start_transaction("SOAP_GetLastTradePrice");
web_custom_request("SOAP_GetLastTradePrice", 
	"URL=http://www.headwired.com/stock", 
	"Method=POST", "TargetFrame=", "Resource=0", "Referer=", 
	"Body=" 
""
  ""
    ""
      "HWB"
    ""
  ""
""
	"Snapshot=t1.inf",
	LAST); 
lr_end_transaction("SOAP_GetLastTradePrice", LR_AUTO);

About the Author

Joel Deutscher is an experienced performance test consultant, passionate about continuous improvement. Joel works with Planit's Technical Testing Services as a Principal Consultant in Sydney, Australia. You can read more about Joel on LinkedIn.

Comments are closed.