A very basic web service test tool

For those of us involved in testing web services and SOA-based applications, there are lots of different test tools on the market that can help speed up the testing and make them repeatable and easy to maintain. Some examples of these tools are SoapUI from SmartBear and SOAtest from Parasoft. SoapUI is available both as a freeware product and as an enterprise edition offering additional functionality. SOAtest is only available in a paid version.

One of the biggest downsides of the freeware version of SoapUI is the lack of data driven test support. This feature is only available in the paid version. In a previous post I introduced a simple way of implementing data driven testing in Selenium Webdriver tests, using Microsoft Excel sheets as the test data container format. As I am very regularly involved in web service testing myself, and often want to use data driven testing to create maintainable and flexible test suites, I thought it would be a good idea to see whether it’s possible to quickly create a very basic web service testing tool that supports data driven testing.

The test data source
As in the previous example, let’s create a test data source first. I chose to base the solution presented here on predefined XML request message files as this saves us the trouble of creating XML objects in our code. There are obvious downsides to this, of course, but for now we will focus on the ability to call a web service and subsequently capture and validate the result.

Our test data source looks like this:

webservice_test_data_source

It contains columns to identify the current test case, the path to the XML file containing the SOAP message to be sent and the endpoint to which the message should be sent. The last two columns contain the name of an element in the web service response we would like to validate and its expected value, respectively.

Reading our test data source
In our very basic web service test tool, we will process this Excel sheet just as we did in the Selenium example posted earlier. For every test data row, we will then execute the following steps:

  • Create a SOAP request from the XML file
  • Send the SOAP request to the right web service endpoint and capture the response
  • Extract the value from a response message element and compare it to the expected value

Create a SOAP request from the XML file
This is an easy step, as all we need to do is open the file, read all of its contents and transform it into a SOAP message object:

private static SOAPMessage createSOAPRequest(String strPath) throws Exception {
        
    // Create a SOAP message from the XML file located at the given path
    FileInputStream fis = new FileInputStream(new File(strPath));
    MessageFactory factory = MessageFactory.newInstance();
    SOAPMessage message = factory.createMessage(new MimeHeaders(), fis);
    return message;
}

Send the SOAP request to the right web service and capture the response
This is fairly straightforward as well and can be done using standard Java methods:

private static SOAPMessage getSOAPResponse(SOAPMessage soapRequest, String strEndpoint) throws Exception, SOAPException {
    	
    // Send the SOAP request to the given endpoint and return the corresponding response
    SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
    SOAPConnection soapConnection = soapConnectionFactory.createConnection();
    SOAPMessage soapResponse = soapConnection.call(soapRequest, strEndpoint);
    return soapResponse;	
}

Validating elements from the response message
Finally, we will parse the response message and validate the value of one of its elements. The validation result is sent to the stdout:

private static void validateValue(SOAPMessage soapMsg, String strEl, String strExpected) throws Exception {
    	
    // Get all elements with the requested element tag from the SOAP message
    SOAPBody soapBody = soapMsg.getSOAPBody();
    NodeList elements = soapBody.getElementsByTagName(strEl);
        
    // Check whether there is exactly one element with the given tag
    if (elements.getLength() != 1){
        System.out.println("Expected exactly one element " + strEl + "in message, but found " + Integer.toString(elements.getLength()));
    } else {
        // Validate the element value against the expected value
        String strActual = elements.item(0).getTextContent();
        if (strActual.equals(strExpected)) {
        	System.out.println("Actual value " + strActual + " for element " + strEl + " matches expected value");
        } else {
        	System.out.println("Expected value " + strExpected + " for element " + strEl + ", but found " + strActual + " instead");
        }
    }
}

Running the test
When we run the test, we see that the web service to be tested is called three times. Two tests succeed, the last test case fails (on purpose, to show that the validation is executed properly):

webservice_console_output

Extensions to our tool
As stated earlier in this post, there are a lot of improvements to be made to this very basic web service test tool. For instance, we could add:

  • Dynamic request message generation based on a template and data source values
  • XSD validation for the response messages
  • Support for non-SOAP-based (or plain XML) web services or even for transport protocols other than HTTP

Some of these improvements will probably be featured in later articles at ontestautomation.com. For questions or suggestions on topics to be covered on this blog, please do not hesitate to contact me at bas AT ontestautomation.com or leave a reply through the comment form below.

