Forum Discussion

MartinSpamer's avatar
MartinSpamer
Frequent Contributor
6 years ago

Let's talk Meta Programming to automatically refactor test cases in SOAPUI

One of SOAPUI's most powerful features and certainly my favourite is using Groovy for Meta-Programming to factor and enhace my tests.  I thought I would share the latest meta-coding script I've added to my Reusable Script library .

 

This script can be used to enhance and cleanup a TestSuite that is created automatically using the built in feature Interface -> Generate TestSuite.  I import quite a lot of my REST API and this approach saves me a lot of grunt work.

 

Script Features:

  1. Renames each RestReqest from "Request N" to something more appropiate following a basic BDD syntax using the HTTP Method and the resource description to provide appropriate description. e.g.
    • "Request N" using a "HTTP GET /account"
    • becomes "When /account is Retrieved"
  2. If the TestCase contains multiple requests these are split into new approriately named TestCases using the above convention to comply with the automated testing best practice of testing one thing at a time.
  3. Adds an Groovy script for Given and Then around each Request step in each TestCase.

To use this script.

 

  1. Define a Library TestSuite in the root of the project you want to refactor.
  2. Disable the Library TestSuite so that it doesn't get run in an uncontrolled manner.
  3. Define Meta-Programming Testcase to get this:

     

  4. Create a Groovy script in Meta-Programming and add the following code:
  5. Then simply run the Refactor Generate Tests.
refactorGeneratedTests(testRunner.testCase.testSuite.project)
cleanUp(testRunner.testCase.testSuite.project)

def refactorGeneratedTests(def thisProject) {
	assert thisProject
	log.info "Processing ${thisProject.name}"

	for (testSuite in thisProject.testSuiteList) {
		if (!testSuite.isDisabled()) {
			log.info "- ${testSuite.name}"
			for (testCase in testSuite.testCaseList) {
				if (!testCase.isDisabled()) {
					log.info "-- ${testCase.name}"

					renameRequestSteps(testCase)

					forEachRequestMake(testCase)

					ensureBdd(testCase)
				}
			}
		}
	}
}

def renameRequestSteps(testCase) {
	assert testCase
	assert testCase instanceof WsdlTestCase
	def languageMap = [ "GET": 'Retrieved', "POST": 'Created', "PUT": "Updated", 'DELETE': 'Deleted']
	log.info "languageMap : ${languageMap}"

	boolean isFirst = true
	for (testStep in testCase.testStepList) {
		log.info "--- ${testStep.name} ${testStep.getClass().getSimpleName()}"
		if (isREST(testStep)) {
			if (testStep.label.startsWith("Request")) {
				String restOperation = testStep.getOperation().getName()
				log.info "restOperation : " + restOperation
				String methodType = testStep.getRestMethod().getMethod()
				log.info "methodType : ${methodType}"
				actionName = languageMap.get(methodType)
				log.info "actionName : ${actionName}"
				String newStepName = "When ${restOperation} is ${actionName}"
				log.info "${newStepName}"

				testStep.setName(newStepName)
			}
		}
	}
}

def forEachRequestMake(testCase) {
	assert testCase
	assert testCase instanceof WsdlTestCase
	def languageMap = [ "GET": 'Retrieve', "POST": 'Create', "PUT": "Update", 'DELETE': 'Delete']
	log.info "languageMap : ${languageMap}"
	
	boolean isFirst = true
	for (testStep in testCase.testStepList) {
		log.info "--- ${testStep.name} (${testStep.getClass().getSimpleName()})"
		if (isREST(testStep)) {
			String restOperation = testStep.getOperation().getName()
			log.info "restOperation : " + restOperation
			String methodType = testStep.getRestMethod().getMethod()
			log.info "methodType : ${methodType}"
			actionName = languageMap.get(methodType)
			log.info "actionName : ${actionName}"
			String newTestCaseName = "${actionName} ${restOperation} "
			log.info "${newTestCaseName}"

			if (isFirst) {
				testCase.setName(newTestCaseName)
				isFirst = false
			} else {
				// clone the test for each REST request
				testCase.testSuite.cloneTestCase(testCase, newTestCaseName);
			}
		}
	}
}

def ensureBdd(testCase) {
	assert testCase
	assert testCase instanceof WsdlTestCase

	givenStep = "Given content for the request"
	if (testCase.getTestStepByName(givenStep) == null) {
		testCase.insertTestStep("groovy", givenStep, 0)
	}

	thenStep = "Then the response is as expected"
	if (testCase.getTestStepByName(thenStep) == null) {
		testCase.addTestStep("groovy", thenStep)
	}
}

def isREST(def testStep) {
	assert testStep
	return testStep instanceof RestTestRequestStep;
}

def addHttpStatusAssertions(testStep) {
	assert testStep
	return testStep instanceof RestTestRequestStep;
	if (testStep.getAssertionCount() == 0) {
		testStep.addAssertion("Valid HTTP Status Codes").setCodes("200")
		testStep.addAssertion("Invalid HTTP Status Codes").setCodes("400, 500")
	}
	log.info testStep.getAssertionList()
}

def cleanUp(def thisProject) {
	assert thisProject
	log.info "${thisProject.name}"
	for (testSuite in thisProject.testSuiteList) {
		log.info "- ${testSuite.name}"
		for (testCase in testSuite.testCaseList) {
			log.info "-- ${testCase.name}"
			String actionName = testCase.name.split().head()
			log.info "-- ${actionName}"
			for (testStep in testCase.testStepList) {
				log.info "--- ${testStep.name} ${testStep.getClass().getSimpleName()}"
				if (isREST(testStep)) {
					if (testStep.name.contains(actionName)) {
						log.info("keep ${testStep.name} in ${testCase.name}")
					} else {
						log.info("remove ${testStep.name} from ${testCase.name}")
						testCase.removeTestStep(testStep)
					}
				}
			}
		}
	}
}

//	https://www.soapui.org/apidocs/com/eviware/soapui/impl/wsdl/teststeps/RestTestRequestStep.html
//	class com.eviware.soapui.impl.wsdl.WsdlProject
//	class com.eviware.soapui.impl.wsdl.WsdlTestSuite
//	class com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
//	class com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep

log.info context.getClass()
log.info testRunner.getClass()
log.info testRunner.testCase.getClass()
log.info testRunner.testCase.testSuite.getClass()
log.info testRunner.testCase.testSuite.project.getClass()
log.info testRunner.testCase.testSuite.project.workspace.getClass()

import com.eviware.soapui.impl.wsdl.WsdlTestSuite
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep

 

No RepliesBe the first to reply