XPath in soapUI Part 1: XPath Assertions and Namespaces

After a long hiatus for the American holidays, in response to numerous requests I'm going to look at using XPath in soapUI over the next two or three posts.  In this post we'll walk through creating a very basic XPath assertion and discuss namespaces, which almost always pop up but can be a bit tricky and not very intuitive if you're new to XPath.  For the sake of space and time, this may seem like a bit of a whirlwind introduction, but I'm hoping it will be more than enough to get you started.  For an in-depth look at XPath or to fill in the gaps, I recommend the tutorial at w3schools.com.

You can download a zipped sample project here with several request steps for which you can create and experiment with your own XPath assertions.  The service returns information about holidays in several countries; e.g., it returns a list of holidays in a given year, the date of a given holiday, etc.  Also, it doesn't use CDATA-- as I discussed in previous posts, services that make extensive use of CDATA require some extra scripting to get them to work with XPath.  Download the project, unzip it, and import it into your soapUI workspace (if you want to create your own project from scratch, the WSDL for this services is at http://www.holidaywebservice.com/Holidays/HolidayService.asmx?WSDL).

Let's walk through creating a simple XPath assertion.  Once you've imported the project and opened it in soapUI, run the GetHolidayDate test request in the GetHolidayDate test case; the response should look something like this:


GetHolidayDate Response XML

SoapUI's XPath assertions allow you to confirm that a specified value in your test request's response XML matches some expected value.  Let's create an assertion that verifies the request is returning the expected date-- in other words, that the value of the GetHolidayDateResult element is '2013-01-01T00:00:00'.  Open the test step editor and expand the Assertions panel, if necessary (click on the Assertions button at the bottom of the editor window).  Open the Add Assertion dialog; the XPath Match assertion is available in the Property Content group.


XPath Match in the Add Assertion dialog

After selecting the XPath Match assertion type, the XPath Match Configuration dialog is launched:


XPath Match Configuration dialog

Once in this dialog, click on the Declare button above the top panel-- soapUI scans the test response to try to identify any namespaces used and automatically creates corresponding declarations:


Namespace declarations automatically generated by soapUI

For those of you unfamiliar with namespaces (and those of you who are may want to skim the next few paragraphs), these provide a way to avoid naming conflicts in XML.  For example, you may have two web services that both return an element named "Addressee".  Associating each "Addressee" element with a different namespace ensures that each remains unique.  Namespaces are generally defined within XML tags using the following syntax:

xmlns[:prefix]="someNamespaceHere"

The colon and prefix are optional.  If the namespace is defined without specifying a prefix (e.g., xmlns = "http://www.someName.com"), it applies to the element for which it's defined and children of that element (assuming they don't have namespace prefixes or their own xmlns attribute defined in the same way).  If the namespace is defined with a prefix (e.g., xmlns:ns = "http://www.someOtherName.com"), XML nodes can be associated with that namespace by using its defined prefix and a colon (e.g., an element labelled ns:Element1 would be associated with the namespace "http://www.someOtherName.com").

Let's return to our example.  Look again at the GetHolidayDateResult element in the response above.  Its namespace ("http://www.27seconds.com/Holidays/") is specified as an attribute of its parent element, GetHolidayDateResponse.  Cross-checking this with the soapUI-generated declarations, we can see this namespace was declared for our XPath expression using the prefix "ns1".  We can now write our XPath expression using the correct namespace prefix.  Type the following in the XPath Match Configuration dialog below the namespace declarations:

//ns1:GetHolidayDateResult

