REST Services and JSON in soapUI Test Suites

In the previous post I walked through adding a REST service to a project in soapUI; as a quick recap, here's a screenshot of where we left the project, with several REST requests:


As with SOAP services, once a REST service has been added to a project soapUI can automatically generate a test suite for the service.  Right-click on the service's node in the workspace tree and select "Generate TestSuite" from the context menu.  The Generate Test Suite dialog looks very similar to the corresponding dialog for SOAP services, allowing you to choose the resources for which you'd like to generate tests, whether you'd like all of the generated tests grouped into a single test case or assigned to their own test cases, etc.:


Let's leave the default options and click OK.  A test suite is generated with one test case for each of the REST service resources we defined previously.  By default, test requests use the parameter values that were set when the corresponding service request was added to the project.  However, these values can be changed in a test request's parameters table, and you can use them with property expansion.  Open the cardId test case and create a test case property called testCard and give it the value "chain-reaction".  Open the editor for its lone test request (Retrieve Individual Card Info) and use soapUI's property expansion syntax to specify the testCard property of the test case as the value of the test request's cardId parameter-- enter "${#TestCase#testCard}".  Click the Send button (the green arrow) for the test request.  Looking at the response, we can see that the data returned does indeed correspond to the card named Chain Reaction:


Remember that you can specify different parameter types in the parameter table, so you can use property expansion with any of them: URI parameters, resource path parameters, request body parameters, etc.

Let's move on to creating an assertion.  Up until now in my posts I've focused on web services that return response data as XML; this REST service gives us an opportunity to look at how soapUI handles JSON data.  SoapUI's solution for dealing with JSON data is really pretty straightforward-- it generates an XML representation of the same data set.  Consequently, all of the same XML-based content assertion types are available to use with JSON response data.  Note the tabs running along the left side of the panel showing the response data, and (if necessary) click on the one labelled "XML" to view the response in XML format.


Click on the Assertions button at the bottom of the Request Editor to open the Assertions panel, click the Add Assertion button, and add a new XQuery Match assertion.  The service returns data for multiple editions of the same card, so we'll use our assertion to confirm some expected values for the two editions of the Chain Reaction card.  Click the Declare button at the top of the assertion's configuration dialog to add a namespace declaration and add an XQuery expression to return data for the card's editions; the expression with its declaration should look something like this:


Click the "Select from current" button to capture the expected result of the expression, then save the assertion with the test request.  When dealing with XML-based assertions and JSON response data, note that even though the XML is auto-generated by soapUI, a namespace declaration and namespace prefixes are still needed.  Also be careful of extra tags in the XML (such as the "e" tags around each set of edition data) that do not exist in the original JSON but are inserted by soapUI to delineate some JSON data structures in the conversion.

Adding REST Services in soapUI

In this post I'll take a long overdue look at REST (REpresentational State Transfer) services in soapUI.  For anybody new to REST, I recommend this article covering the basics.  REST is not a web service protocol in and of itself; it's a web service architecture that can be implemented with any protocol, although it's frequently implemented with HTTP.  Occasionally, there's some confusion that arises from this relationship-- something to remember when thinking about your approach to testing a service.  For example, you may encounter a simple HTTP service labelled as a REST service that doesn't really take advantage of REST's architectural principles.  In these cases, it may be easier or more straightforward to implement test requests as basic HTTP requests in soapUI.

The last few releases of soapUI have also been very REST-centric, focusing on improved support and ease-of-use when dealing with REST services.  Going back just a few releases, creating REST services in a soapUI project was much more involved and complicated.  Consequently, if you intend to work with REST services I recommend updating to the most recent version if you haven't done so already.  This post reflects the workflow in soapUI 5.0.

For these examples, I'll be using the REST service at api.deckbrew.com.  The service provides information about cards from a popular collectible card game (Magic: The Gathering).  I apologize-- for most of you this subject matter will probably seem very dry, but it was surprisingly difficult finding a freely accessible web service that provided resources that could be used to create some meaningful examples.  This service is also limited in that it only leverages the HTTP GET method; an ideal REST service example would also utilize other HTTP methods (corresponding to different actions that could be taken on the service's resources).

