IT Strategy

How to Use Groovy Scripts in SoapUI for Test Requests

Highlighting the main functionality for writing Groovy scripts in the SoapUI open-source application.

SoapUI is a convenient GUI application for testing REST API and SOAP Web Services, which exists in 2 versions: Pro and Open-source. Here we will consider the Open-source version and how to use it with Groovy scripts.

The SoapUI application is written in Groovy. We will add scripts in our tests written in Groovy (although Java syntax is valid for Groovy as well).

SoapUI is a test case constructor that allows you to build tests from current API queries. Below is a screenshot of SoapUI v. 5.5.0 for Windows:

Check out a related article:
SoapUI v. 5.5.0 for Windows

As a test project, we will use the simple Students application (Node.JS + JS) that creates, edits, and deletes users.

Installation:

>git clone https://github.com/EdIzotov/studentsApp.git
>cd studentsApp
>npm install
>npm start

WebUI is available in the application http://localhost:3000/, so it will not be difficult for us to see the API requests and transfer them to the SoapUI app:

SoapUI app
POST /api/users – create user
GET /api/users – get users
PUT /api/users/ID – edit user
DELETE /api/users/ID – delete user

Creating SoapUI project

Let's create a new REST project:

new REST project

and then copy requests into the project:

copy requests into the project

Creating test case

Now let's move on to the test case using the Navigator panel:

Navigator panel

If we right-click on "Test Steps" in the Navigator panel, we will see a list of the main elements for building the test:

Test Steps

Now let's come up with some kind of test. The scenario will be as follows:

  1. Get a list of users.
  2. Create a new user. Check that it is created.
  3. Edit this user and check the changes.
  4. Delete the user and verify that it is deleted.

As action requests, it will look like this:

  1. GET /api/users - fix the users that exist in the system
  2. POST /api/users - create a new user
  3. GET /api/users - get a new list of users to check
  4. PUT /api/users/ID - edit the user
  5. GET /api/users - get a new list of users to check
  6. DELETE /api/users/ID - delete the user
  7. GET /api/users - get a new list to check

Add a REST request for each step:

REST request

Pay attention:

To generate test data, you can invoke static Java methods from anywhere using the "${}" syntax. Also note that many tasks of transferring properties from one step to another one can be solved using the "Property Transfer" element. But we will use Groovy Scripts, because Groovy provides more flexible features. In addition, not all tasks can be solved using Property Transfer, unlike scripts.

Groovy scripting

Values initialization

Now you will learn how to set a property value in SoapUI using Groovy Script. At first, create the first Groovy Script which will set the initial values like this below:

first Groovy Script

Now a little attention to the scripts. There are 2 types of scripts in SoapUI: scripts - test steps, scripts - assertions. Script Assertions will be discussed later in this article. The difference between the two is that Groovy Script is called with the "log", "context", "testRunner" variables, and the Script Assertion is called with the "log", "context", "messageExchange" variables.

We'll immediately deal with the "log" variable in this script and run it by clicking on the launch button on the panel:

log.class

You will receive a message that will show the class of this variable. This will prove to be a classic Logger from Apache.

Please note that unlike Java, where it is customary to use getters and setters, they are created automatically in Groovy. And we can handle both in the Java style - log.getClass () - and in the Groovy style - log.class. They are the same.

If you want to see all the methods of the Logger class, we can do this through reflection (because the script editor in SoapUI does not offer auto-substitution as well-known IDEs):

log.class.methods.collect {method -> return method}

Basically, we will need standard logger methods: log.info, log.debug, log.warn, log.error

For Groovy methods, it is not necessary to use parentheses to call a method if you do not pass any arguments. The "collect" method iterates over the collection, and inside the body of the method, you can change the value of the element. The body uses an anonymous block of code called "Closure". 

Groovy also has a unary "Closure" that you can use if you don't need to manipulate the elements of the collection - this is a reserved word "it":

log.class.methods.collect {it}

Now let's deal with the "context" variable:

context

Context is used to store intermediate results in the current test. We will use it to transfer values between test steps:

context.userName = UUID.randomUUID().toString()
context.userPhone = System.currentTimeMillis()

We use the generation of random values that practically ensure uniqueness (UUID and Unix Timestamp). Also note that when calling these methods, we must use parentheses, because these are Java methods.

We will also transfer this data to CreateNewUser. To do this, we need to add 2 fields of the style "Plain" to a CreateUser request:

CreateUser request

And now we will pass values to these fields in Groovy Script. For this, we will use the "testRunner" variable. "testRunner" is used to control test steps and store/pass values to them. In the above way (through reflection), you can easily get a list of methods for working with this variable:

testRunner.testCase.getTestStepByName('CreateNewUser').setPropertyValue('userName', context.userName)
testRunner.testCase.getTestStepByName('CreateNewUser').setPropertyValue('userPhone', context.userPhone)