The leading double-slashes signify that we want to find an instance of the GetHolidayDateResult element wherever it occurs in our XML tree.  Click on the "Select from current" button below the XPath Expression panel to evaluate the expression-- it should return the value "2013-01-01T00:00:00".  Save the assertion, giving it a meaningful name (so you know at a glance exactly what's passing or failing); in subsequent test runs, the assertion will be re-evaluated and passed or failed accordingly.

As I mentioned at the beginning of this post, namespaces can get a little tricky.  While soapUI will help you out by automatically generating namespace declarations, you're on your own when it comes to using those namespaces correctly in your XPath expression-- if you enter an incorrect namespace prefix (or forget to use one where one is needed), you'll simply get a message that a match can't be found.  In fact, if you see this behavior and you can't find any obvious errors (e.g., typos), a namespace prefix is frequently the culprit and might be the first thing you'll want to double-check.  Note also that soapUI's auto-declared prefix for a given namespace may not necessarily match the prefix defined in the response XML; in this case, you want to use soapUI's declared prefix.

Obviously, this is a very simple example; in the next post (which I promise won't be six weeks from now) we'll look at some more complex expressions.

Beginning soapUI Scripting: "Groovifying" Your Scripts

In this post I'm going to dive into some features specific to Groovy; mainly, alternative ways to work with properties and Groovy closures.  You're likely to come across these as you look at more scripting examples on the web, and although you don't have to use these concepts, once you feel comfortable with them you may choose to incorporate them into your own scripts to make them more compact and efficient.

Working with Properties with Groovy

Groovy provides a couple of alternative ways to work with properties.  Take the following code, for example, which illustrates three different ways to set and retrieve the value of a user-created property:

//Setting a user-defined property the "traditional" way:
context.setProperty("myVar1", "Value1")
//Setting a property using map syntax-- treating property names 

//and values as key-value pairs:
context["myVar2"] = "Value2"
//Setting a property using simple dot notation:
context.myVar3 = "Value3"

//Get the "traditional" way:
log.info("Value of myVar2 = " + context.getProperty("myVar2"))
//Get using map syntax:
log.info("Value of myVar3 = " + context["myVar3"])
//Get using simple dot notation:
log.info("Value of myVar1 = $context.myVar1")

This produces the following output:



You can see all three methods for setting and getting properties are functionally equivalent to each other.

These aren't restricted to user-defined properties; Groovy lets you use the same shortcuts to work with objects' intrinsic properties-- the properties that are class members, typically accessed via their own "getter" and "setter" (sometimes called accessor and mutator) methods.  For example, the WsdlTestCaseRunner class has a method called getResultCount(), which returns the number of step results returned in a test case run.  You can access the same data using simple dot notation and map syntax:

//"Traditional" method to access result count
log.info(testRunner.getResultCount())
//Alternative ways to get the result count
log.info(testRunner.resultCount)
log.info(testRunner["resultCount"])

Closures

You can implement your own lightweight user-defined functions via closures in Groovy.  Closures are defined much like typical variables, except you're assigning code instead of standard data.  The code being assigned to the closure is wrapped in braces:

def logTCProp = {log.info("$it = " + testCase[it])}

Here we're defining a closure called logTCProp; its purpose is to take a test case property name (a string) and write the name and its value to the script log (note this closure should be run in a test case setup or tear down script, where the testCase variable is available).  The keyword it serves as a placeholder for the argument passed in when the closure is called:

logTCProp('name')

This calls the logTCProp closure, passing in the string 'name' as its argument.  When the closure is evaluated, 'name' replaces the it keyword; effectively, it becomes equivalent to the following:

log.info("name = " + testCase['name'])

The resulting output (for a test case named "ClosureExamples"):



The real power of closures is in their ability to be passed as arguments to certain methods (typically related to collections of data-- lists, for example).  Here's an example using the each() method with a Groovy list of strings, using the logTCProp closure we defined previously as its argument:

def propList = ['name' , 'testSuite' , 'testStepCount']
propList.each(logTCProp)


First we define propList as a list of test case property names, then each() is called as a method of the list, with the closure passed in as its argument.  Basically, each() ends up functioning like a for loop: the specified closure (the argument) is executed using each member of the calling list in turn as its argument.  Compare it to:

for(prop in propList){
logTCProp(prop)
}


The resulting output (from the each() method and the for loop):



Another method that can take a closure as its argument is collect().  The collect() method can be used with closures that produce some output value-- as with each(), collect() executes a specified closure against each member of a list, but collect() puts the values output by the closure together into a new list.  Here's an example that gets a test case's step results and puts their statuses into a list:

def returnStatus = {it.status}
def resList = testRunner.results
def statusList = resList.collect(returnStatus)
log.info(statusList.toString())


Example output:



You can save yourself even more typing by taking advantage of anonymous closures-- there's no need to name and define the closure separately from the method calling the closure; instead you can simply place the closure's code (braces and all) after the name of the method with which you'd like to use it. Here's the example I just gave rewritten using an anonymous closure:

def resList = testRunner.results
def statusList = resList.collect{it.status}
log.info(statusList.toString())

Note that returnStatus is no longer defined anywhere-- instead, its bit of code ({it.status}) is placed it after the call to the collect() method.  Also note that there are no parentheses used with the method call (as we do when using a named closure)-- it's as if the braces around the code take their place.

For more on working with Groovy, check out its official site (I recommend the "Beginner's Tutorial" section of the Getting Started Guide as a starting point).

Quick Notes: Thanks and the def Keyword

With the Test Automation Noob blog rolling past 17000 page views, I wanted to thank everybody who has asked questions, taken a few moments to send some feedback regarding posts, or recommended the blog to others; hearing from readers has been very gratifying.  I also apologize for the sporadic frequency of postings:  between work, parenthood (is that redundant?), and other pursuits it's sometimes difficult to carve out time to write new posts on a consistent basis.

If you've looked beyond this blog for soapUI scripting samples, you may have noticed some differences between the scripts here and those posted elsewhere.  Some of these are due to differences between Groovy and Java-- frankly, my scripts tend to be "Java-centric" and don't take advantage of many of Groovy's shortcuts; I think some of the Groovy constructs are a little less intuitive and harder to grasp for somebody starting out in scripting, and I came to soapUI with experience in Java, so I never really dove into the nuts and bolts of Groovy.  I hope to write a post in the not-too-distant future to bridge some of those gaps and illustrate some of the different ways of doing things in Groovy that can help make your scripts more compact.  However, there is one Groovy keyword I haven't used thus far, but intend to use in the future: the def keyword, used when declaring a new variable in a script.  If you've already started implementing scripts without def, don't panic!  It's optional; the scripts I've written so far should be working fine without it, and omitting it saves a little bit of typing.  If you only intend to write simple scripts in soapUI for the odd situation where the standard interface isn't quite sufficient, you can probably get away with leaving out the def keyword.  However, moving forward I intend to use the keyword in scripts and you may see some of the past scripts and posts re-worked to include it (look for an update to the first scripting post on variables for more detail on using the def keyword).  I have two primary reasons for doing this: first, as I mentioned before, def is ubiquitous in scripting examples elsewhere, including soapUI's own site, so including it here provides some consistency.  Secondly, after reading over discussions on the topic and weighing different arguments, I think it's just better practice, particularly if you think you may end up working with Groovy outside of soapUI someday-- getting into the habit of using it now when it may not matter could help avoid headaches later on when it does.