SoapUI - разработка библиотеки для чайников
Понадобилось мне тут опять покопаться в SoapUI. Ситуация нынче напряженная, тестировщики все в бегах, так что приходится браться за лопату техническому писателю. Бесплатная версия SoapUI и так много чего умеет, однако не хватает ей одной важной фичи - создание собственных “библиотек” скриптов. Платная версия позволяет сохранять часто-используемые скрипты в папочку в виде “классов”, а затем вызывать в их в практически в любых скриптах.
В этой статье я уже писала про приключения в SoapUI для начинающих. Скрипты это хорошо, но что делать, если какие-то конструкции нужно использовать вот прям постоянно и писать одно и то же достало? Можно вынести часть часто используемых скриптов в библиотеку и вызывать нужные методы, когда они понадобятся. SoapUI Pro поддерживает такую фичу из коробки, прямо из интерфейса пользователя, но пользователям SoapUI Opensource придется идти путем просветления:
- написать скрипты и скомпилировать их в jar,
- а затем скопировать в папку
<SoapUI %INSTALLDIR%>/bin/ext
.
Есть ещё способ импортирования скриптов и общего проекта, но этот способ уж слишком костыльный даже для меня.
Подготовка
Нам понадобятся:
- среда разработки (например, Idea Intellij, хватит community версии);
- Groovy (распаковать, добавить в переменные окружения своей ОС);
- gradle, который нам поможет все собрать в .jar файл;
- некоторый опыт в разработке скриптов и навыки гуглирования… гугления?
Установите Idea, установите Gradle (загрузить и распаковать) и добавьте gradle в переменные окружения (вот тут написано как. В Idea в Settings > Build, Execution, Deployment > Build Tools > … убедиться, что путь к gradle подцепился).
Создать в Idea новый проект. В процессе создания выбрать Gradle и указать artifact id
например soapui.library
(groupid
можно оставить пустым). Gradle создаст структуру папок и выполнит начальную настройку. Вот такая структура папок, например, вышла у меня:
Чтобы использовать некоторые классы SoapUI (например для установки свойств тест-кейса) нужно импортировать библиотеку SoapUI. Ее можно скопировать прямо из установленного %installdir%SoapUi/bin/
, файл soapui-5.5.0.jar
(версия может отличаться) , скопировать в папку /libs
в директории проекта (создать папку). Чтобы подключить библиотеку нужно в файл build.gradle
в корне проекта отредактировать раздел dependencies
, а также добавить информацию о .jar. Вот так получилось у меня:
plugins {
id 'groovy'
id 'java'
}
version '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'SoapUI Sample Groovy Library'
}
}
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
compile group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '3.1.0'
compile fileTree(dir: 'libs', include: '*.jar')
testCompile group:'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.3'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
Как видно, тут я включила еще парочку подозрительных библиотек. Библиотека xmlbeans нужна SoapUI для работы с XML, а библиотеку Spock (org.spockframework) можно использовать для тестирования скриптов.
Классы объединим в package ru.company.soapui
(где company – название компании, в моем случае). Это нужно для того, чтобы в SoapUI импортировать скрипты из библиотеки, вот так, например: import ru.inforion.soapui.*
, ну и чтобы с другими пакетами, коих тысячи, не пересекались названия методов и классов.
Кодим!
В папке /main/groovy
создадим package
(правой кнопкой - package) и обозвать его, например, ru.inforion.soapui
. Кликнуть ПКМ по package и создать Groovy Class. Idea очень умная, так что она сразу создаст каркас для класса, осталось только вставить методы. Можно создавать несколько классов для скриптов разного назначения, а можно запихать все в один, но есть пара нюансов.
В SoapUI для выполнения скриптов используются:
testRunner
– в Test Step;messageExchange
– в Script Assertion (например, при разборе ответа от сервиса).
Сравните, например, установку свойств в Test Step и Script Assertion:
testRunner.testCase.testSuite.project.setPropertyValue( "projectProperty" ,"Значение свойства")
messageExchange.modelItem.testStep.testCase.testSuite.project.setPropertyValue( "projectProperty" ,"Значение свойства")
Чтобы запускать один и тот же скрипт в разных контекстах, нужно будет немножко извернуться.
Например:
package ru.inforion.soapui
public class Utils {
// этот блок обязателен, чтобы скрипт выполнился в SoapUI
def context
def log
def runner
def sortString(String input) {
char[] charArray = input.replaceAll("[^а-яА-Яa-zA-Z0-9 ]+","").toCharArray()
Arrays.sort(charArray)
String sortedString = new String(charArray)
return sortedString.trim()
}
}
Этот класс можно сразу скомпилировать и протестировать. Для этого в окне Idea справа (такая маленькая вертикальная панелька) раскрыть панель Gradle, раскрыть Tasks/build и дважды кликнуть jar. Проект скомпилируется, готовый .jar
будет в папке проекта в директории /build/libs
(по умолчанию). Этот .jar
необходимо скопировать в папку C:\Program Files (x86)\SmartBear\SoapUI-x.x.x\bin\ext
и перезапустить SoapUI.
В Groovy Script вызывать класс и метод нужно вот так:
import ru.inforion.soapui.*
def myClass = new Utils() //в данном случае нам не нужен ни testRunner, ни messageExchange, так что ничего в скобках не указываем
log.info (myClass.sortString("Ура работает!"))
Для того чтобы использовать объекты SoapUI, например устанавливать свойства тест-кейса или работать с XML ответом от сервиса, нужно указать контекст. Например, метод для сериализации строки в base64 и сохранения результата в свойство тест-кейса, который можно запускать и из Test Step, и из Script Assertion:
package ru.inforion.soapui
class Utils {
def context
def log
def testRunner
/**
* Переводит в base64 строку и сохраняет в указанное свойство Тест-кейса.*
* Метод работает и в тест-степе, и в Script Assertion
*
* @param prop Имя свойства для сохранения base64.
* @param input Строка (строки) для кодирования.
*/
def base64This(String prop, String input) {
String encoded = input.getBytes( 'UTF-8' ).encodeBase64()
//проверяем, если скрипт запущен из Test Step, то используем конструкцию с testRunner
if (runner.getClass().getSimpleName() == "MockTestRunner") {
runner.testCase.setPropertyValue("${prop}",encoded)
}
//или messageExchange для ScriptAssertion
else {
runner.modelItem.testStep.testCase.setPropertyValue("$prop",encoded)
}
}
Вызвать этот класс и метод можно вот так: Из Test Step:
import ru.inforion.soapui.*
//для runner указываем testRunner
def anotherClass = newUtils(context: context, log: log, runner: testRunner)
anotherClass.base64This("Property","Blabla")
Из Script Assertion:
import ru.inforion.soapui.*
//для runner указываем messageExchange
def anotherClass = newUtils(context: context, log: log, runner: messageExchange)
anotherClass.base64This("Property","Blabla")
Можно (ладно, нужно, чтобы на вас коллеги-разработчики не смотрели косо) добавить обработку ошибок. Например, ниже метод для сортировки символов строки, в котором ловится ошибка, если не указана строка для сортировки (больше примеров с try-catch тут).
def sortString(String input) {
try {
char[] charArray = input.replaceAll("[^а-яА-Яa-zA-Z0-9 ]+","").toCharArray()
Arrays.sort(charArray)
String sortedString = new String(charArray).trim()
return sortedString.trim()
}
catch (NullPointerException e) {
log.error (" Не указана строка для сортировки ", e)
assert false //кидаем ошибку в soap. Если эта ошибка поймана, тест можо остановить
}
}
Блок try защищает от ошибок код внутри { }
. Также можно отловить все Exception без указания конкретного (catch (Exception e) {log.error (e)}
), но это считается плохой практикой.
Тестирование
Часть методов можно проверить прямо в Idea. Idea уже создала папку /test
(рядом с /main
), в которой можно создать класс, например UtilsTest, для тестирования. Для тестирования groovy проще всего использовать фреймворк Spock.
Например, класс и метод для тестирования sortString из примера выше:
import spock.lang.Specification
import ru.inforion.soapui.*
class UtilsTest extends Specification {
def tc = new Utils()
def "String sorting"() {
given:
String str = tc.sortString("Некоторая строчка из different 4562 символов")
expect:
str == "2456deeffinrtНааввезиикклмоооооррссттчя"
}
}
Spock хорош тем, что в нем все наглядно. Given - дано, expect - ожидаемый результат. Можно сразу запустить тест (зеленой кнопочкой слева от кода).