An example Eclipse project using the pattern described above can be downloaded here.

Data driven testing in Selenium Webdriver using Excel

Most commercial automated software tools on the market support some sort of data driven testing, which allows you to automatically run a test case multiple times with different input and validation values. As Selenium Webdriver is more an automated testing framework than a ready-to-use tool, you will have to put in some effort to support data driven testing in your automated tests. In this article, I will show you one way of implementing data driven testing in Selenium. There are lots of different approaches possible, and I am aware that the solution presented here can possible be enhanced further enhanced and extended as well, but it will set you off in the right direction when you want to implement data driven testing in your own tests.

The test data source
Before we dive into the implementation in Selenium, let’s first look at the test data source we are going to use to store our input and validation values. As it is widely used in the testing world for test script and test data administration, I usually prefer to use Microsoft Excel as the format for storing my parameters. An additional advantage of using Excel is that you can easily outsource the test data administration to someone other than yourself, someone who might have better knowledge of the test cases that need to be run and the parameters required to execute them.

In the example presented here, I have used a very simple Excel sheet containing a single input parameter (SearchString – a Google search string) and a single validation parameter (PageTitle – the page title displayed by the browser after the search has been executed). Yes, we are performing a pretty trivial test case, but it is sufficient to demonstrate the principle behind the solution presented here.

data_driven_test_data_source

Reading data from the test data source
Next, we need a way to open this Excel sheet and read data from it within our Selenium test script. For this purpose, I use the Apache POI library, which allows you to read, create and edit Microsoft Office-documents using Java. The library, as well as its JavaDoc, can be found at http://poi.apache.org. The classes and methods we are going to use to read data from our Excel sheet are located in the org.apache.poi.hssf.usermodel package.

A simple main method, where we loop through all rows in the Excel sheet containing test data and call the actual test method using the current test data, could look like this:

public static void main (String args[]) {

	try {
		// Open the Excel file
		FileInputStream fis = new FileInputStream("Z:\\Documents\\Bas\\blog\\datasources\\testdata.xls");
		// Access the required test data sheet
		HSSFWorkbook wb = new HSSFWorkbook(fis);
		HSSFSheet sheet = wb.getSheet("testdata");
		// Loop through all rows in the sheet
		// Start at row 1 as row 0 is our header row
		for(int count = 1;count<=sheet.getLastRowNum();count++){
			HSSFRow row = sheet.getRow(count);
			System.out.println("Running test case " + row.getCell(0).toString());
			// Run the test for the current test data row
			runTest(row.getCell(1).toString(),row.getCell(2).toString());
		}
		fis.close();
	} catch (IOException e) {
		System.out.println("Test data file not found");
	}	
}

Simple, yet effective. Of course, many enhancements or improvements can be made to this example, such as:

  • The path to the test data file can be passed as an argument to the main method, or the user can be allowed to select a test data sheet, for example using JFileChooser
  • The fact that the first row contains column headers can be made optional, for example by passing a Boolean argument to our method
  • Instead of using column indexes as we have done here (in the getCell method, we could use column headers and have our code determine the correct column index for a given column at runtime

Executing our sample test
The actual test we are going to execute is located in the runTest method, which is called from the main method for every test data row in our sheet. It starts a browser driver, in this case a HtmlUnitDriver, executes a Google query using the query from the Excel sheet and checks the page title to see whether it matches the expected value. The code is pretty straightforward:

public static void runTest(String strSearchString, String strPageTitle) {
		
		// Start a browser driver and navigate to Google
		WebDriver driver = new HtmlUnitDriver();
        driver.get("http://www.google.com");

        // Enter the search string and send it
        WebElement element = driver.findElement(By.name("q"));
        element.sendKeys(strSearchString);
        element.submit();
        
        // Check the title of the page
        if (driver.getTitle().equals(strPageTitle)) {
        	System.out.println("Page title is " + strPageTitle + ", as expected");
        } else {
        	System.out.println("Expected page title was " + strPageTitle + ", but was " + driver.getTitle() + " instead");
        }
        
        //Close the browser
        driver.quit();
}

When we run this test, we can see in our stdout that the test script is executed three times, once for each row in the test data sheet:
data_driven_console_outputAdding or changing test cases is now as easy as editing the Excel sheet associated with our test. As long as nothing is changed in the location or the order of the columns, no maintenance is required in our Selenium script.