Overhaul: Test Automation with SoapUI using JsonBuilder and JsonSlurper

I was looking into various ways to do more efficient creation of Json on the fly using the techniques I’ve described in my previous posts. However, while you can do it these ways (which would have to include writing your own parser) there’s a much easier solution, which I’m just glad to have realized sooner rather than later.

I still believe the best way to do automated regression is in a script library away from SoapUI; it gives far more flexibility when the need to make changes inevitably occurs. Keeping that in mind the following approach is not only easier but not hard to implement. Instead of passing each parameter per column in Excel, you can pass the entire Json string in one column. Then, using a combination of the JsonSlurper and the JsonBuilder/StreamingJsonBuilder, you can create valid Json.

So, how do you do it. Consider the following code below, which can be used for any Json you would pass in. The ‘rawJsonString’ is created because if someone pastes json into the Excel cell it can be in a ‘pretty’ format. At least this way we strip out any returns and newlines and let the inbuilt JsonSlurper handle the rest.

The simple function, jsonToMap, creates a new JsonSlurper, parses the text (just like you could do for your assertions), and returns the result.

Finally, we need to actually create our json that will appear in the body of our Rest request. Here’s where the StreamingJsonBuilder comes in. We use StreamingJsonBuilder because we aren’t manipulating or have a need at all for keeping anything in memory. After doing some research this is a cleaner solution and behaves similarly to the JsonBuilder referenced in earlier posts.

The function, CreateObject, takes the parameters ‘root’ and ‘map’. Root is taken from the createJSON function. In most calls you’re either going to have a root with a bunch of given parameters, lists, etc, under it, or it’s just going to be a list of parameters. Since you’re pasting in the rest of the Json in the value of your test case parameter you just need that one value before the output of jsonToMap. If you wanted to you could take out root entirely and just pass the whole json including the root. I think this way provides more possible flexibility going forward. The rest of the function should be self explanatory.

The code that would be in your SoapUI Groovy script is:

def req = new Json()
req.createJSON(testRunner,4,'RootObject')

The code that is used to create the json:

public class Json {

	def createJSON(testRunner,testStepLocation,root) {
		//properties
		def request = testRunner.testCase.getTestStepAt(testStepLocation).getTestRequest()
		def tcProps = testRunner.testCase.getProperties()
		def map
		def rawJsonString
		def prettyPrintJson
		
		//grab objects
		for (p in tcProps) {			
			if (p.value.getValue() != "") {	
					prettyPrintJson = p.value.getValue()	
					rawJsonString = makeSingleLineJson(prettyPrintJson)
					map = jsonToMap(rawJsonString)
			}
		}			
		if (root != null) {
			def object = CreateObject(root, map)
			request.setRequestContent(object)
		} else {
			request.setRequestContent(rawJsonString)	
		}
	}
	
	//create Object
	def CreateObject(root, map) {
		def jsonWriter = new StringWriter()
		def builder = new groovy.json.StreamingJsonBuilder(jsonWriter)				
		def r = builder {						
				"${root}"(map)						
			}				
		def json = groovy.json.JsonOutput.prettyPrint(jsonWriter.toString())
		json = groovy.json.StringEscapeUtils.unescapeJava(json)
		return json
	}
	
	//convert the given json
	def jsonToMap(someJson) {
		def slurper = new groovy.json.JsonSlurper()
		def result = slurper.parseText(someJson)
		return result	
	}
	
	def makeSingleLineJson(prettyPrintJson) {
		def rawJson = prettyPrintJson.replaceAll("\\r?\\n","")
		return rawJson	
	}
}