ContributionsMost RecentMost LikesSolutionsHow to write a reusable script Library I've found the need to define a common Library of reusable Groovy Scripts for use with SOAPUI community edition, there isn't a tutorial or established examples on how this can be achieved so here is an example of how I did this. 1) Define a new TestSuite in the root of your project called Library. 2) Disable the Library TestSuite so that it doesn't get run in an uncontrolled manner. 3) Define a TestCase under Library, I name this after the module-name. 4) Define a Groovy Script, I give this the name of the Groovy Class that is going to contain my reusable code. class Example { def log def context def testRunner // Class constructor with same case as Class name def Example(logIn,contextIn,testRunnerIn) { this.log = logIn this.context = contextIn this.testRunner = testRunnerIn } } 5) Add the reusable code as method, pass parameters as necessary. def execute(message) { // do some stuff to prove I've run with right context, etc. log.info testRunner log.info context log.info "return "+message return message } 6) We need to instance of the class; add the following to the end of the Script, outside the class definition. This will place the instance in the project's context. context.setProperty( "example", new Example( log, context, testRunner) ) log.info "Library Context:"+context 7) You can now reuse the instance in any Groovy Script, with the following Groovy code. // get a reference to the library TestSuite library = testRunner.testCase.testSuite.project.testSuites["Library"] // find the module within the library module = library.testCases["module-name"].testSteps["Example"] // initialise the library; which places an instance of Example in the context module.run(testRunner, context) // get the instance of example from the context. def example = context.example // run the method, with parameter log.info "example.execute() = " + example.execute("Tester") 😎 Add more modules, classes or methods as necessary. 9) The instance can be added to the Global context if you want to use it across SOAPUI projects. 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 forMeta-Programmingto factor and enhace my tests. I thought I would share the latest meta-coding script I've added to myReusable 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 syntaxusing 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 forGiven and Thenaround 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 theLibraryTestSuite 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 Re: How to call function from another groovy code? How to write a reusable script Library using Grooby in SOAPUI, with no external dependencies. https://community.smartbear.com/t5/SoapUI-Pro/How-to-write-a-reusable-script-Library/m-p/29499 Re: What is the best way to version paths? Best, I'm not sure, but apretty effective technique that works well both server and client sideis to seperate a logical URI path from a physical (URL) version path. In the physical realm I would keep as seperate yaml versions. /v2/users/{id} /v1/users/{id} On top of that provide logical URI paths, where I've used current or latest, use naming consistent with your organisation norms, so these might be live, staging or whatever makes sense to your peers. /current/users/{id} - the current live version /latest/users/{id} - might be the overnight build /legacy/users/{id} - the previous version I typically prefix the API with its unique identifier/name even if that would be currently redundant. /sso/current/users/{id} -> /sso/v2/users ... /sso/latest/users/{id} -> /sso/v3/users... /sso/legacy/users/{id} -> /sso/v1/users... Re: Run as administrator The fact this used to work and doesn't now is suggestive of an external factorsuch as aGroup policy change by your organisation's windows administrators. You could try re-installing it to your local user folder, something I do anyway. Re: is there any option to read the total project execution time through groovy Thetotal execution timeof test project is essentially a meaningless metric from a performance testing point of view unless you can eliminate the non-determinacy of network latency. It might be slightly useful as a very broad responsiveness under load with a sufficient large sample. If you still want to do it, then use the groovy provided byShasiSinghbut I suggest putting it in the Setup & TearDown scripts for the Test Suite. Re: How to have a failed step within a loop to be logged in transaction log Can you edit your post and embed the code in code tags, you're making it hard to read and therefore less likely to get an answer. All useful tests need to assert that the behaviour is correct, that what was expected actually happened. You will need to assert something after each step to ensure you catch the error. http://groovy-lang.org/style-guide.html#_catch_any_exception passed = true // while (...) { // get test step by name // run the test step // verify the result verify(expected == actualResult) } assert passed def verify(def condition) { try { assert condition } catch (AssertionError assertion) { log.info assertion passed = false } } TestRunner.runTestStepByName(...) returns a TestStepResult you can use. https://support.smartbear.com/readyapi/apidocs/soapui/com/eviware/soapui/impl/wsdl/panels/support/MockTestRunner publicTestStepResultrunTestStepByName(Stringname) Re: SOAP returning empty string . This is a community forum so people will respond at their own pace. You can make this more likely by posting a question that is clear. Your question is unclear and needs editing to provide sufficient information to be able to help. Re: Calling java class from mock script To use a Java class such asBase64 you must have the import and the jdk must be on the class path. Goovy does include the following classes by default. import java.lang.* import java.util.* import java.io.* import java.net.* import groovy.lang.* import groovy.util.* import java.math.BigInteger import java.math.BigDecimal However in this case Groovy already has built in base64 encoding/decoding.http://docs.groovy-lang.org/2.4.3/html/api/org/codehaus/groovy/runtime/EncodingGroovyMethods.html String encoded = 'AUTHORISATION-TOKEN'.bytes.encodeBase64().toString() log.info encoded byte[] decoded = encoded.decodeBase64() log.info new String(decoded) I'd question the need for mock to actually need to authorisatise, in most cases I test for their presence not their values. Re: How to Trigger Testsuite (SOAPui free version) from CI/CD pipeline of gitlab? The link includes detailed steps to set it up, the only bit missing is pulling the code from gitlab which would require an <scm>...</scm> section adding to the pom file: e.g. Which is explained here:https://maven.apache.org/scm/maven-scm-plugin/examples/bootstrapping-with-pom.html