When adding a SOAP service to a project, soapUI uses its WSDL document to determine the service's operations, their parameters, etc.  REST services have WADL (Web Application Description Language), which is roughly equivalent to SOAP's WSDL, but frequently a WADL document is not provided for a REST service (as is the case with our example service).  In these cases, soapUI allows you to enter service requests and parses the requests to identify the service's components.

From the soapUI File menu, select the option to create a new REST project.  You'll be prompted to enter a URI for the service:


To generate a request for a filtered card search, enter the following for the URI (as one continuous line):

https://api.deckbrew.com/mtg/cards?page=1&type=&subtype=&supertype=&name=&oracle=&set=&rarity=rare&color=red&multicolor=false&multiverseid=&format=&status=legal

In the workspace tree, soapUI generates a new project containing a node for the service's Cards resource, along with method and request child nodes corresponding to the URI we entered.  Click on the request to see the generated GET request:


All of the parameters entered as part of the request URI (including those for which no value was provided) are listed in the Request Editor.  You can add extra information about the parameters via the panel below the table; designating whether or not a parameter is required, for example.

The Level column determines the parameter's "scope" within the service-- a parameter can be associated with the RESOURCE level or the METHOD level.  Associating it with the RESOURCE level means the parameter is automatically "inherited" by any other method(s) created for its parent resource; it's added by default.  Associating it with the METHOD level means the parameter is only applicable to that method.  For this example, we'll just leave the parameters set to the default (RESOURCE).

A parameter's Style column indicates how the parameter is implemented-- the QUERY style corresponds to the standard "?parameter1=value1&parameter2=value2..." format you see as part of this GET request's URI.  Although POST requests are not supported by this example REST service, the QUERY type is also used when sending parameters in this format as part of the body (as opposed to the URI), as with POST requests.  For a POST request (and other methods allowing parameters in the message body), a checkbox is displayed that allows you to specify that parameters should be added to the request body instead of the URI.


To see an example of a different style, let's try adding a request to get the details for a specific card.  Right-click on the service in the tree and select "New Resource" from the context menu.  Another prompt appears-- note that once the host for the REST service has been established (via our previously created request), it's no longer necessary to enter the full URI when adding more resources.  The resource path by itself is sufficient.  Enter the following in the prompt:

/mtg/cards/about-face

You'll be asked if you want to add the new resource as a child of the existing Cards resource.  The parameters we added for the Cards resource aren't relevant to the single card request, so we're just going to add it as a completely separate resource.  Click No to the prompt.

There are no URI parameters for this request.  Instead, the last part of the resource path is the parameter.  We used "about-face" as the individual card id, but we can change the id to retrieve information for other cards.  This is where the TEMPLATE parameter style comes into play.  Open up the Request Editor dialog and add a new parameter called cardId.  Set its value to "about-face" and set the parameter's style to TEMPLATE.  You'll see the parameter appended to the resource path at the top of the dialog, enclosed in braces.  Edit the path to remove the hard-coded text "about-face", leaving the parameter to indicate the card id to retrieve:


After adding some additional resources and modifying some names to make them more descriptive, here's what our service looks like in our project:


In the next post, I'll look at using the REST service in a test suite.

Beginning soapUI Scripting: Javadocs 2

In my last post I started a discussion of javadocs, providing a high level overview. In this post I'll try to cover some of the keywords and concepts you may encounter when dealing with documentation for a class.

