SoapUI Groovy: Using JSONBuilder to create JSON from TestCase properties that contain an Object

Please see updated post here for a simpler solution.

I looked around and couldn’t find a simple solution to creating JSON from test case properties while one of the properties already had a written out object. My requests ended up having quotes where they shouldn’t have, badly formed JSON, or just blank in some areas.

Let’s say this is what my SoapUI TestCase Properties used to look like when grabbed from Excel:

tcPropsExample

So, the JSON is more or less written out for my MyObject property. I also tried different combinations, for example, writing out “MyObject” : {“Date”:…..etc} or { “MyObject” : {“Date” :……etc} and using that as the property value, but nothing worked out of the box like I wanted it to.

Now, I still have other properties in there that I want to make part of my JSON call, in the end I want a structure like:

{
    "A": "value",
    "DefinedObject1": {
        "X": "value",
        "Y": "value"
    },
    "DefinedObject2": {
        "Date": "value",
        "Param1": "value",
        "Param2": "value"
    }
}

I don’t know if there’s a better solution to this, but instead of passing in well formed JSON as a value I write out the JSON using ‘=’ instead of ‘:’ and ‘&’ instead of ‘,’.

Which ends up looking like this in an editor:

json1

Then I use this Groovy script for creating my JSON body:

package qa

public class MyClass {	

	def createJSON(testRunner,testStepLocation) {

		//properties
		def request = testRunner.testCase.getTestStepAt(testStepLocation).getTestRequest()
		def tcProps = testRunner.testCase.getProperties()
		def map1 = [ : ]
		def map2 = [ : ]
		def object1
		
			//grab all the properties from the test case and put them in a map as long as they aren't empty
			for (p in tcProps) {
				if (p.value.getValue() != "") {
					if (p.key.equals('A')) {
						map1.put(p.key, p.value.getValue())
					} else if (p.key.equals('X') || p.key.equals('Y')) {
						map2.put(p.key, p.value.getValue())
					} else if (p.key.equals('MyObject')){
						object1 = p.value.getValue()
					}
				}
			}

			if (object1 != null && object1 != "") {	

			//remove line break characters from the string
			object1 = object1.replaceAll("\\r?\\n","")
			
			//split the string for the object into a new map
			def object1Map = object1.split('&').inject([:]) { map, token ->
				token.split('=').with { map[it[0]] = it[1] }
				map
			        }
			}			
			def builder = new groovy.json.JsonBuilder()

			if (object1 != null && object1 != "") {	
			  def root = builder {
				map1.each() {
					key,
					value -> "${key}" "${value}"
				}
				DefinedObject1 {
					map2.each() {
						key,
						value-> "${key}" "${value}"
					}					
				}	
				DefinedObject2 {		
					object1Map.each() {
						key,
						value -> "${key}" "${value}"
					}
				}
			  }
			} else {  //could add more if/else statements here to cover all scenarios but you get the idea
			  def root = builder {
				map1.each() {
					key,
					value -> "${key}" "${value}"
				}
				DefinedObject1 {
					map2.each() {
						key,
						value-> "${key}" "${value}"
						}					
					}	
				}
			}			
		def json = builder.toPrettyString()
		json = groovy.json.StringEscapeUtils.unescapeJava(json)
		request.setRequestContent(json)
	}
}

I think the comments inline make it pretty self-explanatory but just to clarify this is what happens:

1) Grab all the TestCase properties and split them up into different maps
2) If it’s MyObject as the key (property name) then instead just grab the value and assign it to a string variable
3) Strip said string of any new line characters if not null/empty
4) Fancy code that I got from StackOverflow here that basically just says “Split up my string based on X and Y delimiters and make it a map”
5) If statements to cover different structure if variables are null/empty
6) Create the JSON based on those three maps we just created

Enjoy!

Advertisements

Making things organized…

I recently compared a few other tools to SoapUI, but for the price and compared to what has already been done, nothing stuck out.

Here’s a quick recap with some improvements that were necessary..

Say you have a group of testers all using the same SoapUI composite project. JSON calls are normally a mix of POSTs and GETs. For the POSTs, you can setup a WSDL-like environment that are separated by categories and have various calls under them.

For POSTs regression you can have a loop that’s the same for each API (more complex ones can have their own scenario based calls):

– Datasouce – Excel
– Property Transfer
– CreateValidJSON – Groovy Script
– Add Assertions – Groovy Script
– JSON Request
– ExcelDataSink – Output Pass/Fail Results to Excel Docs
– OutputRequestResponseFile – Groovy Script
– Loop

You can create other test cases or suites to cover specific testers if you want. You can then create your own cases to test your enhancements or bugs and check into SVN (if you use a repository) against the given Jira number. Handy plugin. Regression cases can be tracked by entering them into the Excel Datasources and again checked in against the given Jira number. To get around multiple testers updating regression sheets at once you can put locks on all your Excel documents.

Getting back to SoapUI…I really, really wish it had a Composite Action -> Test Suite option. This would allow the ability to save a test suite/reload a test suite without having to do a full project save/update. I saw it as a future enhancement so we’ll see if it’s ever implemented. For now, you need to refresh the whole project at the end of a cycle or when you need to see each others updates. Not a huge deal.

Recent improvements to SoapUI…

In version 5.0, they made a lot of headway (which has been nice) from when we first stated setting up REST testing. For one, they’ve upgraded the Groovy jar file that’s included (yay!). They’ve also made the creation of requests based off URI more user friendly and updated the parameters GUI so it’s less..for lack of a better word…buggy. I’m pretty sure they’ve fixed either a memory leak bug or an issue related to it, because even without updating the JVM memory parameters I’m no longer occasionally crashing.

Things I’m working on…

So, going forward I’ll be looking at better ways to pass entire objects through from Excel to SoapUI to then convert, using Groovy, into valid the JSON. That’s been a little problematic so far. I’ve done it, but it’s not pretty and is really a trick of the whole system that I can’t expect other testers to deal with.