1
votes

We have few soapui projects each sending testrequests at different web services. The Groovy script that executes the tests is however for the most part identical for each project. Therefore we decided it would be good with regard to easy versioning and maintenance to keep the common script in separate "dummy" project ("TestWSScript-soapui-project.xml") with one testsuite/case (Autotest/Test) with only one testStep (Groovy script named "Run"). The idea is to have one project for each WebService (say WS1-soapui-project.xml) which has testSuite with one TestCase. Within this TestCase will be

  • Groovy test step to set WS specific properties and call the universal script from TestWSScript-soapui-project.xml
  • Request test step to call the webservice and perform assertions
  • Ending Groovy test step.

This works from within SoapUI, but I want to run the tests from Windows command line (batch file for automatization purposes). Here I ran into a problem: when invoking testrunner from command line with

set "SOAPUI_FOR_TEST_DIR=..\..\..\programs\SoapUI-5.6.0"    
"%SOAPUI_FOR_TEST_DIR%\bin\testrunner.bat" -sAutoTest -r -a -j -I "..\resources\WS1-soapui-project.xml"

it does not load whole workspace with all SoapUi projects. Therefore the following script (in WS1-soapui-project.xml/AutoTest suite/Test TestCase) that should run testStep from project TestWSScript-soapui-project.xml/AutoTest suite/Test TestCase returns Null (more specifically "Cannot invoke method getProjectByName() on null object")

import com.eviware.soapui.model.project.ProjectFactoryRegistry
import com.eviware.soapui.impl.wsdl.WsdlProjectFactory

def workspace = testRunner.testCase.testSuite.project.workspace
def testProject = (workspace==null) ? 
  ProjectFactoryRegistry.getProjectFactory(WsdlProjectFactory.WSDL_TYPE).createNew("TestWSScript.xml") :
  workspace.getProjectByName("TestWSScript")
if(!testProject.open && workspace!=null) workspace.openProject(testProject)


// Connect to the test step in another project.
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName('TestWSScript')
tCase = prj.testSuites['AutoTest'].testCases['Test']
tStep = tCase.getTestStepByName("Run")

// Call the test runner and check if it can run the specified step.
def runner = tStep.run(testRunner, context)

The called script just loops through parameters read from csv file and calls request step. It is irrelevant for the problem I need to solve as the issue happens before the script is called.

Is there even a way to achieve what we want? We are using the free version of SoapUI-5.6.0. Thanks in advance.

1
If you're already running it from Windows command line, (assumed cmd.exe), why are you using cmd.exe /C to launch another cmd.exe instance? Also if you're running a batch file, as those are already processed by cmd.exe, why use cmd.exe at all, as opposed to just running the batch file directly. I also note that there's no doublequotes in your provided command-line, and you've not given us any idea whatsoever, of the content of any of the variables it contains, or how those were defined. We need to be able to replicate your issue, please read minimal reproducible example for more information on what that means. - Compo
Thanks for response. I tried to clear it a bit of the unneeded parameters and add better explanation of the process. The cmd.exe was inherited from my colleague and has no explicit meaning so I removed it. Is it clear now? - Matěj Morávek
You still should have two sets of double-quotes on the second line; one enclosing the .bat file path, and one enclosing the .xml file path. - Compo
Why? There is no space in the path so quotes are not necessary. It works perfectly fine this way. Nevertheless, I added them so it is absolutely universal, if you need it. More importantly, this call is NOT where the issue occurs, you are nitpicking on something that does not help solve my problem. - Matěj Morávek
You posted a question which uses inherited, (read as unsolicited) code, with no request whatsover for 'no unsolictied advice'; and therefore that advice is implied. Your decision is simply whether you wish to action, or ignore, that advice, not to complain that you've received it. - Compo

1 Answers

0
votes

Here is what I suggest in your case.

  • Instead of a separate project for just one groovy script, create a library out of it.
  • Create a class and methods as needed. Use method arguments or class members in case if you are passing data from the callers.
  • Use your existing script, convert them into class, methods.
  • Create the class(es) based on the need.
  • It can be programmed either java or groovy
  • Compile the class(es) and create library
  • Copy this library under %SOAPUI_HOME%\bin\ext directory
  • Now you can just call those methods in any project. No more dummy project is required.
  • Good thing is all the projects are independent.

