MartinSpamer
6 years agoFrequent Contributor
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:
- 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"
- 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.
- Adds an Groovy script for Given and Then around each Request step in each TestCase.
To use this script.
- Define a Library TestSuite in the root of the project you want to refactor.
- Disable the Library TestSuite so that it doesn't get run in an uncontrolled manner.
- Define Meta-Programming Testcase to get this:
- Create a Groovy script in Meta-Programming and add the following code:
- 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