Basically, our first step is done:

first step is done

GET /users initial values

Now consider the GetUsersInitial step. We will get the current list of users in the step. It is recommended to add checks for each step using Assertions at the bottom of the window:

consider the GetUsersInitial step

The list of possible assertions includes those that can be used without Groovy. But we will add all checks through Script Assertion:

checks through Script Assertion

First, consider the messageExchange variable:

messageExchange.class.methods.collect {it}

And we will see that there are some methods for working with the Request => Response pair. For example, getResponseContent() and getResponseStatusCode(). Let's try to call and get data:

messageExchange.responseStatusCode

And then we want to check:

assert messageExchange.responseStatusCode == 200

Now get the response body and save it in the context:

context.getUsersInitial = messageExchange.responseContent

The step is done:

The step is done

Creating user with POST /api/users

Handle the CreateNewUser request. To use our "username" and "userPhone" values in the request body, we need the ${} construct:

Handle the CreateNewUser request

And similar to the previous REST request, add Assertion:

assert messageExchange.responseStatusCode == 200

Passing user ID to next steps

Now add one more Groovy Script to ensure that the created user ID is passed to edit and delete requests:

edit and delete requests

This way we get the response body of the previous request:

testRunner.testCase.getTestStepByName('CreateNewUser').properties.Response.value

But note that we get a String, but we need to get a Map object (JSON, if you want) to get a specific ID. To do this, use the built-in groovy.json library:

import groovy.json.JsonSlurper

id = new JsonSlurper().parseText(testRunner.testCase.getTestStepByName('CreateNewUser').properties.Response.value).id.toString()

And we pass in the "DELETE" and "PUT" requests in the ID field of type Template, which we created in advance (seen in the screenshots above):

testRunner.testCase.getTestStepByName('EditUser').setPropertyValue('ID', id)
testRunner.testCase.getTestStepByName('DeleteUser').setPropertyValue('ID', id)

And save into the context:

context.id = id
save into the context

Checking that user was created

Next, we process the request in which we verify that the user is created. In the GetUsersAfterCreate request, we can immediately proceed to the Script Assertion. Of course, we need the JsonSlurper library to convert String to List of Maps:

import groovy.json.JsonSlurper

Check the status code:

assert messageExchange.responseStatusCode == 200

Parse JSON and check that there are more users:

json = new JsonSlurper()
users = json.parseText(context.getUsersInitial)
newUsers = json.parseText(messageExchange.responseContent)
assert newUsers.size() > users.size(),

Now we'll check that our user is in the new list of users:

userExists = false
newUsers.each {
	if (it.id.toString() == context.id) {
		if (it.name == context.userName && it.phone == context.userPhone) {
			userExists = true
		}		
	}
}
assert userExists

This Script Assertion is done:

Script Assertion is done

Generating new data

Next, we create a new Groovy Script, generate new data for editing and transfer it:

context.userName = UUID.randomUUID().toString()
context.userPhone = System.currentTimeMillis().toString()

testRunner.testCase.getTestStepByName('EditUser').setPropertyValue('userName', context.userName)
testRunner.testCase.getTestStepByName('EditUser').setPropertyValue('userPhone', context.userPhone)

Edit user with PUT /api/users/ID

Let's edit the EditUser step:

EditUser step

And add into this step Script Assertion:

assert messageExchange.responseStatusCode == 204
add into this step Script Assertion

Checking that the user was edited

Add Script Assertion in GetUsersAfterEdit request:

import groovy.json.JsonSlurper

assert messageExchange.responseStatusCode == 200
json = new JsonSlurper()
users = json.parseText(messageExchange.responseContent)
userExists = false
users.each {
	if (it.id.toString() == context.id) {
		if (it.name == context.userName && it.phone == context.userPhone) {
			userExists = true
		}		
	}
}
assert userExists
Add Script Assertion in GetUsersAfterEdit request

Removing the user

Add Script Assertion in DeleteUser request:

assert messageExchange.responseStatusCode == 204
Removing the user

Checking that the user was removed

Finally, add Script Assertion to the last request to verify that the user has been deleted:

import groovy.json.JsonSlurper

assert messageExchange.responseStatusCode == 200
json = new JsonSlurper()
users = json.parseText(messageExchange.responseContent)
userExists = true
users.each {
	if (it.id.toString() == context.id) {
		userExists = false
	}
}
assert userExists
Checking that the user was removed

Results

Now we can complete the entire test:

Results

Conclusion

SoapUI is a powerful GUI tool where you can create API tests. If the functionality of the open-source version is not enough, then we can always use Groovy scripts. The main thing in the scripts used is the "context" variable through which we can exchange data between test steps, Groovy Scripts and Script Assertions. Also in Groovy Script we use the "testRunner" variable to access other test objects, and in Script Assertion we use "messageExchane" to access the contents of the current test step.

avatar
QA TL