I have to admit I may have bitten off more than I can chew with this post, which accounts in part for the length of time it took me to publish it.  As I started looking at javadocs and javadoc keywords in more detail, I realized the post had to include explanations of a lot of basic Java concepts.  I hope I did an adequate job of explaining them, but I strongly encourage you to check out the official Java Tutorials to fill in the gaps (of which I'm sure there are a few).  I recommend the entire Learning the Java Language trail, but the particularly relevant sections include the sections on Classes and Objects and Interfaces and Inheritance.

Access Modifiers and Special Considerations for Groovy

Access modifiers-- private, package-private (which is the default when no modifier is specified), protected, and public-- specify the context in which a class and its members can be read and/or modified in code.  In the context of the basic usage of an API (when using it in a soapUI script, for example, as opposed to more advanced usage like making your own modifications to the source code), you're generally only going to deal with classes and members marked public.  The two most restrictive levels of access, private and package-private are reserved for those classes and members that represent "internal wiring"-- strictly intended for use within a class (private) or package (package-private), not intended for direct use by API consumers.  In fact, the Javadoc tool excludes classes and members with these access modifiers by default, in which case they don't even appear in documentation.  Members at the protected level are only slightly less restricted in that they're inherited by sub-classes of their enclosing class (even sub-classes that aren't in the same package)-- for somebody using the API, this comes into play when creating your own sub-class, something beyond the basic scripting covered here.

However, there's a very important caveat when working with Groovy.  When trying some scripting in soapUI with the HSSFWorkbook class, I was surprised to see that I could in fact access the _sheets field.  If you look at the documentation, this field is marked protected, meaning it should only be accessible from within the class, within other resources in the same package, or from within a sub-class-- a Groovy Script step doesn't fall into any of those categories.  After investigating, I found this interesting post indicating that Groovy doesn't always respect access modifiers (see item 6)-- that's potentially a bad thing; there are good reasons why an API developer might restrict access to a certain member of a class, particularly when it comes to modifying its value.  As the article says, just because Groovy allows you to do something doesn't mean you should do it; you may have to police yourself a bit-- be wary of accessing classes or members marked anything other than public.

Static and Final

The final modifier generally restricts a user's ability to modify a class or member, although it means slightly different things in different contexts.  Applied to a class, it means the class can not be extended-- you can not create a sub-class based on that class.  A final method can not be overridden in a sub-class; in other words, you can't change the way the method is implemented, writing new code for it in your sub-class.  The value of a field marked final can not be changed.  As with the more restrictive access modifiers discussed above, the final modifier at the class and method level isn't something you'll need to worry about too much with basic usage of the API; it's more relevant when you start dealing with sub-classes.  With fields, however, more often than not you'll see them marked final in javadocs, and the distinction is important even in the context of basic scripting.

The static modifier designates a class (as opposed to instance) member.  A non-static member is associated with an individual object-- an instance of a class.  I discussed the _sheets field of the HSSFWorkbook class above-- if you were to create two different HSSFWorkbook objects and add sheets to each, the _sheets field would be different for each object; each instance of HSSFWorkbook would have its own value for the field.  A static member, on the other hand, is associated with the class itself; when you access a class member, you access it through the name of the class, not the name of a variable representing an instance of the class:

log.info(myWorkbook._sheets) //_sheets is accessed for an HSSFWorkbook instance named myWorkbook-- can be done in Groovy
log.info(HSSFWorkbook.INITIAL_CAPACITY) //INITIAL_CAPACITY is accessed via the HSSFWorkbook class itself

It's common to use the static and final modifiers together with fields to create constants-- so common, in fact, that there's a convention in Java to use all caps in these fields' names (as with the INITIAL_CAPACITY field above).  Class constants often represent values that are frequently used; creating class constants for these values eliminates the need to repeatedly declare variables to hold them.  Java's Math class has the static final field PI, for example; similarly, the Color class has static fields to represent frequently used colors: RED, BLUE, etc.  Again, there's no need to create objects of class Math or Color to access these constants; they're called against the class names themselves (Math.PI or Color.RED, for example).

Methods, too, can be marked static.  Returning to Java's Math class as an example, aside from the standard methods it inherits from the object class, all of its methods are static-- the class is essentially a toolbox of mathematical operations.  As with static fields, static methods are accessed via the class instead of an instance.

Method Return and Parameter Types