Here is blog content created by Rupert Anderson, one of the SoapUI export and Author.

Steps

1.Create the following directory structure

soapuilib/src/main/groovy/custom

2.Get some Groovy code

For this example, I have knocked together a simple script to generate sequential ids. It may be of little practical use, but I wanted something with a simple public static method to call. Since the method is static, there will be no need to instantiate the class before calling it in step #8.

[groovy title=”SequentialIdGenerator.groovy”]
package custom

import java.util.concurrent.atomic.AtomicLong

public class SequentialIdGenerator {
public static final long counterSeed = 1000
public static final String prefix = "id"
private static AtomicLong counter = new AtomicLong(counterSeed)

public static String nextId() {
return prefix + counter.incrementAndGet()
}
}
[/groovy]

    create the above script as a text file called SequentialIdGenerator.groovy
    copy it to soapuilib/src/main/groovy/custom

3.Create Gradle build script

For this part, there are plenty of options to build the code and package it, such as Maven, Ant or just running the right shell commands! The following minimal Gradle script allows us to compile and package the code as a jar in one easy statement.

[code language=”groovy”]
apply plugin: ‘groovy’

version = ‘1.0’

jar {
classifier = ‘library’
manifest {
attributes ‘Implementation-Title’: ‘SoapUI Sample Groovy Library’, ‘Implementation-Version’: version
}
}

repositories {
mavenCentral()
}

dependencies {
compile ‘org.codehaus.groovy:groovy:2.1.7’ //Matches Groovy in SoapUI 5.2.1
}

[/code]

    Create the above Gradle script as soapuilib/build.gradle

INFO: Groovy Version – (At time of writing) The current version of Groovy is v2.4.6, but SoapUI 5.2.1 ships with Groovy 2.1.7. If you try to compile with a Groovy version 2.3+ and use it with SoapUI, you will see an error popup and log message in like ‘org/codehaus/groovy/runtime/typehandling/ShortTypeHandling‘ – see http://glaforge.appspot.com/article/groovy-2-3-5-out-with-upward-compatibility for more details and options. Basically, you can still use the latest Groovy version, but will need to include an additional groovy-backports-compat23 dependency!

5.Compile it & Create jar file

Now we’re ready to use the Gradle script to compile the sample script from step #2 and package it as a jar file.

    Open a shell/command prompt at soapuilib/
    gradle clean build jar

You should then see output like:

[bash]

tests-MacBook-Pro:soapuilib test$ gradle clean build jar
:clean
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 5.499 secs

This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.12/userguide/gradle_daemon.html

[/bash]

and our new library jar file created under the directory:

soapuilib/build/soapuilib-1.0-sample.jar

6.Add jar file to SoapUI

To make our new Groovy library jar available for use in SoapUI, it should be added in SoapUI Home under the following external library directory:

SoapUI ext Directory

Or the Windows equivalent e.g. C:\Program Files\SmartBear\SoapUI-5.2.1\bin\ext

7.Verify jar file is imported

When SoapUI is restarted, you should see the following log entry indicating that the jar file has been successfully added to the SoapUI classpath:

SoapUI ext Lib Loaded
8.Call the code

Our SequentialIdGenerator has a public static method nextId() that we can call, so to do this we can either import the class (Example 1)  or just prefix the class with its package (Example 2). See below:

    Example 1 – Call from Groovy TestStep:

[code]
import custom.*

log.info SequentialIdGenerator.nextId()
[/code]

Gives output like:

[code]

Thu May 12 16:49:20 BST 2016:INFO:id1001

[/code]

    Example 2 – Call from Property Expansion:

[code]

${= custom.SequentialIdGenerator.nextId()}

[/code]

EDIT: Here is the sample code with context, log variable access.

<script src="https://gist.github.com/nmrao/c489a485bbe3418cf49d8442f9fb92eb.js"></script>