Method definitions in javadocs specify return types (the data types of results from functions) and parameter type(s) (the types of the values passed into the functions).  For the most part, these should be pretty straightforward; for example, look at the WsdlTestCase class in the API documentation for soapUI.  In the Method Summary table, find the getTestStepByName() method; in the left-hand (Modifier and Type) column you can see that the return type is WsdlTestStep.  In the Method and Description column, you can see in the parentheses next to the method name that the method takes a single String argument called stepName-- note that stepName is a somewhat arbitrary parameter name; any variable name could have been used when the method was created (of course, stepName is a good choice because it describes the significance of the String argument).  From the perspective of somebody using the method, the parameter name itself is relatively unimportant; what is important is recognizing the method takes a single String argument and returns a WsdlTestStep object.

The void keyword is used for the return type when a method doesn't return a value.  The setName() function of the WsdlTestCase class, for example, changes a property of the test case without actually returning anything.  For functions that don't take any arguments, the parentheses next to the method name are simply left empty.

Some functions return multiple data items; for these, the "enclosing" data type is also indicated.  For example, the getTestStepList() method of the WsdlTestCase class specifies a return type of List<TestStep>, meaning it returns an object of class List containing zero (the list could be empty) or more TestStep objects (more about what that means below).  The getTestSteps() method returns an object of class Map; Maps consist of key-value pairs, so the return type specifies Map<String,TestStep>-- each key-value pair in the returned Map consists of a String (the key) and a TestStep object (the value).

In some cases, a method's parameter and/or return types are determined at runtime, in which case you'll see a slightly complicated-looking syntax. Look at the getTestStepsOfType() method, for example.  The return type is given as <T extends TestStep> List<T>.  There's no T class, of course.  The T is used as a placeholder for a data type to be determined later.  The <T extends TestStep> part of the return type tells us that there's a restriction on T-- it has to be a type that's derived from the TestStep interface (a class that implements the TestStep interface, for example, or a class that extends another class that implements the interface, etc.), and the rest (List<T>) tells us that the method returns a List of objects of that type.  So how is the type actually determined? If you look at the method description column, getTestStepsOfType(Class<T> stepType) tells us that type T is the type of the class passed in for the stepType argument-- so the argument determines the meaning of T in the return type definition as well.

Return Types and Polymorphism

Above, when discussing the getTestStepList() method, I wrote that it returns a list of TestStep objects.  If you were to look at the TestStep definition in the javadocs, however, you'll see that TestStep is actually not a class-- it's an interface.  In my last post I mentioned that you can't actually create an instance of an interface.  What's going on here?  This is actually an illustration of the object-oriented concept of polymorphism-- it's a source of great flexibility and power in Java, but for me, at least, it was a source of some confusion when I first started working with javadocs.  In a very simplified nutshell, polymorphism means an object can be many things at the same time. Because an object can extend another class and/or implement multiple interfaces, it shares their characteristics and can be used wherever a parent class or any implemented interfaces are called for.  So for example, if an interface is specified as a method parameter or return type (as with the getTestStepList() method), it means that the method will take or return an object of a class that implements the given interface.  The same principle applies to classes that are sub-classed: if a class is given as a parameter or return type, the method can actually take or return an instance of the class or any sub-class of that class.  For example, WsdlTestStep is the return type for the getTestStepAt() method.  If you look at the javadoc entry for WsdlTestStep, you'll see that it has three sub-classes: WsdlPropertiesTestStep, WsdlRunTestCaseTestStep, and WsdlTestStepWithProperties (which itself has its own sub-classes).  The specific class returned by the method, then, can be any of the sub-classes of WsdlTestStep (including the sub-classes of the WsdlTestStepWithProperties class).

The problem with polymorphism in the context of javadocs is that they may not indicate the specific class that's ultimately returned by a call to the method in your script.  Knowing the class of the returned object is important, of course, in order to know what methods and properties are available to that object.  If push comes to shove, you can identify an object's class by using the getClass() method-- this is a basic method inherited by all classes from Java's Object class:
def myTestStep = testCase.getTestStepAt(1)
log.info(myTestStep.getClass())
//Example output: class com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep
//The return type specified in the javadoc for getTestStepAt() is WsdlTestStep
//The object returned is actually an instance of an indirect sub-class of the WsdlTestStep class